ConfigurationState.Migration.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. using Avalonia.Media;
  2. using Gommon;
  3. using Ryujinx.Ava.Utilities.Configuration.System;
  4. using Ryujinx.Ava.Utilities.Configuration.UI;
  5. using Ryujinx.Common.Configuration;
  6. using Ryujinx.Common.Configuration.Hid;
  7. using Ryujinx.Common.Configuration.Hid.Controller;
  8. using Ryujinx.Common.Configuration.Hid.Keyboard;
  9. using Ryujinx.Common.Configuration.Multiplayer;
  10. using Ryujinx.Common.Logging;
  11. using Ryujinx.HLE;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using RyuLogger = Ryujinx.Common.Logging.Logger;
  16. namespace Ryujinx.Ava.Utilities.Configuration
  17. {
  18. public partial class ConfigurationState
  19. {
  20. public void Load(ConfigurationFileFormat cff, string configurationFilePath)
  21. {
  22. bool configurationFileUpdated = false;
  23. if (cff.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
  24. {
  25. RyuLogger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {cff.Version}, loading default.");
  26. LoadDefault();
  27. }
  28. foreach ((int newVersion, Action<ConfigurationFileFormat> migratorFunction)
  29. in _migrations.OrderBy(x => x.Key))
  30. {
  31. if (cff.Version >= newVersion)
  32. continue;
  33. RyuLogger.Warning?.Print(LogClass.Application,
  34. $"Outdated configuration version {cff.Version}, migrating to version {newVersion}.");
  35. migratorFunction(cff);
  36. configurationFileUpdated = true;
  37. }
  38. EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
  39. CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
  40. ShowConfirmExit.Value = cff.ShowConfirmExit;
  41. RememberWindowState.Value = cff.RememberWindowState;
  42. ShowTitleBar.Value = cff.ShowTitleBar;
  43. EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration;
  44. HideCursor.Value = cff.HideCursor;
  45. Logger.EnableFileLog.Value = cff.EnableFileLog;
  46. Logger.EnableDebug.Value = cff.LoggingEnableDebug;
  47. Logger.EnableStub.Value = cff.LoggingEnableStub;
  48. Logger.EnableInfo.Value = cff.LoggingEnableInfo;
  49. Logger.EnableWarn.Value = cff.LoggingEnableWarn;
  50. Logger.EnableError.Value = cff.LoggingEnableError;
  51. Logger.EnableTrace.Value = cff.LoggingEnableTrace;
  52. Logger.EnableGuest.Value = cff.LoggingEnableGuest;
  53. Logger.EnableFsAccessLog.Value = cff.LoggingEnableFsAccessLog;
  54. Logger.FilteredClasses.Value = cff.LoggingFilteredClasses;
  55. Logger.GraphicsDebugLevel.Value = cff.LoggingGraphicsDebugLevel;
  56. Graphics.ResScale.Value = cff.ResScale;
  57. Graphics.ResScaleCustom.Value = cff.ResScaleCustom;
  58. Graphics.MaxAnisotropy.Value = cff.MaxAnisotropy;
  59. Graphics.AspectRatio.Value = cff.AspectRatio;
  60. Graphics.ShadersDumpPath.Value = cff.GraphicsShadersDumpPath;
  61. Graphics.BackendThreading.Value = cff.BackendThreading;
  62. Graphics.GraphicsBackend.Value = cff.GraphicsBackend;
  63. Graphics.PreferredGpu.Value = cff.PreferredGpu;
  64. Graphics.AntiAliasing.Value = cff.AntiAliasing;
  65. Graphics.ScalingFilter.Value = cff.ScalingFilter;
  66. Graphics.ScalingFilterLevel.Value = cff.ScalingFilterLevel;
  67. Graphics.VSyncMode.Value = cff.VSyncMode;
  68. Graphics.EnableCustomVSyncInterval.Value = cff.EnableCustomVSyncInterval;
  69. Graphics.CustomVSyncInterval.Value = cff.CustomVSyncInterval;
  70. Graphics.EnableShaderCache.Value = cff.EnableShaderCache;
  71. Graphics.EnableTextureRecompression.Value = cff.EnableTextureRecompression;
  72. Graphics.EnableMacroHLE.Value = cff.EnableMacroHLE;
  73. Graphics.EnableColorSpacePassthrough.Value = cff.EnableColorSpacePassthrough;
  74. System.Language.Value = cff.SystemLanguage;
  75. System.Region.Value = cff.SystemRegion;
  76. System.TimeZone.Value = cff.SystemTimeZone;
  77. System.SystemTimeOffset.Value = cff.SystemTimeOffset;
  78. System.EnableDockedMode.Value = cff.DockedMode;
  79. System.EnablePtc.Value = cff.EnablePtc;
  80. System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc;
  81. System.EnableInternetAccess.Value = cff.EnableInternetAccess;
  82. System.EnableFsIntegrityChecks.Value = cff.EnableFsIntegrityChecks;
  83. System.FsGlobalAccessLogMode.Value = cff.FsGlobalAccessLogMode;
  84. System.AudioBackend.Value = cff.AudioBackend;
  85. System.AudioVolume.Value = cff.AudioVolume;
  86. System.MemoryManagerMode.Value = cff.MemoryManagerMode;
  87. System.DramSize.Value = cff.DramSize;
  88. System.IgnoreMissingServices.Value = cff.IgnoreMissingServices;
  89. System.IgnoreApplet.Value = cff.IgnoreApplet;
  90. System.UseHypervisor.Value = cff.UseHypervisor;
  91. UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
  92. UI.GuiColumns.IconColumn.Value = cff.GuiColumns.IconColumn;
  93. UI.GuiColumns.AppColumn.Value = cff.GuiColumns.AppColumn;
  94. UI.GuiColumns.DevColumn.Value = cff.GuiColumns.DevColumn;
  95. UI.GuiColumns.VersionColumn.Value = cff.GuiColumns.VersionColumn;
  96. UI.GuiColumns.TimePlayedColumn.Value = cff.GuiColumns.TimePlayedColumn;
  97. UI.GuiColumns.LastPlayedColumn.Value = cff.GuiColumns.LastPlayedColumn;
  98. UI.GuiColumns.FileExtColumn.Value = cff.GuiColumns.FileExtColumn;
  99. UI.GuiColumns.FileSizeColumn.Value = cff.GuiColumns.FileSizeColumn;
  100. UI.GuiColumns.PathColumn.Value = cff.GuiColumns.PathColumn;
  101. UI.ColumnSort.SortColumnId.Value = cff.ColumnSort.SortColumnId;
  102. UI.ColumnSort.SortAscending.Value = cff.ColumnSort.SortAscending;
  103. UI.GameDirs.Value = cff.GameDirs;
  104. UI.AutoloadDirs.Value = cff.AutoloadDirs ?? [];
  105. UI.ShownFileTypes.NSP.Value = cff.ShownFileTypes.NSP;
  106. UI.ShownFileTypes.PFS0.Value = cff.ShownFileTypes.PFS0;
  107. UI.ShownFileTypes.XCI.Value = cff.ShownFileTypes.XCI;
  108. UI.ShownFileTypes.NCA.Value = cff.ShownFileTypes.NCA;
  109. UI.ShownFileTypes.NRO.Value = cff.ShownFileTypes.NRO;
  110. UI.ShownFileTypes.NSO.Value = cff.ShownFileTypes.NSO;
  111. UI.LanguageCode.Value = cff.LanguageCode;
  112. UI.BaseStyle.Value = cff.BaseStyle;
  113. UI.GameListViewMode.Value = cff.GameListViewMode;
  114. UI.ShowNames.Value = cff.ShowNames;
  115. UI.IsAscendingOrder.Value = cff.IsAscendingOrder;
  116. UI.GridSize.Value = cff.GridSize;
  117. UI.ApplicationSort.Value = cff.ApplicationSort;
  118. UI.StartFullscreen.Value = cff.StartFullscreen;
  119. UI.StartNoUI.Value = cff.StartNoUI;
  120. UI.ShowConsole.Value = cff.ShowConsole;
  121. UI.WindowStartup.WindowSizeWidth.Value = cff.WindowStartup.WindowSizeWidth;
  122. UI.WindowStartup.WindowSizeHeight.Value = cff.WindowStartup.WindowSizeHeight;
  123. UI.WindowStartup.WindowPositionX.Value = cff.WindowStartup.WindowPositionX;
  124. UI.WindowStartup.WindowPositionY.Value = cff.WindowStartup.WindowPositionY;
  125. UI.WindowStartup.WindowMaximized.Value = cff.WindowStartup.WindowMaximized;
  126. Hid.EnableKeyboard.Value = cff.EnableKeyboard;
  127. Hid.EnableMouse.Value = cff.EnableMouse;
  128. Hid.Hotkeys.Value = cff.Hotkeys;
  129. Hid.InputConfig.Value = cff.InputConfig ?? [];
  130. Hid.RainbowSpeed.Value = cff.RainbowSpeed;
  131. Multiplayer.LanInterfaceId.Value = cff.MultiplayerLanInterfaceId;
  132. Multiplayer.Mode.Value = cff.MultiplayerMode;
  133. Multiplayer.DisableP2p.Value = cff.MultiplayerDisableP2p;
  134. Multiplayer.LdnPassphrase.Value = cff.MultiplayerLdnPassphrase;
  135. Multiplayer.LdnServer.Value = cff.LdnServer;
  136. {
  137. Hacks.ShowDirtyHacks.Value = cff.ShowDirtyHacks;
  138. DirtyHacks hacks = new (cff.DirtyHacks ?? []);
  139. Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix);
  140. Hacks.EnableShaderTranslationDelay.Value = hacks.IsEnabled(DirtyHack.ShaderTranslationDelay);
  141. Hacks.ShaderTranslationDelay.Value = hacks[DirtyHack.ShaderTranslationDelay].CoerceAtLeast(0);
  142. }
  143. if (configurationFileUpdated)
  144. {
  145. ToFileFormat().SaveConfig(configurationFilePath);
  146. RyuLogger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
  147. }
  148. }
  149. private static readonly Dictionary<int, Action<ConfigurationFileFormat>> _migrations =
  150. Collections.NewDictionary<int, Action<ConfigurationFileFormat>>(
  151. (2, static cff => cff.SystemRegion = Region.USA),
  152. (3, static cff => cff.SystemTimeZone = "UTC"),
  153. (4, static cff => cff.MaxAnisotropy = -1),
  154. (5, static cff => cff.SystemTimeOffset = 0),
  155. (8, static cff => cff.EnablePtc = true),
  156. (9, static cff =>
  157. {
  158. cff.ColumnSort = new ColumnSort { SortColumnId = 0, SortAscending = false };
  159. cff.Hotkeys = new KeyboardHotkeys { ToggleVSyncMode = Key.F1 };
  160. }),
  161. (10, static cff => cff.AudioBackend = AudioBackend.OpenAl),
  162. (11, static cff =>
  163. {
  164. cff.ResScale = 1;
  165. cff.ResScaleCustom = 1.0f;
  166. }),
  167. (12, static cff => cff.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None),
  168. // 13 -> LDN1
  169. (14, static cff => cff.CheckUpdatesOnStart = true),
  170. (16, static cff => cff.EnableShaderCache = true),
  171. (17, static cff => cff.StartFullscreen = false),
  172. (18, static cff => cff.AspectRatio = AspectRatio.Fixed16x9),
  173. // 19 -> LDN2
  174. (20, static cff => cff.ShowConfirmExit = true),
  175. (21, static cff =>
  176. {
  177. // Initialize network config.
  178. cff.MultiplayerMode = MultiplayerMode.Disabled;
  179. cff.MultiplayerLanInterfaceId = "0";
  180. }),
  181. (22, static cff => cff.HideCursor = HideCursorMode.Never),
  182. (24, static cff =>
  183. {
  184. cff.InputConfig =
  185. [
  186. new StandardKeyboardInputConfig
  187. {
  188. Version = InputConfig.CurrentVersion,
  189. Backend = InputBackendType.WindowKeyboard,
  190. Id = "0",
  191. PlayerIndex = PlayerIndex.Player1,
  192. ControllerType = ControllerType.ProController,
  193. LeftJoycon = new LeftJoyconCommonConfig<Key>
  194. {
  195. DpadUp = Key.Up,
  196. DpadDown = Key.Down,
  197. DpadLeft = Key.Left,
  198. DpadRight = Key.Right,
  199. ButtonMinus = Key.Minus,
  200. ButtonL = Key.E,
  201. ButtonZl = Key.Q,
  202. ButtonSl = Key.Unbound,
  203. ButtonSr = Key.Unbound,
  204. },
  205. LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
  206. {
  207. StickUp = Key.W,
  208. StickDown = Key.S,
  209. StickLeft = Key.A,
  210. StickRight = Key.D,
  211. StickButton = Key.F,
  212. },
  213. RightJoycon = new RightJoyconCommonConfig<Key>
  214. {
  215. ButtonA = Key.Z,
  216. ButtonB = Key.X,
  217. ButtonX = Key.C,
  218. ButtonY = Key.V,
  219. ButtonPlus = Key.Plus,
  220. ButtonR = Key.U,
  221. ButtonZr = Key.O,
  222. ButtonSl = Key.Unbound,
  223. ButtonSr = Key.Unbound,
  224. },
  225. RightJoyconStick = new JoyconConfigKeyboardStick<Key>
  226. {
  227. StickUp = Key.I,
  228. StickDown = Key.K,
  229. StickLeft = Key.J,
  230. StickRight = Key.L,
  231. StickButton = Key.H,
  232. },
  233. }
  234. ];
  235. }),
  236. (26, static cff => cff.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe),
  237. (27, static cff => cff.EnableMouse = false),
  238. (29,
  239. static cff =>
  240. cff.Hotkeys = new KeyboardHotkeys
  241. {
  242. ToggleVSyncMode = Key.F1, Screenshot = Key.F8, ShowUI = Key.F4
  243. }),
  244. (30, static cff =>
  245. {
  246. foreach (StandardControllerInputConfig config in cff.InputConfig.OfType<StandardControllerInputConfig>())
  247. {
  248. config.Rumble = new RumbleConfigController
  249. {
  250. EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f,
  251. };
  252. }
  253. }),
  254. (31, static cff => cff.BackendThreading = BackendThreading.Auto),
  255. (32, static cff => cff.Hotkeys = new KeyboardHotkeys
  256. {
  257. ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
  258. Screenshot = cff.Hotkeys.Screenshot,
  259. ShowUI = cff.Hotkeys.ShowUI,
  260. Pause = Key.F5,
  261. }),
  262. (33, static cff =>
  263. {
  264. cff.Hotkeys = new KeyboardHotkeys
  265. {
  266. ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
  267. Screenshot = cff.Hotkeys.Screenshot,
  268. ShowUI = cff.Hotkeys.ShowUI,
  269. Pause = cff.Hotkeys.Pause,
  270. ToggleMute = Key.F2,
  271. };
  272. cff.AudioVolume = 1;
  273. }),
  274. (34, static cff => cff.EnableInternetAccess = false),
  275. (35, static cff =>
  276. {
  277. foreach (StandardControllerInputConfig config in cff.InputConfig
  278. .OfType<StandardControllerInputConfig>())
  279. {
  280. config.RangeLeft = 1.0f;
  281. config.RangeRight = 1.0f;
  282. }
  283. }),
  284. (36, static cff => cff.LoggingEnableTrace = false),
  285. (37, static cff => cff.ShowConsole = true),
  286. (38, static cff =>
  287. {
  288. cff.BaseStyle = "Dark";
  289. cff.GameListViewMode = 0;
  290. cff.ShowNames = true;
  291. cff.GridSize = 2;
  292. cff.LanguageCode = "en_US";
  293. }),
  294. (39,
  295. static cff => cff.Hotkeys = new KeyboardHotkeys
  296. {
  297. ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
  298. Screenshot = cff.Hotkeys.Screenshot,
  299. ShowUI = cff.Hotkeys.ShowUI,
  300. Pause = cff.Hotkeys.Pause,
  301. ToggleMute = cff.Hotkeys.ToggleMute,
  302. ResScaleUp = Key.Unbound,
  303. ResScaleDown = Key.Unbound
  304. }),
  305. (40, static cff => cff.GraphicsBackend = GraphicsBackend.OpenGl),
  306. (41,
  307. static cff => cff.Hotkeys = new KeyboardHotkeys
  308. {
  309. ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
  310. Screenshot = cff.Hotkeys.Screenshot,
  311. ShowUI = cff.Hotkeys.ShowUI,
  312. Pause = cff.Hotkeys.Pause,
  313. ToggleMute = cff.Hotkeys.ToggleMute,
  314. ResScaleUp = cff.Hotkeys.ResScaleUp,
  315. ResScaleDown = cff.Hotkeys.ResScaleDown,
  316. VolumeUp = Key.Unbound,
  317. VolumeDown = Key.Unbound
  318. }),
  319. (42, static cff => cff.EnableMacroHLE = true),
  320. (43, static cff => cff.UseHypervisor = true),
  321. (44, static cff =>
  322. {
  323. cff.AntiAliasing = AntiAliasing.None;
  324. cff.ScalingFilter = ScalingFilter.Bilinear;
  325. cff.ScalingFilterLevel = 80;
  326. }),
  327. (45,
  328. static cff => cff.ShownFileTypes = new ShownFileTypes
  329. {
  330. NSP = true,
  331. PFS0 = true,
  332. XCI = true,
  333. NCA = true,
  334. NRO = true,
  335. NSO = true
  336. }),
  337. (46, static cff => cff.UseHypervisor = OperatingSystem.IsMacOS()),
  338. (47,
  339. static cff => cff.WindowStartup = new WindowStartup
  340. {
  341. WindowPositionX = 0,
  342. WindowPositionY = 0,
  343. WindowSizeHeight = 760,
  344. WindowSizeWidth = 1280,
  345. WindowMaximized = false
  346. }),
  347. (48, static cff => cff.EnableColorSpacePassthrough = false),
  348. (49, static _ =>
  349. {
  350. if (OperatingSystem.IsMacOS())
  351. {
  352. AppDataManager.FixMacOSConfigurationFolders();
  353. }
  354. }),
  355. (50, static cff => cff.EnableHardwareAcceleration = true),
  356. (51, static cff => cff.RememberWindowState = true),
  357. (52, static cff => cff.AutoloadDirs = []),
  358. (53, static cff => cff.EnableLowPowerPtc = false),
  359. (54, static cff => cff.DramSize = MemoryConfiguration.MemoryConfiguration4GiB),
  360. (55, static cff => cff.IgnoreApplet = false),
  361. (56, static cff => cff.ShowTitleBar = !OperatingSystem.IsWindows()),
  362. (57, static cff =>
  363. {
  364. cff.VSyncMode = VSyncMode.Switch;
  365. cff.EnableCustomVSyncInterval = false;
  366. cff.Hotkeys = new KeyboardHotkeys
  367. {
  368. ToggleVSyncMode = Key.F1,
  369. Screenshot = cff.Hotkeys.Screenshot,
  370. ShowUI = cff.Hotkeys.ShowUI,
  371. Pause = cff.Hotkeys.Pause,
  372. ToggleMute = cff.Hotkeys.ToggleMute,
  373. ResScaleUp = cff.Hotkeys.ResScaleUp,
  374. ResScaleDown = cff.Hotkeys.ResScaleDown,
  375. VolumeUp = cff.Hotkeys.VolumeUp,
  376. VolumeDown = cff.Hotkeys.VolumeDown,
  377. CustomVSyncIntervalIncrement = Key.Unbound,
  378. CustomVSyncIntervalDecrement = Key.Unbound,
  379. };
  380. cff.CustomVSyncInterval = 120;
  381. }),
  382. // 58 migration accidentally got skipped, but it worked with no issues somehow lol
  383. (59, static cff =>
  384. {
  385. cff.ShowDirtyHacks = false;
  386. cff.DirtyHacks = [];
  387. // This was accidentally enabled by default when it was PRed. That is not what we want,
  388. // so as a compromise users who want to use it will simply need to re-enable it once after updating.
  389. cff.IgnoreApplet = false;
  390. }),
  391. (60, static cff => cff.StartNoUI = false),
  392. (61, static cff =>
  393. {
  394. foreach (StandardControllerInputConfig config in cff.InputConfig.OfType<StandardControllerInputConfig>())
  395. {
  396. config.Led = new LedConfigController
  397. {
  398. EnableLed = false,
  399. TurnOffLed = false,
  400. UseRainbow = false,
  401. LedColor = new Color(255, 5, 1, 253).ToUInt32()
  402. };
  403. }
  404. }),
  405. (62, static cff => cff.RainbowSpeed = 1f),
  406. (63, static cff => cff.MatchSystemTime = false)
  407. );
  408. }
  409. }