ConfigurationState.Migration.cs 21 KB

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