Skip to content

commit f573f12

abduznik edited this page May 23, 2026 · 1 revision

feat(linux): implement EmuDeck integration and Linux emulator support

Commit: f573f12708ef95f5de74ab43bed8238eba5850d8

Author: Yan

Date: 2026-04-11

Why: Adds a new feature or capability to the application.

Files Changed

lib/core/emulator/emulator_download_service.dart   | 12 +++
 lib/core/emulator/emulator_registry_data.dart      | 34 +++++---
 lib/core/emulator/strategies/azahar_strategy.dart  |  2 +-
 lib/core/emulator/strategies/cemu_strategy.dart    |  2 +-
 lib/core/emulator/strategies/dolphin_strategy.dart |  2 +-
 .../emulator/strategies/duckstation_strategy.dart  |  2 +-
 lib/core/emulator/strategies/flycast_strategy.dart |  2 +-
 lib/core/emulator/strategies/pcsx2_strategy.dart   |  2 +-
 lib/core/emulator/strategies/rpcs3_strategy.dart   |  2 +-
 lib/core/emulator/strategies/xemu_strategy.dart    |  2 +-
 lib/core/save/strategies/azahar_save_strategy.dart |  6 +-
 lib/core/save/strategies/cemu_save_strategy.dart   | 10 +--
 .../save/strategies/dolphin_save_strategy.dart     |  6 +-
 .../save/strategies/duckstation_save_strategy.dart | 10 +--
 lib/core/save/strategies/eden_save_strategy.dart   |  8 +-
 lib/core/save/strategies/ppsspp_save_strategy.dart | 10 +--
 lib/core/save/strategies/rpcs3_save_strategy.dart  | 10 +--
 lib/core/storage/directory_service.dart            | 58 +++++++++++--
 lib/ui/screens/settings_screen.dart                | 49 +++++++++++
 test/unit/firmware_service_test.mocks.dart         | 94 +++++++++++++++++++---
 test/unit/save_sync_service_test.mocks.dart        | 94 +++++++++++++++++++---
 test/unit/strategy_registry_test.mocks.dart        | 94 +++++++++++++++++++---
 test/widgets/library_screen_test.mocks.dart        | 94 +++++++++++++++++++---
 test/widgets/settings_screen_test.mocks.dart       | 94 +++++++++++++++++++---
 24 files changed, 590 insertions(+), 109 deletions(-)
  • lib/core/emulator/emulator_download_service.dart
  • lib/core/emulator/emulator_registry_data.dart
  • lib/core/emulator/strategies/azahar_strategy.dart
  • lib/core/emulator/strategies/cemu_strategy.dart
  • lib/core/emulator/strategies/dolphin_strategy.dart
  • lib/core/emulator/strategies/duckstation_strategy.dart
  • lib/core/emulator/strategies/flycast_strategy.dart
  • lib/core/emulator/strategies/pcsx2_strategy.dart
  • lib/core/emulator/strategies/rpcs3_strategy.dart
  • lib/core/emulator/strategies/xemu_strategy.dart
  • lib/core/save/strategies/azahar_save_strategy.dart
  • lib/core/save/strategies/cemu_save_strategy.dart
  • lib/core/save/strategies/dolphin_save_strategy.dart
  • lib/core/save/strategies/duckstation_save_strategy.dart
  • lib/core/save/strategies/eden_save_strategy.dart
  • lib/core/save/strategies/ppsspp_save_strategy.dart
  • lib/core/save/strategies/rpcs3_save_strategy.dart
  • lib/core/storage/directory_service.dart
  • lib/ui/screens/settings_screen.dart
  • test/unit/firmware_service_test.mocks.dart
  • test/unit/save_sync_service_test.mocks.dart
  • test/unit/strategy_registry_test.mocks.dart
  • test/widgets/library_screen_test.mocks.dart
  • test/widgets/settings_screen_test.mocks.dart

Diff

diff --git a/lib/core/emulator/emulator_download_service.dart b/lib/core/emulator/emulator_download_service.dart
index 99128c6..1a4d489 100644
--- a/lib/core/emulator/emulator_download_service.dart
+++ b/lib/core/emulator/emulator_download_service.dart
@@ -178,6 +178,18 @@ class EmulatorDownloadService {
             status: 'Extracting...',
           ));
           await _extractionService.extract(tempFilePath, emulatorDir);
+
+          // Linux specific: ensure binary is executable
+          if (Platform.isLinux) {
+            final exeName = definition['linux_executable'] as String?;
+            if (exeName != null) {
+              final exePath = await _directoryService.findEmulatorExecutable(emulatorId, exeName);
+              if (exePath != null) {
+                await Process.run('chmod', ['+x', exePath]);
+              }
+            }
+          }
+
           controller.add(DownloadProgress(
             id: emulatorId,
             gameName: emulatorName,
diff --git a/lib/core/emulator/emulator_registry_data.dart b/lib/core/emulator/emulator_registry_data.dart
index 112a55b..569857b 100644
--- a/lib/core/emulator/emulator_registry_data.dart
+++ b/lib/core/emulator/emulator_registry_data.dart
@@ -20,10 +20,14 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
   {
     'id': 'dolphin',
     'name': 'Dolphin',
-    'type': 'direct',
+    'type': 'github',
+    'github_repo': 'dolphin-emu/dolphin',
+    'github_asset_required_windows': ['x64', '.7z'],
+    'github_asset_required_linux': ['x86_64', '.AppImage'],
+    'github_asset_excluded': ['debug', 'symbols'],
     'windows_url': 'https://dl.dolphin-emu.org/builds/dolphin-master-latest-x64.7z',
     'windows_executable': 'Dolphin.exe',
-    'linux_executable': 'dolphin-emu',
+    'linux_executable': 'Dolphin.AppImage',
     'macos_url': 'https://dl.dolphin-emu.org/releases/2603a/dolphin-2603a-universal.dmg',
     'macos_executable': 'Dolphin.app/Contents/MacOS/Dolphin',
     'platform_slugs': ['gc', 'gamecube', 'wii', 'ngc'],
@@ -35,6 +39,7 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'type': 'direct',
     'windows_url': 'https://git.eden-emu.dev/eden-emu/eden/-/releases/permalink/latest/downloads/eden-windows-msvc-install.zip',
     'windows_executable': 'eden.exe',
+    'linux_url': 'https://git.eden-emu.dev/eden-emu/eden/-/releases/permalink/latest/downloads/eden-linux-x86_64.tar.gz',
     'linux_executable': 'eden',
     'macos_url': 'https://git.eden-emu.dev/eden-emu/eden/releases/download/v0.2.0-rc2/Eden-macOS-v0.2.0-rc2.tar.gz',
     'macos_executable': 'Eden.app/Contents/MacOS/Eden',
@@ -49,9 +54,10 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo_macos': 'RPCS3/rpcs3-binaries-mac-arm64',
     'github_asset_required': ['win64'],
     'github_asset_required_macos': ['macos', 'aarch64', '.7z'],
+    'github_asset_required_linux': ['linux', 'x86_64', '.AppImage'],
     'github_asset_excluded': ['debug'],
     'windows_executable': 'rpcs3.exe',
-    'linux_executable': 'rpcs3',
+    'linux_executable': 'rpcs3.AppImage',
     'macos_executable': 'RPCS3.app/Contents/MacOS/RPCS3',
     'platform_slugs': ['ps3', 'playstation-3', 'playstation3'],
     'supported_platforms': ['windows', 'linux', 'macos'],
@@ -63,10 +69,11 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo': 'PCSX2/pcsx2',
     'github_asset_required': ['windows', 'Qt'],
     'github_asset_required_macos': ['macos', 'Qt'],
+    'github_asset_required_linux': ['linux', 'x86_64', '.AppImage'],
     'github_asset_excluded': ['debug', 'sse4'],
     'github_asset_excluded_windows': ['arm64'],
     'windows_executable': 'pcsx2-qt.exe',
-    'linux_executable': 'pcsx2-qt',
+    'linux_executable': 'pcsx2-qt.AppImage',
     'macos_executable': 'PCSX2.app/Contents/MacOS/PCSX2',
     'platform_slugs': ['ps2', 'playstation-2', 'playstation2'],
     'supported_platforms': ['windows', 'linux', 'macos'],
@@ -78,10 +85,11 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo': 'azahar-emu/azahar',
     'github_asset_required_windows': ['windows', 'msys2'],
     'github_asset_required_macos': ['macos', 'arm64'],
+    'github_asset_required_linux': ['linux', 'x86_64', '.AppImage'],
     'github_asset_excluded_windows': ['debug', 'appimage'],
     'github_asset_excluded_macos': ['debug', 'libretro'],
     'windows_executable': 'azahar.exe',
-    'linux_executable': 'azahar',
+    'linux_executable': 'azahar.AppImage',
     'macos_executable': 'Azahar.app/Contents/MacOS/Azahar',
     'platform_slugs': ['3ds', 'n3ds', 'nintendo-3ds', 'nintendo3ds', 'new-nintendo-3ds', 'new-nintendo-3ds-xl'],
     'supported_platforms': ['windows', 'linux', 'macos'],
@@ -93,11 +101,12 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo': 'cemu-project/Cemu',
     'github_asset_required': ['windows', 'x64', '.zip'],
     'github_asset_required_macos': ['macos', '.dmg'],
+    'github_asset_required_linux': ['linux', 'x86_64', '.AppImage'],
     'github_asset_excluded': ['debug', 'symbols'],
     'github_asset_excluded_windows': ['linux', 'macos'],
     'github_asset_excluded_macos': ['windows', 'linux'],
     'windows_executable': 'Cemu.exe',
-    'linux_executable': 'cemu',
+    'linux_executable': 'Cemu.AppImage',
     'macos_executable': 'Cemu.app/Contents/MacOS/Cemu',
     'platform_slugs': ['wiiu', 'wii-u', 'nintendo-wii-u', 'nintendo-wiiu'],
     'supported_platforms': ['windows', 'linux', 'macos'],
@@ -109,14 +118,15 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo': 'xemu-project/xemu',
     'github_asset_required': ['win', 'x86_64', 'release'],
     'github_asset_required_macos': ['macos', 'release'],
+    'github_asset_required_linux': ['linux', 'x86_64', '.AppImage'],
     'github_asset_excluded': ['dbg', 'pdb', 'arm', 'appimage', 'tar'],
     'github_asset_excluded_windows': ['macos'],
     'github_asset_excluded_macos': ['win'],
     'windows_executable': 'xemu.exe',
-    'linux_executable': 'xemu',
+    'linux_executable': 'xemu.AppImage',
     'macos_executable': 'Xemu.app/Contents/MacOS/xemu',
     'platform_slugs': ['xbox'],
-    'supported_platforms': ['windows', 'macos'],
+    'supported_platforms': ['windows', 'macos', 'linux'],
   },
   {
     'id': 'xenia_canary',
@@ -137,9 +147,10 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo': 'stenzek/duckstation',
     'github_asset_required': ['windows', 'x64'],
     'github_asset_required_macos': ['mac', 'release'],
+    'github_asset_required_linux': ['x64', '.AppImage'],
     'github_asset_excluded': ['nogui', 'debug', 'arm64'],
     'windows_executable': 'duckstation-qt-x64-ReleaseLTCG.exe',
-    'linux_executable': 'duckstation-qt',
+    'linux_executable': 'DuckStation.AppImage',
     'macos_executable': 'DuckStation.app/Contents/MacOS/DuckStation',
     'platform_slugs': ['ps1', 'playstation', 'psx'],
     'supported_platforms': ['windows', 'linux', 'macos'],
@@ -151,11 +162,12 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo': 'flyinghead/flycast',
     'github_asset_required': ['win64', '.zip'],
     'github_asset_required_macos': ['macOS', '.zip'],
+    'github_asset_required_linux': ['linux', 'x86_64', '.AppImage'],
     'github_asset_excluded': ['debug', 'symbols'],
     'github_asset_excluded_windows': ['linux', 'macos'],
     'github_asset_excluded_macos': ['windows', 'linux'],
     'windows_executable': 'flycast.exe',
-    'linux_executable': 'flycast',
+    'linux_executable': 'flycast.AppImage',
     'macos_executable': 'Flycast.app/Contents/MacOS/Flycast',
     'platform_slugs': ['dc', 'dreamcast', 'naomi', 'naomi2', 'atomiswave', 'cave', 'hikaru'],
     'supported_platforms': ['windows', 'linux', 'macos'],
@@ -167,6 +179,7 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo': 'melonDS-emu/melonDS',
     'github_asset_required': ['win', '.zip'],
     'github_asset_required_macos': ['macos', '.zip'],
+    'github_asset_required_linux': ['linux', 'x64', '.tar.gz'],
     'github_asset_excluded': ['source', 'debug'],
     'github_asset_excluded_macos': ['libretro'],
     'windows_executable': 'melonDS.exe',
@@ -196,6 +209,7 @@ const List<Map<String, dynamic>> kEmulatorDefinitions = [
     'github_repo': 'mgba-emu/mgba',
     'github_asset_required': ['win64', '.7z'],
     'github_asset_required_macos': ['macos', '.dmg'],
+    'github_asset_required_linux': ['x86_64', '.tar.xz'],
     'github_asset_excluded': ['debug', 'symbols', 'source'],
     'windows_executable': 'mGBA.exe',
     'linux_executable': 'mgba',
diff --git a/lib/core/emulator/strategies/azahar_strategy.dart b/lib/core/emulator/strategies/azahar_strategy.dart
index 638fe05..2ae7e99 100644
--- a/lib/core/emulator/strategies/azahar_strategy.dart
+++ b/lib/core/emulator/strategies/azahar_strategy.dart
@@ -27,7 +27,7 @@ class AzaharStrategy extends EmulatorStrategy {
   String get windowsExecutable => 'azahar.exe';
 
   @override
-  String get linuxExecutable => 'azahar';
+  String get linuxExecutable => 'azahar.AppImage';
 
   @override
   String get macosExecutable => 'Azahar.app/Contents/MacOS/azahar';
diff --git a/lib/core/emulator/strategies/cemu_strategy.dart b/lib/core/emulator/strategies/cemu_strategy.dart
index 338226f..5afc0e7 100644
--- a/lib/core/emulator/strategies/cemu_strategy.dart
+++ b/lib/core/emulator/strategies/cemu_strategy.dart
@@ -22,7 +22,7 @@ class CemuStrategy extends EmulatorStrategy {
   String get windowsExecutable => 'Cemu.exe';
 
   @override
-  String get linuxExecutable => 'cemu';
+  String get linuxExecutable => 'Cemu.AppImage';
 
   @override
   String get macosExecutable => 'Cemu.app/Contents/MacOS/Cemu';
diff --git a/lib/core/emulator/strategies/dolphin_strategy.dart b/lib/core/emulator/strategies/dolphin_strategy.dart
index 8cb3155..8dc4b87 100644
--- a/lib/core/emulator/strategies/dolphin_strategy.dart
+++ b/lib/core/emulator/strategies/dolphin_strategy.dart
@@ -22,7 +22,7 @@ class DolphinStrategy extends EmulatorStrategy {
   String get windowsExecutable => 'Dolphin.exe';
 
   @override
-  String get linuxExecutable => 'dolphin-emu';
+  String get linuxExecutable => 'Dolphin.AppImage';
 
   @override
   String get macosExecutable => 'Dolphin.app/Contents/MacOS/Dolphin';
diff --git a/lib/core/emulator/strategies/duckstation_strategy.dart b/lib/core/emulator/strategies/duckstation_strategy.dart
index 75b40e8..d96bcc4 100644
--- a/lib/core/emulator/strategies/duckstation_strategy.dart
+++ b/lib/core/emulator/strategies/duckstation_strategy.dart
@@ -22,7 +22,7 @@ class DuckstationStrategy extends EmulatorStrategy {
   String get windowsExecutable => 'duckstation-qt-x64-ReleaseLTCG.exe';
 
   @override
-  String get linuxExecutable => 'duckstation-qt';
+  String get linuxExecutable => 'DuckStation.AppImage';
 
   @override
   String get macosExecutable => 'DuckStation.app/Contents/MacOS/DuckStation';
diff --git a/lib/core/emulator/strategies/flycast_strategy.dart b/lib/core/emulator/strategies/flycast_strategy.dart
index 1d897f4..1014266 100644
--- a/lib/core/emulator/strategies/flycast_strategy.dart
+++ b/lib/core/emulator/strategies/flycast_strategy.dart
@@ -22,7 +22,7 @@ class FlycastStrategy extends EmulatorStrategy {
   String get windowsExecutable => 'flycast.exe';
 
   @override
-  String get linuxExecutable => 'flycast';
+  String get linuxExecutable => 'flycast.AppImage';
 
   @override
   String get macosExecutable => 'Flycast.app/Contents/MacOS/Flycast';
diff --git a/lib/core/emulator/strategies/pcsx2_strategy.dart b/lib/core/emulator/strategies/pcsx2_strategy.dart
index 4004312..f429e8b 100644
--- a/lib/core/emulator/strategies/pcsx2_strategy.dart
+++ b/lib/core/emulator/strategies/pcsx2_strategy.dart
@@ -22,7 +22,7 @@ class Pcsx2Strategy extends EmulatorStrategy {
   String get windowsExecutable => 'pcsx2-qt.exe';
 
   @override
-  String get linuxExecutable => 'pcsx2-qt';
+  String get linuxExecutable => 'pcsx2-qt.AppImage';
 
   @override
   String get macosExecutable => 'PCSX2.app/Contents/MacOS/PCSX2';
diff --git a/lib/core/emulator/strategies/rpcs3_strategy.dart b/lib/core/emulator/strategies/rpcs3_strategy.dart
index 99a4764..2908c77 100644
--- a/lib/core/emulator/strategies/rpcs3_strategy.dart
+++ b/lib/core/emulator/strategies/rpcs3_strategy.dart
@@ -23,7 +23,7 @@ class Rpcs3Strategy extends EmulatorStrategy {
   String get windowsExecutable => 'rpcs3.exe';
 
   @override
-  String get linuxExecutable => 'rpcs3';
+  String get linuxExecutable => 'rpcs3.AppImage';
 
   @override
   String get macosExecutable => 'RPCS3.app/Contents/MacOS/RPCS3';
diff --git a/lib/core/emulator/strategies/xemu_strategy.dart b/lib/core/emulator/strategies/xemu_strategy.dart
index 4e09a52..17c6004 100644
--- a/lib/core/emulator/strategies/xemu_strategy.dart
+++ b/lib/core/emulator/strategies/xemu_strategy.dart
@@ -21,7 +21,7 @@ class XemuStrategy extends EmulatorStrategy {
   String get windowsExecutable => 'xemu.exe';
 
   @override
-  String get linuxExecutable => 'xemu';
+  String get linuxExecutable => 'xemu.AppImage';
 
   @override
   bool get supportsSaveSync => false;
diff --git a/lib/core/save/strategies/azahar_save_strategy.dart b/lib/core/save/strategies/azahar_save_strategy.dart
index 6b97d24..24c23f9 100644
--- a/lib/core/save/strategies/azahar_save_strategy.dart
+++ b/lib/core/save/strategies/azahar_save_strategy.dart
@@ -32,8 +32,8 @@ class AzaharSaveStrategy extends SaveStrategy {
     _manualMapping = mapping;
   }
 
-  Future<String> _getAzaharSystemBase() async {
-    final resolvedPath = await _directoryService.getEmulatorSystemDirectory('azahar');
+  Future<String> _getAzaharSystemBase({String? platformSlug}) async {
+    final resolvedPath = await _directoryService.getEmulatorSystemDirectory('azahar', platformSlug: platformSlug);
     if (!await io.Directory(resolvedPath).exists()) {
       throw Exception('Save directory not found for Azahar at $resolvedPath. Please launch Azahar at least once to generate save data.');
     }
@@ -49,7 +49,7 @@ class AzaharSaveStrategy extends SaveStrategy {
           'Please select the save folder manually from the sdmc directory.');
     }
 
-    final base = await _getAzaharSystemBase();
+    final base = await _getAzaharSystemBase(platformSlug: game.platformSlug);
 
     // _manualMapping is expected to be the relative path from sdmc
     final finalPath = p.join(base, 'sdmc', _manualMapping!);
diff --git a/lib/core/save/strategies/cemu_save_strategy.dart b/lib/core/save/strategies/cemu_save_strategy.dart
index 34cc200..2e80981 100644
--- a/lib/core/save/strategies/cemu_save_strategy.dart
+++ b/lib/core/save/strategies/cemu_save_strategy.dart
@@ -15,7 +15,7 @@ class CemuSaveStrategy extends SaveStrategy {
   @override
   String get strategyId => 'cemu';
 
-  Future<String> _getSaveRoot() async {
+  Future<String> _getSaveRoot({String? platformSlug}) async {
     // 1. Check emulator-relative path first (e.g. for Windows portable)
     final emuDir = await _directoryService.getEmulatorDirectory('cemu');
     final portableRoot = p.join(emuDir, 'mlc01', 'usr', 'save');
@@ -24,7 +24,7 @@ class CemuSaveStrategy extends SaveStrategy {
     }
 
     // 2. Dynamic path resolution for macOS/Windows/Linux
-    final baseDir = await _directoryService.getEmulatorAppSupportDirectory('Cemu');
+    final baseDir = await _directoryService.getEmulatorAppSupportDirectory('Cemu', platformSlug: platformSlug);
     // On macOS, Cemu's save structure might be different in Application Support,
     // but typically it mirrors the internal folder structure if using the same mlc01 logic.
     // Actually, Cemu on macOS often puts mlc01 directly in Application Support/Cemu
@@ -38,13 +38,13 @@ class CemuSaveStrategy extends SaveStrategy {
 
   @override
   Future<String?> getSaveDir(Game game, String romPath) async {
-    return await _getSaveRoot();
+    return await _getSaveRoot(platformSlug: game.platformSlug);
   }
 
   @override
   Future<List<io.File>> getSaveFiles(Game game, String romPath,
       {DateTime? sessionStart, String syncMode = 'both'}) async {
-    final saveRoot = await _getSaveRoot();
+    final saveRoot = await _getSaveRoot(platformSlug: game.platformSlug);
     final saveBase = io.Directory(p.join(saveRoot, '00050000'));
     if (!await saveBase.exists()) return [];
     return [io.File(saveBase.path)]; // Return the directory as a single item
@@ -53,7 +53,7 @@ class CemuSaveStrategy extends SaveStrategy {
   @override
   Future<bool> restoreSave(Game game, String destPath, Uint8List data, String filename) async {
     try {
-      final saveRoot = await _getSaveRoot();
+      final saveRoot = await _getSaveRoot(platformSlug: game.platformSlug);
       await io.Directory(saveRoot).create(recursive: true);
       if (filename.toLowerCase().endsWith('.zip')) {
         final archive = ZipDecoder().decodeBytes(data);
diff --git a/lib/core/save/strategies/dolphin_save_strategy.dart b/lib/core/save/strategies/dolphin_save_strategy.dart
index df8c007..f9ac6ab 100644
--- a/lib/core/save/strategies/dolphin_save_strategy.dart
+++ b/lib/core/save/strategies/dolphin_save_strategy.dart
@@ -19,7 +19,7 @@ class DolphinSaveStrategy extends SaveStrategy {
   String get strategyId => 'dolphin';
 
   /// Returns the base user directory for Dolphin.
-  Future<String> _getUserDir() async {
+  Future<String> _getUserDir({String? platformSlug}) async {
     // 1. Check portable mode first — User folder next to exe
     final exePath = await _directoryService.findEmulatorExecutable(
         'dolphin', 'Dolphin.exe');
@@ -35,7 +35,7 @@ class DolphinSaveStrategy extends SaveStrategy {
     }
 
     // 2. Fall back to app support directory
-    final resolvedPath = await _directoryService.getEmulatorAppSupportDirectory('Dolphin');
+    final resolvedPath = await _directoryService.getEmulatorAppSupportDirectory('Dolphin', platformSlug: platformSlug);
     if (!await io.Directory(resolvedPath).exists()) {
       throw Exception('Save directory not found for Dolphin at $resolvedPath. Please launch Dolphin at least once to generate save data.');
     }
@@ -72,7 +72,7 @@ class DolphinSaveStrategy extends SaveStrategy {
 
   @override
   Future<String?> getSaveDir(Game game, String romPath) async {
-    final userDir = await _getUserDir();
+    final userDir = await _getUserDir(platformSlug: game.platformSlug);
 
     final isWii = game.platformSlug?.toLowerCase() == 'wii';
 
diff --git a/lib/core/save/strategies/duckstation_save_strategy.dart b/lib/core/save/strategies/duckstation_save_strategy.dart
index 8bd3665..4cfc93d 100644
--- a/lib/core/save/strategies/duckstation_save_strategy.dart
+++ b/lib/core/save/strategies/duckstation_save_strategy.dart
@@ -16,7 +16,7 @@ class DuckstationSaveStrategy extends SaveStrategy {
   @override
   String get strategyId => 'duckstation';
 
-  Future<String> _getBaseDir() async {
+  Future<String> _getBaseDir({String? platformSlug}) async {
     // 1. Check portable mode first (Windows)
     final exePath = await _directoryService.findEmulatorExecutable(
         'duckstation', 'duckstation-qt-x64-ReleaseLTCG.exe');
@@ -33,7 +33,7 @@ class DuckstationSaveStrategy extends SaveStrategy {
       final localAppData = io.Platform.environment['LOCALAPPDATA'] ?? '';
       resolvedPath = p.join(localAppData, 'DuckStation');
     } else {
-      resolvedPath = await _directoryService.getEmulatorAppSupportDirectory('DuckStation');
+      resolvedPath = await _directoryService.getEmulatorAppSupportDirectory('DuckStation', platformSlug: platformSlug);
     }
 
     if (!await io.Directory(resolvedPath).exists()) {
@@ -44,14 +44,14 @@ class DuckstationSaveStrategy extends SaveStrategy {
 
   @override
   Future<String?> getSaveDir(Game game, String romPath) async {
-    final baseDir = await _getBaseDir();
+    final baseDir = await _getBaseDir(platformSlug: game.platformSlug);
     return p.join(baseDir, 'memcards');
   }
 
   @override
   Future<List<File>> getSaveFiles(Game game, String romPath,
       {DateTime? sessionStart, String syncMode = 'both'}) async {
-    final baseDir = await _getBaseDir();
+    final baseDir = await _getBaseDir(platformSlug: game.platformSlug);
 
     final result = <File>[];
     final stem = getRomStem(game);
@@ -91,7 +91,7 @@ class DuckstationSaveStrategy extends SaveStrategy {
   Future<bool> restoreSave(
       Game game, String destPath, Uint8List data, String filename) async {
     try {
-      final baseDir = await _getBaseDir();
+      final baseDir = await _getBaseDir(platformSlug: game.platformSlug);
 
       if (filename.toLowerCase().endsWith('.zip')) {
         final archive = ZipDecoder().decodeBytes(data);
diff --git a/lib/core/save/strategies/eden_save_strategy.dart b/lib/core/save/strategies/eden_save_strategy.dart
index b29e3aa..b12c868 100644
--- a/lib/core/save/strategies/eden_save_strategy.dart
+++ b/lib/core/save/strategies/eden_save_strategy.dart
@@ -441,10 +441,10 @@ class EdenSaveStrategy extends SaveStrategy {
   //  Platform-specific save base path
   // ═══════════════════════════════════════════════════════════════════════════
 
-  Future<String> _getEdenSaveBase() async {
+  Future<String> _getEdenSaveBase({String? platformSlug}) async {
     final String resolvedPath;
     if (io.Platform.isMacOS || io.Platform.isLinux) {
-      resolvedPath = await _directoryService.getEmulatorAppSupportDirectory('eden');
+      resolvedPath = await _directoryService.getEmulatorAppSupportDirectory('eden', platformSlug: platformSlug);
     } else if (io.Platform.isWindows) {
       final appData = io.Platform.environment['APPDATA'] ?? '';
       resolvedPath = p.join(appData, 'eden');
@@ -467,7 +467,7 @@ class EdenSaveStrategy extends SaveStrategy {
   Future<String?> getSaveDir(Game game, String romPath) async {
     debugPrint('=== EDEN SAVE DIR: ${game.name} ===');
 
-    final base = await _getEdenSaveBase();
+    final base = await _getEdenSaveBase(platformSlug: game.platformSlug);
 
     final profileId = await _resolveProfileId(base);
     final titleId = await _resolveTitleId(romPath, game);
@@ -547,7 +547,7 @@ class EdenSaveStrategy extends SaveStrategy {
     try {
       debugPrint('=== EDEN RESTORE: ${game.name} ===');
 
-      final base = await _getEdenSaveBase();
+      final base = await _getEdenSaveBase(platformSlug: game.platformSlug);
 
       final profileId = await _resolveProfileId(base);
 
diff --git a/lib/core/save/strategies/ppsspp_save_strategy.dart b/lib/core/save/strategies/ppsspp_save_strategy.dart
index 8d69d0c..b654712 100644
--- a/lib/core/save/strategies/ppsspp_save_strategy.dart
+++ b/lib/core/save/strategies/ppsspp_save_strategy.dart
@@ -17,7 +17,7 @@ class PpssppSaveStrategy extends SaveStrategy {
   @override
   String get strategyId => 'ppsspp';
 
-  Future<String> _getPspDir() async {
+  Future<String> _getPspDir({String? platformSlug}) async {
     // 1. Check portable mode first (Windows)
     if (io.Platform.isWindows) {
       final exePath = await _directoryService.findEmulatorExecutable(
@@ -54,7 +54,7 @@ class PpssppSaveStrategy extends SaveStrategy {
     }
 
     // 2. Dynamic path resolution
-    final baseDir = await _directoryService.getEmulatorAppSupportDirectory('ppsspp');
+    final baseDir = await _directoryService.getEmulatorAppSupportDirectory('ppsspp', platformSlug: platformSlug);
     final pspDir = p.join(baseDir, 'PSP');
 
     if (!await io.Directory(pspDir).exists()) {
@@ -124,14 +124,14 @@ class PpssppSaveStrategy extends SaveStrategy {
 
   @override
   Future<String?> getSaveDir(Game game, String romPath) async {
-    final pspDir = await _getPspDir();
+    final pspDir = await _getPspDir(platformSlug: game.platformSlug);
     return p.join(pspDir, 'SAVEDATA');
   }
 
   @override
   Future<List<File>> getSaveFiles(Game game, String romPath,
       {DateTime? sessionStart, String syncMode = 'both'}) async {
-    final pspDir = await _getPspDir();
+    final pspDir = await _getPspDir(platformSlug: game.platformSlug);
     final result = <File>[];
 
     // --- Handle SAVEDATA folders ---
@@ -215,7 +215,7 @@ class PpssppSaveStrategy extends SaveStrategy {
   Future<bool> restoreSave(
       Game game, String destPath, Uint8List data, String filename) async {
     try {
-      final pspDir = await _getPspDir();
+      final pspDir = await _getPspDir(platformSlug: game.platformSlug);
 
       if (filename.toLowerCase().endsWith('.zip')) {
         final archive = ZipDecoder().decodeBytes(data);
diff --git a/lib/core/save/strategies/rpcs3_save_strategy.dart b/lib/core/save/strategies/rpcs3_save_strategy.dart
index 34fcc63..35b91ee 100644
--- a/lib/core/save/strategies/rpcs3_save_strategy.dart
+++ b/lib/core/save/strategies/rpcs3_save_strategy.dart
@@ -83,7 +83,7 @@ class Rpcs3SaveStrategy extends SaveStrategy {
     }
   }
 
-  Future<String> _getRpcs3SaveRoot() async {
+  Future<String> _getRpcs3SaveRoot({String? platformSlug}) async {
     // 1. Check portable mode first (Windows)
     final exePath = await _directoryService.findEmulatorExecutable(
         'rpcs3', 'rpcs3.exe');
@@ -96,7 +96,7 @@ class Rpcs3SaveStrategy extends SaveStrategy {
     }
 
     // 2. Dynamic path resolution
-    final baseDir = await _directoryService.getEmulatorAppSupportDirectory('rpcs3');
+    final baseDir = await _directoryService.getEmulatorAppSupportDirectory('rpcs3', platformSlug: platformSlug);
     final resolvedPath = p.join(baseDir, 'dev_hdd0', 'home', '00000001', 'savedata');
 
     if (!await io.Directory(resolvedPath).exists()) {
@@ -297,7 +297,7 @@ class Rpcs3SaveStrategy extends SaveStrategy {
     if (_activeFolderOverride != null) {
       return _activeFolderOverride;
     }
-    final saveRoot = await _getRpcs3SaveRoot();
+    final saveRoot = await _getRpcs3SaveRoot(platformSlug: game.platformSlug);
     final dirs = await _findSaveDirs(saveRoot, game);
     return dirs.isNotEmpty ? dirs.first.path : null;
   }
@@ -305,7 +305,7 @@ class Rpcs3SaveStrategy extends SaveStrategy {
   @override
   Future<List<File>> getSaveFiles(Game game, String romPath,
       {DateTime? sessionStart, String syncMode = 'both'}) async {
-    final saveRoot = await _getRpcs3SaveRoot();
+    final saveRoot = await _getRpcs3SaveRoot(platformSlug: game.platformSlug);
 
     // Manual override — wrap single dir
     List<Directory> saveDirs;
@@ -348,7 +348,7 @@ class Rpcs3SaveStrategy extends SaveStrategy {
   Future<bool> restoreSave(
       Game game, String destPath, Uint8List data, String filename) async {
     try {
-      final saveRoot = await _getRpcs3SaveRoot();
+      final saveRoot = await _getRpcs3SaveRoot(platformSlug: game.platformSlug);
 
       if (filename.toLowerCase().endsWith('.zip')) {
         final archive = ZipDecoder().decodeBytes(data);
diff --git a/lib/core/storage/directory_service.dart b/lib/core/storage/directory_service.dart
index eb665cc..2e54154 100644
--- a/lib/core/storage/directory_service.dart
+++ b/lib/core/storage/directory_service.dart
@@ -10,6 +10,8 @@ import 'package:freegosy/core/romm/romm_models.dart';
 class DirectoryService {
   static const String _romsRootPathKey = 'romsRootPath';
   static const String _emulatorsRootPathKey = 'emulatorsRootPath';
+  static const String _linuxSyncPresetKey = 'linuxSyncPreset';
+  static const String _emudeckRootPathKey = 'emudeckRootPath';
 
   // Known extensions per platform slug
   static const Map<String, List<String>> _platformExtensions = {
@@ -37,12 +39,17 @@ class DirectoryService {
 
   late String romsRootPath;
   late String emulatorsRootPath;
+  String linuxSyncPreset = 'default';
+  String? emudeckRootPath;
   final Map<String, String> _emulatorPathOverrides = {};
 
   DirectoryService();
 
   Future<void> initialize() async {
     final prefs = await SharedPreferences.getInstance();
+    linuxSyncPreset = prefs.getString(_linuxSyncPresetKey) ?? 'default';
+    emudeckRootPath = prefs.getString(_emudeckRootPathKey);
+
     final String defaultBase;
     if (defaultTargetPlatform == TargetPlatform.macOS ||
         defaultTargetPlatform == TargetPlatform.linux) {
@@ -53,13 +60,40 @@ class DirectoryService {
       defaultBase = docsDir.path;
     }
 
-    romsRootPath = prefs.getString(_romsRootPathKey) ?? '$defaultBase/ROMs';
-    emulatorsRootPath = prefs.getString(_emulatorsRootPathKey) ?? '$defaultBase/Emulators';
+    if (defaultTargetPlatform == TargetPlatform.linux &&
+        linuxSyncPreset == 'emudeck' &&
+        emudeckRootPath != null) {
+      romsRootPath =
+          prefs.getString(_romsRootPathKey) ?? p.join(emudeckRootPath!, 'Emulation/roms');
+      emulatorsRootPath =
+          prefs.getString(_emulatorsRootPathKey) ?? p.join(emudeckRootPath!, 'Emulation/tools');
+    } else {
+      romsRootPath = prefs.getString(_romsRootPathKey) ?? '$defaultBase/ROMs';
+      emulatorsRootPath =
+          prefs.getString(_emulatorsRootPathKey) ?? '$defaultBase/Emulators';
+    }
+
     await _ensureDirectoryExists(romsRootPath);
     await _ensureDirectoryExists(emulatorsRootPath);
     await loadEmulatorPathOverrides();
   }
 
+  Future<void> setLinuxSyncPreset(String preset) async {
+    final prefs = await SharedPreferences.getInstance();
+    await prefs.setString(_linuxSyncPresetKey, preset);
+    linuxSyncPreset = preset;
+    // Re-initialize to update paths based on new preset
+    await initialize();
+  }
+
+  Future<void> setEmudeckRoot(String path) async {
+    final prefs = await SharedPreferences.getInstance();
+    await prefs.setString(_emudeckRootPathKey, path);
+    emudeckRootPath = path;
+    // Re-initialize to update paths based on new root
+    await initialize();
+  }
+
   Future<void> loadEmulatorPathOverrides() async {
     final prefs = await SharedPreferences.getInstance();
     for (final key in prefs.getKeys()) {
@@ -280,7 +314,7 @@ class DirectoryService {
     return dirPath;
   }
 
-  Future<String> getEmulatorAppSupportDirectory(String emulatorName) async {
+  Future<String> getEmulatorAppSupportDirectory(String emulatorName, {String? platformSlug}) async {
     if (io.Platform.isMacOS) {
       final appSupport = await getApplicationSupportDirectory();
       // On macOS, getApplicationSupportDirectory() returns ~/Library/Application Support/com.example.app
@@ -290,21 +324,33 @@ class DirectoryService {
       final appData = io.Platform.environment['APPDATA'] ?? '';
       return p.join(appData, emulatorName);
     } else if (io.Platform.isLinux) {
+      if (linuxSyncPreset == 'emudeck' && emudeckRootPath != null) {
+        // EmuDeck standard saves path: Emulation/saves/[emulator]/[platform]
+        // If platform is not provided, we might have to guess or return a base
+        final base = p.join(emudeckRootPath!, 'Emulation', 'saves', emulatorName.toLowerCase());
+        if (platformSlug != null) {
+          return p.join(base, platformSlug);
+        }
+        return base;
+      }
       final home = io.Platform.environment['HOME'] ?? '';
       return p.join(home, '.config', emulatorName);
     }
     throw UnsupportedError('Platform not supported for save path resolution');
   }
 
-  Future<String> getEmulatorBiosDirectory(String emulatorId) async {
+  Future<String> getEmulatorBiosDirectory(String emulatorId, {String? platformSlug}) async {
+    if (io.Platform.isLinux && linuxSyncPreset == 'emudeck' && emudeckRootPath != null) {
+      return p.join(emudeckRootPath!, 'Emulation', 'bios');
+    }
     final emuDir = await getEmulatorDirectory(emulatorId);
     final dirPath = p.join(emuDir, 'BIOS');
     await _ensureDirectoryExists(dirPath);
     return dirPath;
   }
 
-  Future<String> getEmulatorSystemDirectory(String emulatorId) async {
-    return await getEmulatorBiosDirectory(emulatorId);
+  Future<String> getEmulatorSystemDirectory(String emulatorId, {String? platformSlug}) async {
+    return await getEmulatorBiosDirectory(emulatorId, platformSlug: platformSlug);
   }
 
   Future<void> deleteEmulator(String emulatorId) async {
diff --git a/lib/ui/screens/settings_screen.dart b/lib/ui/screens/settings_screen.dart
index c02df34..4105015 100644
--- a/lib/ui/screens/settings_screen.dart
+++ b/lib/ui/screens/settings_screen.dart
@@ -153,6 +153,10 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
                     const SizedBox(height: 24),
                     _buildRetroArchSyncModeSection(context, ref),
                     const SizedBox(height: 24),
+                    if (defaultTargetPlatform == TargetPlatform.linux) ...[
+                      _buildLinuxSettingsSection(context, ref, directoryService),
+                      const SizedBox(height: 24),
+                    ],
                     // Call the extracted emulators section function
                     buildEmulatorsSection(
                       context, // Pass context
@@ -424,6 +428,51 @@ class _SettingsScreenState extends ConsumerState<SettingsScreen> {
     );
   }
 
+  // --- Linux Settings Section ---
+  Widget _buildLinuxSettingsSection(BuildContext context, WidgetRef ref, DirectoryService directoryService) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        const Text('Linux Integration', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
+        const SizedBox(height: 8),
+        const Text('Select sync method for Linux/Steam Deck', style: TextStyle(color: Colors.grey)),
+        const SizedBox(height: 12),
+        SegmentedButton<String>(
+          segments: const [
+            ButtonSegment(value: 'default', label: Text('Default')),
+            ButtonSegment(value: 'emudeck', label: Text('EmuDeck')),
+          ],
+          selected: {directoryService.linuxSyncPreset},
+          onSelectionChanged: (selection) async {
+            final value = selection.first;
+            await directoryService.setLinuxSyncPreset(value);
+            ref.invalidate(directoryServiceProvider);
+            if (mounted) setState(() {});
+          },
+        ),
+        if (directoryService.linuxSyncPreset == 'emudeck') ...[
+          const SizedBox(height: 16),
+          _buildPathRow(
+            label: 'EmuDeck Root Path',
+            currentPath: directoryService.emudeckRootPath ?? 'Not set',
+            onChanged: (newPath) async {
+              if (newPath != null) {
+                await directoryService.setEmudeckRoot(newPath);
+                ref.invalidate(directoryServiceProvider);
+                if (mounted) setState(() {});
+              }
+            },
+          ),
+          const SizedBox(height: 8),
+          const Text(
+            'EmuDeck integration will use Emulation/roms and Emulation/tools inside this path.',
+            style: TextStyle(fontSize: 12, color: Colors.grey, fontStyle: FontStyle.italic),
+          ),
+        ],
+      ],
+    );
+  }
+
   // --- Legal Section ---
   Widget _buildLegalSection(BuildContext context) {
     return Column(
diff --git a/test/unit/firmware_service_test.mocks.dart b/test/unit/firmware_service_test.mocks.dart
index de3e513..8b37d0e 100644
--- a/test/unit/firmware_service_test.mocks.dart
+++ b/test/unit/firmware_service_test.mocks.dart
@@ -323,6 +323,17 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           )
           as String);
 
+  @override
+  String get linuxSyncPreset =>
+      (super.noSuchMethod(
+            Invocation.getter(#linuxSyncPreset),
+            returnValue: _i4.dummyValue<String>(
+              this,
+              Invocation.getter(#linuxSyncPreset),
+            ),
+          )
+          as String);
+
   @override
   set romsRootPath(String? value) => super.noSuchMethod(
     Invocation.setter(#romsRootPath, value),
@@ -335,6 +346,18 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
     returnValueForMissingStub: null,
   );
 
+  @override
+  set linuxSyncPreset(String? value) => super.noSuchMethod(
+    Invocation.setter(#linuxSyncPreset, value),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  set emudeckRootPath(String? value) => super.noSuchMethod(
+    Invocation.setter(#emudeckRootPath, value),
+    returnValueForMissingStub: null,
+  );
+
   @override
   _i5.Future<void> initialize() =>
       (super.noSuchMethod(
@@ -344,6 +367,24 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           )
           as _i5.Future<void>);
 
+  @override
+  _i5.Future<void> setLinuxSyncPreset(String? preset) =>
+      (super.noSuchMethod(
+            Invocation.method(#setLinuxSyncPreset, [preset]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
+  @override
+  _i5.Future<void> setEmudeckRoot(String? path) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmudeckRoot, [path]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
   @override
   _i5.Future<void> loadEmulatorPathOverrides() =>
       (super.noSuchMethod(
@@ -474,41 +515,72 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorAppSupportDirectory(String? emulatorName) =>
+  _i5.Future<String> getEmulatorAppSupportDirectory(
+    String? emulatorName, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorAppSupportDirectory, [emulatorName]),
+            Invocation.method(
+              #getEmulatorAppSupportDirectory,
+              [emulatorName],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorAppSupportDirectory, [
-                  emulatorName,
-                ]),
+                Invocation.method(
+                  #getEmulatorAppSupportDirectory,
+                  [emulatorName],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorBiosDirectory(String? emulatorId) =>
+  _i5.Future<String> getEmulatorBiosDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorBiosDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorBiosDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorSystemDirectory(String? emulatorId) =>
+  _i5.Future<String> getEmulatorSystemDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorSystemDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorSystemDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
diff --git a/test/unit/save_sync_service_test.mocks.dart b/test/unit/save_sync_service_test.mocks.dart
index dd66357..316f366 100644
--- a/test/unit/save_sync_service_test.mocks.dart
+++ b/test/unit/save_sync_service_test.mocks.dart
@@ -323,6 +323,17 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           )
           as String);
 
+  @override
+  String get linuxSyncPreset =>
+      (super.noSuchMethod(
+            Invocation.getter(#linuxSyncPreset),
+            returnValue: _i4.dummyValue<String>(
+              this,
+              Invocation.getter(#linuxSyncPreset),
+            ),
+          )
+          as String);
+
   @override
   set romsRootPath(String? value) => super.noSuchMethod(
     Invocation.setter(#romsRootPath, value),
@@ -335,6 +346,18 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
     returnValueForMissingStub: null,
   );
 
+  @override
+  set linuxSyncPreset(String? value) => super.noSuchMethod(
+    Invocation.setter(#linuxSyncPreset, value),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  set emudeckRootPath(String? value) => super.noSuchMethod(
+    Invocation.setter(#emudeckRootPath, value),
+    returnValueForMissingStub: null,
+  );
+
   @override
   _i5.Future<void> initialize() =>
       (super.noSuchMethod(
@@ -344,6 +367,24 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           )
           as _i5.Future<void>);
 
+  @override
+  _i5.Future<void> setLinuxSyncPreset(String? preset) =>
+      (super.noSuchMethod(
+            Invocation.method(#setLinuxSyncPreset, [preset]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
+  @override
+  _i5.Future<void> setEmudeckRoot(String? path) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmudeckRoot, [path]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
   @override
   _i5.Future<void> loadEmulatorPathOverrides() =>
       (super.noSuchMethod(
@@ -474,41 +515,72 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorAppSupportDirectory(String? emulatorName) =>
+  _i5.Future<String> getEmulatorAppSupportDirectory(
+    String? emulatorName, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorAppSupportDirectory, [emulatorName]),
+            Invocation.method(
+              #getEmulatorAppSupportDirectory,
+              [emulatorName],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorAppSupportDirectory, [
-                  emulatorName,
-                ]),
+                Invocation.method(
+                  #getEmulatorAppSupportDirectory,
+                  [emulatorName],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorBiosDirectory(String? emulatorId) =>
+  _i5.Future<String> getEmulatorBiosDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorBiosDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorBiosDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorSystemDirectory(String? emulatorId) =>
+  _i5.Future<String> getEmulatorSystemDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorSystemDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorSystemDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
diff --git a/test/unit/strategy_registry_test.mocks.dart b/test/unit/strategy_registry_test.mocks.dart
index e7fd644..cfaa6cc 100644
--- a/test/unit/strategy_registry_test.mocks.dart
+++ b/test/unit/strategy_registry_test.mocks.dart
@@ -55,6 +55,17 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
           )
           as String);
 
+  @override
+  String get linuxSyncPreset =>
+      (super.noSuchMethod(
+            Invocation.getter(#linuxSyncPreset),
+            returnValue: _i3.dummyValue<String>(
+              this,
+              Invocation.getter(#linuxSyncPreset),
+            ),
+          )
+          as String);
+
   @override
   set romsRootPath(String? value) => super.noSuchMethod(
     Invocation.setter(#romsRootPath, value),
@@ -67,6 +78,18 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
     returnValueForMissingStub: null,
   );
 
+  @override
+  set linuxSyncPreset(String? value) => super.noSuchMethod(
+    Invocation.setter(#linuxSyncPreset, value),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  set emudeckRootPath(String? value) => super.noSuchMethod(
+    Invocation.setter(#emudeckRootPath, value),
+    returnValueForMissingStub: null,
+  );
+
   @override
   _i4.Future<void> initialize() =>
       (super.noSuchMethod(
@@ -76,6 +99,24 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
           )
           as _i4.Future<void>);
 
+  @override
+  _i4.Future<void> setLinuxSyncPreset(String? preset) =>
+      (super.noSuchMethod(
+            Invocation.method(#setLinuxSyncPreset, [preset]),
+            returnValue: _i4.Future<void>.value(),
+            returnValueForMissingStub: _i4.Future<void>.value(),
+          )
+          as _i4.Future<void>);
+
+  @override
+  _i4.Future<void> setEmudeckRoot(String? path) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmudeckRoot, [path]),
+            returnValue: _i4.Future<void>.value(),
+            returnValueForMissingStub: _i4.Future<void>.value(),
+          )
+          as _i4.Future<void>);
+
   @override
   _i4.Future<void> loadEmulatorPathOverrides() =>
       (super.noSuchMethod(
@@ -206,41 +247,72 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
           as _i4.Future<String>);
 
   @override
-  _i4.Future<String> getEmulatorAppSupportDirectory(String? emulatorName) =>
+  _i4.Future<String> getEmulatorAppSupportDirectory(
+    String? emulatorName, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorAppSupportDirectory, [emulatorName]),
+            Invocation.method(
+              #getEmulatorAppSupportDirectory,
+              [emulatorName],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i4.Future<String>.value(
               _i3.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorAppSupportDirectory, [
-                  emulatorName,
-                ]),
+                Invocation.method(
+                  #getEmulatorAppSupportDirectory,
+                  [emulatorName],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i4.Future<String>);
 
   @override
-  _i4.Future<String> getEmulatorBiosDirectory(String? emulatorId) =>
+  _i4.Future<String> getEmulatorBiosDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorBiosDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i4.Future<String>.value(
               _i3.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorBiosDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i4.Future<String>);
 
   @override
-  _i4.Future<String> getEmulatorSystemDirectory(String? emulatorId) =>
+  _i4.Future<String> getEmulatorSystemDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorSystemDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i4.Future<String>.value(
               _i3.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorSystemDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
diff --git a/test/widgets/library_screen_test.mocks.dart b/test/widgets/library_screen_test.mocks.dart
index 44ab193..934e5cf 100644
--- a/test/widgets/library_screen_test.mocks.dart
+++ b/test/widgets/library_screen_test.mocks.dart
@@ -321,6 +321,17 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           )
           as String);
 
+  @override
+  String get linuxSyncPreset =>
+      (super.noSuchMethod(
+            Invocation.getter(#linuxSyncPreset),
+            returnValue: _i4.dummyValue<String>(
+              this,
+              Invocation.getter(#linuxSyncPreset),
+            ),
+          )
+          as String);
+
   @override
   set romsRootPath(String? value) => super.noSuchMethod(
     Invocation.setter(#romsRootPath, value),
@@ -333,6 +344,18 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
     returnValueForMissingStub: null,
   );
 
+  @override
+  set linuxSyncPreset(String? value) => super.noSuchMethod(
+    Invocation.setter(#linuxSyncPreset, value),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  set emudeckRootPath(String? value) => super.noSuchMethod(
+    Invocation.setter(#emudeckRootPath, value),
+    returnValueForMissingStub: null,
+  );
+
   @override
   _i5.Future<void> initialize() =>
       (super.noSuchMethod(
@@ -342,6 +365,24 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           )
           as _i5.Future<void>);
 
+  @override
+  _i5.Future<void> setLinuxSyncPreset(String? preset) =>
+      (super.noSuchMethod(
+            Invocation.method(#setLinuxSyncPreset, [preset]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
+  @override
+  _i5.Future<void> setEmudeckRoot(String? path) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmudeckRoot, [path]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
   @override
   _i5.Future<void> loadEmulatorPathOverrides() =>
       (super.noSuchMethod(
@@ -472,41 +513,72 @@ class MockDirectoryService extends _i1.Mock implements _i8.DirectoryService {
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorAppSupportDirectory(String? emulatorName) =>
+  _i5.Future<String> getEmulatorAppSupportDirectory(
+    String? emulatorName, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorAppSupportDirectory, [emulatorName]),
+            Invocation.method(
+              #getEmulatorAppSupportDirectory,
+              [emulatorName],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorAppSupportDirectory, [
-                  emulatorName,
-                ]),
+                Invocation.method(
+                  #getEmulatorAppSupportDirectory,
+                  [emulatorName],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorBiosDirectory(String? emulatorId) =>
+  _i5.Future<String> getEmulatorBiosDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorBiosDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorBiosDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorSystemDirectory(String? emulatorId) =>
+  _i5.Future<String> getEmulatorSystemDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorSystemDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorSystemDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
diff --git a/test/widgets/settings_screen_test.mocks.dart b/test/widgets/settings_screen_test.mocks.dart
index ad21c9e..03e41e7 100644
--- a/test/widgets/settings_screen_test.mocks.dart
+++ b/test/widgets/settings_screen_test.mocks.dart
@@ -65,6 +65,17 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           )
           as String);
 
+  @override
+  String get linuxSyncPreset =>
+      (super.noSuchMethod(
+            Invocation.getter(#linuxSyncPreset),
+            returnValue: _i4.dummyValue<String>(
+              this,
+              Invocation.getter(#linuxSyncPreset),
+            ),
+          )
+          as String);
+
   @override
   set romsRootPath(String? value) => super.noSuchMethod(
     Invocation.setter(#romsRootPath, value),
@@ -77,6 +88,18 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
     returnValueForMissingStub: null,
   );
 
+  @override
+  set linuxSyncPreset(String? value) => super.noSuchMethod(
+    Invocation.setter(#linuxSyncPreset, value),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  set emudeckRootPath(String? value) => super.noSuchMethod(
+    Invocation.setter(#emudeckRootPath, value),
+    returnValueForMissingStub: null,
+  );
+
   @override
   _i5.Future<void> initialize() =>
       (super.noSuchMethod(
@@ -86,6 +109,24 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           )
           as _i5.Future<void>);
 
+  @override
+  _i5.Future<void> setLinuxSyncPreset(String? preset) =>
+      (super.noSuchMethod(
+            Invocation.method(#setLinuxSyncPreset, [preset]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
+  @override
+  _i5.Future<void> setEmudeckRoot(String? path) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmudeckRoot, [path]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
   @override
   _i5.Future<void> loadEmulatorPathOverrides() =>
       (super.noSuchMethod(
@@ -216,41 +257,72 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorAppSupportDirectory(String? emulatorName) =>
+  _i5.Future<String> getEmulatorAppSupportDirectory(
+    String? emulatorName, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorAppSupportDirectory, [emulatorName]),
+            Invocation.method(
+              #getEmulatorAppSupportDirectory,
+              [emulatorName],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorAppSupportDirectory, [
-                  emulatorName,
-                ]),
+                Invocation.method(
+                  #getEmulatorAppSupportDirectory,
+                  [emulatorName],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorBiosDirectory(String? emulatorId) =>
+  _i5.Future<String> getEmulatorBiosDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorBiosDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorBiosDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorBiosDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )
           as _i5.Future<String>);
 
   @override
-  _i5.Future<String> getEmulatorSystemDirectory(String? emulatorId) =>
+  _i5.Future<String> getEmulatorSystemDirectory(
+    String? emulatorId, {
+    String? platformSlug,
+  }) =>
       (super.noSuchMethod(
-            Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+            Invocation.method(
+              #getEmulatorSystemDirectory,
+              [emulatorId],
+              {#platformSlug: platformSlug},
+            ),
             returnValue: _i5.Future<String>.value(
               _i4.dummyValue<String>(
                 this,
-                Invocation.method(#getEmulatorSystemDirectory, [emulatorId]),
+                Invocation.method(
+                  #getEmulatorSystemDirectory,
+                  [emulatorId],
+                  {#platformSlug: platformSlug},
+                ),
               ),
             ),
           )

Clone this wiki locally