ConfigurationState.cs 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  1. using Ryujinx.Common;
  2. using Ryujinx.Common.Configuration;
  3. using Ryujinx.Common.Configuration.Hid;
  4. using Ryujinx.Common.Configuration.Hid.Controller;
  5. using Ryujinx.Common.Configuration.Hid.Keyboard;
  6. using Ryujinx.Common.Logging;
  7. using Ryujinx.Configuration.System;
  8. using Ryujinx.Configuration.Ui;
  9. using Ryujinx.Ui.Helper;
  10. using System;
  11. using System.Collections.Generic;
  12. namespace Ryujinx.Configuration
  13. {
  14. public class ConfigurationState
  15. {
  16. /// <summary>
  17. /// UI configuration section
  18. /// </summary>
  19. public class UiSection
  20. {
  21. public class Columns
  22. {
  23. public ReactiveObject<bool> FavColumn { get; private set; }
  24. public ReactiveObject<bool> IconColumn { get; private set; }
  25. public ReactiveObject<bool> AppColumn { get; private set; }
  26. public ReactiveObject<bool> DevColumn { get; private set; }
  27. public ReactiveObject<bool> VersionColumn { get; private set; }
  28. public ReactiveObject<bool> TimePlayedColumn { get; private set; }
  29. public ReactiveObject<bool> LastPlayedColumn { get; private set; }
  30. public ReactiveObject<bool> FileExtColumn { get; private set; }
  31. public ReactiveObject<bool> FileSizeColumn { get; private set; }
  32. public ReactiveObject<bool> PathColumn { get; private set; }
  33. public Columns()
  34. {
  35. FavColumn = new ReactiveObject<bool>();
  36. IconColumn = new ReactiveObject<bool>();
  37. AppColumn = new ReactiveObject<bool>();
  38. DevColumn = new ReactiveObject<bool>();
  39. VersionColumn = new ReactiveObject<bool>();
  40. TimePlayedColumn = new ReactiveObject<bool>();
  41. LastPlayedColumn = new ReactiveObject<bool>();
  42. FileExtColumn = new ReactiveObject<bool>();
  43. FileSizeColumn = new ReactiveObject<bool>();
  44. PathColumn = new ReactiveObject<bool>();
  45. }
  46. }
  47. public class ColumnSortSettings
  48. {
  49. public ReactiveObject<int> SortColumnId { get; private set; }
  50. public ReactiveObject<bool> SortAscending { get; private set; }
  51. public ColumnSortSettings()
  52. {
  53. SortColumnId = new ReactiveObject<int>();
  54. SortAscending = new ReactiveObject<bool>();
  55. }
  56. }
  57. /// <summary>
  58. /// Used to toggle columns in the GUI
  59. /// </summary>
  60. public Columns GuiColumns { get; private set; }
  61. /// <summary>
  62. /// Used to configure column sort settings in the GUI
  63. /// </summary>
  64. public ColumnSortSettings ColumnSort { get; private set; }
  65. /// <summary>
  66. /// A list of directories containing games to be used to load games into the games list
  67. /// </summary>
  68. public ReactiveObject<List<string>> GameDirs { get; private set; }
  69. /// <summary>
  70. /// Enable or disable custom themes in the GUI
  71. /// </summary>
  72. public ReactiveObject<bool> EnableCustomTheme { get; private set; }
  73. /// <summary>
  74. /// Path to custom GUI theme
  75. /// </summary>
  76. public ReactiveObject<string> CustomThemePath { get; private set; }
  77. /// <summary>
  78. /// Start games in fullscreen mode
  79. /// </summary>
  80. public ReactiveObject<bool> StartFullscreen { get; private set; }
  81. /// <summary>
  82. /// Hide / Show Console Window
  83. /// </summary>
  84. public ReactiveObject<bool> ShowConsole { get; private set; }
  85. public UiSection()
  86. {
  87. GuiColumns = new Columns();
  88. ColumnSort = new ColumnSortSettings();
  89. GameDirs = new ReactiveObject<List<string>>();
  90. EnableCustomTheme = new ReactiveObject<bool>();
  91. CustomThemePath = new ReactiveObject<string>();
  92. StartFullscreen = new ReactiveObject<bool>();
  93. ShowConsole = new ReactiveObject<bool>();
  94. ShowConsole.Event += static (s, e) => { ConsoleHelper.SetConsoleWindowState(e.NewValue); };
  95. }
  96. }
  97. /// <summary>
  98. /// Logger configuration section
  99. /// </summary>
  100. public class LoggerSection
  101. {
  102. /// <summary>
  103. /// Enables printing debug log messages
  104. /// </summary>
  105. public ReactiveObject<bool> EnableDebug { get; private set; }
  106. /// <summary>
  107. /// Enables printing stub log messages
  108. /// </summary>
  109. public ReactiveObject<bool> EnableStub { get; private set; }
  110. /// <summary>
  111. /// Enables printing info log messages
  112. /// </summary>
  113. public ReactiveObject<bool> EnableInfo { get; private set; }
  114. /// <summary>
  115. /// Enables printing warning log messages
  116. /// </summary>
  117. public ReactiveObject<bool> EnableWarn { get; private set; }
  118. /// <summary>
  119. /// Enables printing error log messages
  120. /// </summary>
  121. public ReactiveObject<bool> EnableError { get; private set; }
  122. /// <summary>
  123. /// Enables printing trace log messages
  124. /// </summary>
  125. public ReactiveObject<bool> EnableTrace { get; private set; }
  126. /// <summary>
  127. /// Enables printing guest log messages
  128. /// </summary>
  129. public ReactiveObject<bool> EnableGuest { get; private set; }
  130. /// <summary>
  131. /// Enables printing FS access log messages
  132. /// </summary>
  133. public ReactiveObject<bool> EnableFsAccessLog { get; private set; }
  134. /// <summary>
  135. /// Controls which log messages are written to the log targets
  136. /// </summary>
  137. public ReactiveObject<LogClass[]> FilteredClasses { get; private set; }
  138. /// <summary>
  139. /// Enables or disables logging to a file on disk
  140. /// </summary>
  141. public ReactiveObject<bool> EnableFileLog { get; private set; }
  142. /// <summary>
  143. /// Controls which OpenGL log messages are recorded in the log
  144. /// </summary>
  145. public ReactiveObject<GraphicsDebugLevel> GraphicsDebugLevel { get; private set; }
  146. public LoggerSection()
  147. {
  148. EnableDebug = new ReactiveObject<bool>();
  149. EnableStub = new ReactiveObject<bool>();
  150. EnableInfo = new ReactiveObject<bool>();
  151. EnableWarn = new ReactiveObject<bool>();
  152. EnableError = new ReactiveObject<bool>();
  153. EnableTrace = new ReactiveObject<bool>();
  154. EnableGuest = new ReactiveObject<bool>();
  155. EnableFsAccessLog = new ReactiveObject<bool>();
  156. FilteredClasses = new ReactiveObject<LogClass[]>();
  157. EnableFileLog = new ReactiveObject<bool>();
  158. EnableFileLog.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFileLog));
  159. GraphicsDebugLevel = new ReactiveObject<GraphicsDebugLevel>();
  160. }
  161. }
  162. /// <summary>
  163. /// System configuration section
  164. /// </summary>
  165. public class SystemSection
  166. {
  167. /// <summary>
  168. /// Change System Language
  169. /// </summary>
  170. public ReactiveObject<Language> Language { get; private set; }
  171. /// <summary>
  172. /// Change System Region
  173. /// </summary>
  174. public ReactiveObject<Region> Region { get; private set; }
  175. /// <summary>
  176. /// Change System TimeZone
  177. /// </summary>
  178. public ReactiveObject<string> TimeZone { get; private set; }
  179. /// <summary>
  180. /// System Time Offset in Seconds
  181. /// </summary>
  182. public ReactiveObject<long> SystemTimeOffset { get; private set; }
  183. /// <summary>
  184. /// Enables or disables Docked Mode
  185. /// </summary>
  186. public ReactiveObject<bool> EnableDockedMode { get; private set; }
  187. /// <summary>
  188. /// Enables or disables profiled translation cache persistency
  189. /// </summary>
  190. public ReactiveObject<bool> EnablePtc { get; private set; }
  191. /// <summary>
  192. /// Enables or disables guest Internet access
  193. /// </summary>
  194. public ReactiveObject<bool> EnableInternetAccess { get; private set; }
  195. /// <summary>
  196. /// Enables integrity checks on Game content files
  197. /// </summary>
  198. public ReactiveObject<bool> EnableFsIntegrityChecks { get; private set; }
  199. /// <summary>
  200. /// Enables FS access log output to the console. Possible modes are 0-3
  201. /// </summary>
  202. public ReactiveObject<int> FsGlobalAccessLogMode { get; private set; }
  203. /// <summary>
  204. /// The selected audio backend
  205. /// </summary>
  206. public ReactiveObject<AudioBackend> AudioBackend { get; private set; }
  207. /// <summary>
  208. /// The audio backend volume
  209. /// </summary>
  210. public ReactiveObject<float> AudioVolume { get; private set; }
  211. /// <summary>
  212. /// The selected memory manager mode
  213. /// </summary>
  214. public ReactiveObject<MemoryManagerMode> MemoryManagerMode { get; private set; }
  215. /// <summary>
  216. /// Defines the amount of RAM available on the emulated system, and how it is distributed
  217. /// </summary>
  218. public ReactiveObject<bool> ExpandRam { get; private set; }
  219. /// <summary>
  220. /// Enable or disable ignoring missing services
  221. /// </summary>
  222. public ReactiveObject<bool> IgnoreMissingServices { get; private set; }
  223. public SystemSection()
  224. {
  225. Language = new ReactiveObject<Language>();
  226. Region = new ReactiveObject<Region>();
  227. TimeZone = new ReactiveObject<string>();
  228. SystemTimeOffset = new ReactiveObject<long>();
  229. EnableDockedMode = new ReactiveObject<bool>();
  230. EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode));
  231. EnablePtc = new ReactiveObject<bool>();
  232. EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc));
  233. EnableInternetAccess = new ReactiveObject<bool>();
  234. EnableInternetAccess.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableInternetAccess));
  235. EnableFsIntegrityChecks = new ReactiveObject<bool>();
  236. EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableFsIntegrityChecks));
  237. FsGlobalAccessLogMode = new ReactiveObject<int>();
  238. FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(FsGlobalAccessLogMode));
  239. AudioBackend = new ReactiveObject<AudioBackend>();
  240. AudioBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioBackend));
  241. MemoryManagerMode = new ReactiveObject<MemoryManagerMode>();
  242. MemoryManagerMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(MemoryManagerMode));
  243. ExpandRam = new ReactiveObject<bool>();
  244. ExpandRam.Event += static (sender, e) => LogValueChange(sender, e, nameof(ExpandRam));
  245. IgnoreMissingServices = new ReactiveObject<bool>();
  246. IgnoreMissingServices.Event += static (sender, e) => LogValueChange(sender, e, nameof(IgnoreMissingServices));
  247. AudioVolume = new ReactiveObject<float>();
  248. AudioVolume.Event += static (sender, e) => LogValueChange(sender, e, nameof(AudioVolume));
  249. }
  250. }
  251. /// <summary>
  252. /// Hid configuration section
  253. /// </summary>
  254. public class HidSection
  255. {
  256. /// <summary>
  257. /// Enable or disable keyboard support (Independent from controllers binding)
  258. /// </summary>
  259. public ReactiveObject<bool> EnableKeyboard { get; private set; }
  260. /// <summary>
  261. /// Enable or disable mouse support (Independent from controllers binding)
  262. /// </summary>
  263. public ReactiveObject<bool> EnableMouse { get; private set; }
  264. /// <summary>
  265. /// Hotkey Keyboard Bindings
  266. /// </summary>
  267. public ReactiveObject<KeyboardHotkeys> Hotkeys { get; private set; }
  268. /// <summary>
  269. /// Input device configuration.
  270. /// NOTE: This ReactiveObject won't issue an event when the List has elements added or removed.
  271. /// TODO: Implement a ReactiveList class.
  272. /// </summary>
  273. public ReactiveObject<List<InputConfig>> InputConfig { get; private set; }
  274. public HidSection()
  275. {
  276. EnableKeyboard = new ReactiveObject<bool>();
  277. EnableMouse = new ReactiveObject<bool>();
  278. Hotkeys = new ReactiveObject<KeyboardHotkeys>();
  279. InputConfig = new ReactiveObject<List<InputConfig>>();
  280. }
  281. }
  282. /// <summary>
  283. /// Graphics configuration section
  284. /// </summary>
  285. public class GraphicsSection
  286. {
  287. /// <summary>
  288. /// Whether or not backend threading is enabled. The "Auto" setting will determine whether threading should be enabled at runtime.
  289. /// </summary>
  290. public ReactiveObject<BackendThreading> BackendThreading { get; private set; }
  291. /// <summary>
  292. /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide.
  293. /// </summary>
  294. public ReactiveObject<float> MaxAnisotropy { get; private set; }
  295. /// <summary>
  296. /// Aspect Ratio applied to the renderer window.
  297. /// </summary>
  298. public ReactiveObject<AspectRatio> AspectRatio { get; private set; }
  299. /// <summary>
  300. /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead.
  301. /// </summary>
  302. public ReactiveObject<int> ResScale { get; private set; }
  303. /// <summary>
  304. /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1.
  305. /// </summary>
  306. public ReactiveObject<float> ResScaleCustom { get; private set; }
  307. /// <summary>
  308. /// Dumps shaders in this local directory
  309. /// </summary>
  310. public ReactiveObject<string> ShadersDumpPath { get; private set; }
  311. /// <summary>
  312. /// Enables or disables Vertical Sync
  313. /// </summary>
  314. public ReactiveObject<bool> EnableVsync { get; private set; }
  315. /// <summary>
  316. /// Enables or disables Shader cache
  317. /// </summary>
  318. public ReactiveObject<bool> EnableShaderCache { get; private set; }
  319. public GraphicsSection()
  320. {
  321. BackendThreading = new ReactiveObject<BackendThreading>();
  322. BackendThreading.Event += static (sender, e) => LogValueChange(sender, e, nameof(BackendThreading));
  323. ResScale = new ReactiveObject<int>();
  324. ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale));
  325. ResScaleCustom = new ReactiveObject<float>();
  326. ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom));
  327. MaxAnisotropy = new ReactiveObject<float>();
  328. MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy));
  329. AspectRatio = new ReactiveObject<AspectRatio>();
  330. AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio));
  331. ShadersDumpPath = new ReactiveObject<string>();
  332. EnableVsync = new ReactiveObject<bool>();
  333. EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync));
  334. EnableShaderCache = new ReactiveObject<bool>();
  335. EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache));
  336. }
  337. }
  338. /// <summary>
  339. /// The default configuration instance
  340. /// </summary>
  341. public static ConfigurationState Instance { get; private set; }
  342. /// <summary>
  343. /// The Ui section
  344. /// </summary>
  345. public UiSection Ui { get; private set; }
  346. /// <summary>
  347. /// The Logger section
  348. /// </summary>
  349. public LoggerSection Logger { get; private set; }
  350. /// <summary>
  351. /// The System section
  352. /// </summary>
  353. public SystemSection System { get; private set; }
  354. /// <summary>
  355. /// The Graphics section
  356. /// </summary>
  357. public GraphicsSection Graphics { get; private set; }
  358. /// <summary>
  359. /// The Hid section
  360. /// </summary>
  361. public HidSection Hid { get; private set; }
  362. /// <summary>
  363. /// Enables or disables Discord Rich Presence
  364. /// </summary>
  365. public ReactiveObject<bool> EnableDiscordIntegration { get; private set; }
  366. /// <summary>
  367. /// Checks for updates when Ryujinx starts when enabled
  368. /// </summary>
  369. public ReactiveObject<bool> CheckUpdatesOnStart { get; private set; }
  370. /// <summary>
  371. /// Show "Confirm Exit" Dialog
  372. /// </summary>
  373. public ReactiveObject<bool> ShowConfirmExit { get; private set; }
  374. /// <summary>
  375. /// Hide Cursor on Idle
  376. /// </summary>
  377. public ReactiveObject<bool> HideCursorOnIdle { get; private set; }
  378. private ConfigurationState()
  379. {
  380. Ui = new UiSection();
  381. Logger = new LoggerSection();
  382. System = new SystemSection();
  383. Graphics = new GraphicsSection();
  384. Hid = new HidSection();
  385. EnableDiscordIntegration = new ReactiveObject<bool>();
  386. CheckUpdatesOnStart = new ReactiveObject<bool>();
  387. ShowConfirmExit = new ReactiveObject<bool>();
  388. HideCursorOnIdle = new ReactiveObject<bool>();
  389. }
  390. public ConfigurationFileFormat ToFileFormat()
  391. {
  392. ConfigurationFileFormat configurationFile = new ConfigurationFileFormat
  393. {
  394. Version = ConfigurationFileFormat.CurrentVersion,
  395. EnableFileLog = Logger.EnableFileLog,
  396. BackendThreading = Graphics.BackendThreading,
  397. ResScale = Graphics.ResScale,
  398. ResScaleCustom = Graphics.ResScaleCustom,
  399. MaxAnisotropy = Graphics.MaxAnisotropy,
  400. AspectRatio = Graphics.AspectRatio,
  401. GraphicsShadersDumpPath = Graphics.ShadersDumpPath,
  402. LoggingEnableDebug = Logger.EnableDebug,
  403. LoggingEnableStub = Logger.EnableStub,
  404. LoggingEnableInfo = Logger.EnableInfo,
  405. LoggingEnableWarn = Logger.EnableWarn,
  406. LoggingEnableError = Logger.EnableError,
  407. LoggingEnableTrace = Logger.EnableTrace,
  408. LoggingEnableGuest = Logger.EnableGuest,
  409. LoggingEnableFsAccessLog = Logger.EnableFsAccessLog,
  410. LoggingFilteredClasses = Logger.FilteredClasses,
  411. LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel,
  412. SystemLanguage = System.Language,
  413. SystemRegion = System.Region,
  414. SystemTimeZone = System.TimeZone,
  415. SystemTimeOffset = System.SystemTimeOffset,
  416. DockedMode = System.EnableDockedMode,
  417. EnableDiscordIntegration = EnableDiscordIntegration,
  418. CheckUpdatesOnStart = CheckUpdatesOnStart,
  419. ShowConfirmExit = ShowConfirmExit,
  420. HideCursorOnIdle = HideCursorOnIdle,
  421. EnableVsync = Graphics.EnableVsync,
  422. EnableShaderCache = Graphics.EnableShaderCache,
  423. EnablePtc = System.EnablePtc,
  424. EnableInternetAccess = System.EnableInternetAccess,
  425. EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
  426. FsGlobalAccessLogMode = System.FsGlobalAccessLogMode,
  427. AudioBackend = System.AudioBackend,
  428. AudioVolume = System.AudioVolume,
  429. MemoryManagerMode = System.MemoryManagerMode,
  430. ExpandRam = System.ExpandRam,
  431. IgnoreMissingServices = System.IgnoreMissingServices,
  432. GuiColumns = new GuiColumns
  433. {
  434. FavColumn = Ui.GuiColumns.FavColumn,
  435. IconColumn = Ui.GuiColumns.IconColumn,
  436. AppColumn = Ui.GuiColumns.AppColumn,
  437. DevColumn = Ui.GuiColumns.DevColumn,
  438. VersionColumn = Ui.GuiColumns.VersionColumn,
  439. TimePlayedColumn = Ui.GuiColumns.TimePlayedColumn,
  440. LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn,
  441. FileExtColumn = Ui.GuiColumns.FileExtColumn,
  442. FileSizeColumn = Ui.GuiColumns.FileSizeColumn,
  443. PathColumn = Ui.GuiColumns.PathColumn,
  444. },
  445. ColumnSort = new ColumnSort
  446. {
  447. SortColumnId = Ui.ColumnSort.SortColumnId,
  448. SortAscending = Ui.ColumnSort.SortAscending
  449. },
  450. GameDirs = Ui.GameDirs,
  451. EnableCustomTheme = Ui.EnableCustomTheme,
  452. CustomThemePath = Ui.CustomThemePath,
  453. StartFullscreen = Ui.StartFullscreen,
  454. ShowConsole = Ui.ShowConsole,
  455. EnableKeyboard = Hid.EnableKeyboard,
  456. EnableMouse = Hid.EnableMouse,
  457. Hotkeys = Hid.Hotkeys,
  458. KeyboardConfig = new List<object>(),
  459. ControllerConfig = new List<object>(),
  460. InputConfig = Hid.InputConfig,
  461. };
  462. return configurationFile;
  463. }
  464. public void LoadDefault()
  465. {
  466. Logger.EnableFileLog.Value = true;
  467. Graphics.BackendThreading.Value = BackendThreading.Auto;
  468. Graphics.ResScale.Value = 1;
  469. Graphics.ResScaleCustom.Value = 1.0f;
  470. Graphics.MaxAnisotropy.Value = -1.0f;
  471. Graphics.AspectRatio.Value = AspectRatio.Fixed16x9;
  472. Graphics.ShadersDumpPath.Value = "";
  473. Logger.EnableDebug.Value = false;
  474. Logger.EnableStub.Value = true;
  475. Logger.EnableInfo.Value = true;
  476. Logger.EnableWarn.Value = true;
  477. Logger.EnableError.Value = true;
  478. Logger.EnableTrace.Value = false;
  479. Logger.EnableGuest.Value = true;
  480. Logger.EnableFsAccessLog.Value = false;
  481. Logger.FilteredClasses.Value = Array.Empty<LogClass>();
  482. Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None;
  483. System.Language.Value = Language.AmericanEnglish;
  484. System.Region.Value = Region.USA;
  485. System.TimeZone.Value = "UTC";
  486. System.SystemTimeOffset.Value = 0;
  487. System.EnableDockedMode.Value = true;
  488. EnableDiscordIntegration.Value = true;
  489. CheckUpdatesOnStart.Value = true;
  490. ShowConfirmExit.Value = true;
  491. HideCursorOnIdle.Value = false;
  492. Graphics.EnableVsync.Value = true;
  493. Graphics.EnableShaderCache.Value = true;
  494. System.EnablePtc.Value = true;
  495. System.EnableInternetAccess.Value = false;
  496. System.EnableFsIntegrityChecks.Value = true;
  497. System.FsGlobalAccessLogMode.Value = 0;
  498. System.AudioBackend.Value = AudioBackend.SDL2;
  499. System.AudioVolume.Value = 1;
  500. System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe;
  501. System.ExpandRam.Value = false;
  502. System.IgnoreMissingServices.Value = false;
  503. Ui.GuiColumns.FavColumn.Value = true;
  504. Ui.GuiColumns.IconColumn.Value = true;
  505. Ui.GuiColumns.AppColumn.Value = true;
  506. Ui.GuiColumns.DevColumn.Value = true;
  507. Ui.GuiColumns.VersionColumn.Value = true;
  508. Ui.GuiColumns.TimePlayedColumn.Value = true;
  509. Ui.GuiColumns.LastPlayedColumn.Value = true;
  510. Ui.GuiColumns.FileExtColumn.Value = true;
  511. Ui.GuiColumns.FileSizeColumn.Value = true;
  512. Ui.GuiColumns.PathColumn.Value = true;
  513. Ui.ColumnSort.SortColumnId.Value = 0;
  514. Ui.ColumnSort.SortAscending.Value = false;
  515. Ui.GameDirs.Value = new List<string>();
  516. Ui.EnableCustomTheme.Value = false;
  517. Ui.CustomThemePath.Value = "";
  518. Ui.StartFullscreen.Value = false;
  519. Ui.ShowConsole.Value = true;
  520. Hid.EnableKeyboard.Value = false;
  521. Hid.EnableMouse.Value = false;
  522. Hid.Hotkeys.Value = new KeyboardHotkeys
  523. {
  524. ToggleVsync = Key.Tab,
  525. ToggleMute = Key.F2,
  526. Screenshot = Key.F8,
  527. ShowUi = Key.F4,
  528. Pause = Key.F5
  529. };
  530. Hid.InputConfig.Value = new List<InputConfig>
  531. {
  532. new StandardKeyboardInputConfig
  533. {
  534. Version = InputConfig.CurrentVersion,
  535. Backend = InputBackendType.WindowKeyboard,
  536. Id = "0",
  537. PlayerIndex = PlayerIndex.Player1,
  538. ControllerType = ControllerType.JoyconPair,
  539. LeftJoycon = new LeftJoyconCommonConfig<Key>
  540. {
  541. DpadUp = Key.Up,
  542. DpadDown = Key.Down,
  543. DpadLeft = Key.Left,
  544. DpadRight = Key.Right,
  545. ButtonMinus = Key.Minus,
  546. ButtonL = Key.E,
  547. ButtonZl = Key.Q,
  548. ButtonSl = Key.Unbound,
  549. ButtonSr = Key.Unbound
  550. },
  551. LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
  552. {
  553. StickUp = Key.W,
  554. StickDown = Key.S,
  555. StickLeft = Key.A,
  556. StickRight = Key.D,
  557. StickButton = Key.F,
  558. },
  559. RightJoycon = new RightJoyconCommonConfig<Key>
  560. {
  561. ButtonA = Key.Z,
  562. ButtonB = Key.X,
  563. ButtonX = Key.C,
  564. ButtonY = Key.V,
  565. ButtonPlus = Key.Plus,
  566. ButtonR = Key.U,
  567. ButtonZr = Key.O,
  568. ButtonSl = Key.Unbound,
  569. ButtonSr = Key.Unbound
  570. },
  571. RightJoyconStick = new JoyconConfigKeyboardStick<Key>
  572. {
  573. StickUp = Key.I,
  574. StickDown = Key.K,
  575. StickLeft = Key.J,
  576. StickRight = Key.L,
  577. StickButton = Key.H,
  578. }
  579. }
  580. };
  581. }
  582. public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath)
  583. {
  584. bool configurationFileUpdated = false;
  585. if (configurationFileFormat.Version < 0 || configurationFileFormat.Version > ConfigurationFileFormat.CurrentVersion)
  586. {
  587. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default.");
  588. LoadDefault();
  589. return;
  590. }
  591. if (configurationFileFormat.Version < 2)
  592. {
  593. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2.");
  594. configurationFileFormat.SystemRegion = Region.USA;
  595. configurationFileUpdated = true;
  596. }
  597. if (configurationFileFormat.Version < 3)
  598. {
  599. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3.");
  600. configurationFileFormat.SystemTimeZone = "UTC";
  601. configurationFileUpdated = true;
  602. }
  603. if (configurationFileFormat.Version < 4)
  604. {
  605. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4.");
  606. configurationFileFormat.MaxAnisotropy = -1;
  607. configurationFileUpdated = true;
  608. }
  609. if (configurationFileFormat.Version < 5)
  610. {
  611. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5.");
  612. configurationFileFormat.SystemTimeOffset = 0;
  613. configurationFileUpdated = true;
  614. }
  615. if (configurationFileFormat.Version < 8)
  616. {
  617. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8.");
  618. configurationFileFormat.EnablePtc = true;
  619. configurationFileUpdated = true;
  620. }
  621. if (configurationFileFormat.Version < 9)
  622. {
  623. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9.");
  624. configurationFileFormat.ColumnSort = new ColumnSort
  625. {
  626. SortColumnId = 0,
  627. SortAscending = false
  628. };
  629. configurationFileFormat.Hotkeys = new KeyboardHotkeys
  630. {
  631. ToggleVsync = Key.Tab
  632. };
  633. configurationFileUpdated = true;
  634. }
  635. if (configurationFileFormat.Version < 10)
  636. {
  637. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10.");
  638. configurationFileFormat.AudioBackend = AudioBackend.OpenAl;
  639. configurationFileUpdated = true;
  640. }
  641. if (configurationFileFormat.Version < 11)
  642. {
  643. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11.");
  644. configurationFileFormat.ResScale = 1;
  645. configurationFileFormat.ResScaleCustom = 1.0f;
  646. configurationFileUpdated = true;
  647. }
  648. if (configurationFileFormat.Version < 12)
  649. {
  650. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12.");
  651. configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None;
  652. configurationFileUpdated = true;
  653. }
  654. if (configurationFileFormat.Version < 14)
  655. {
  656. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14.");
  657. configurationFileFormat.CheckUpdatesOnStart = true;
  658. configurationFileUpdated = true;
  659. }
  660. if (configurationFileFormat.Version < 16)
  661. {
  662. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16.");
  663. configurationFileFormat.EnableShaderCache = true;
  664. configurationFileUpdated = true;
  665. }
  666. if (configurationFileFormat.Version < 17)
  667. {
  668. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17.");
  669. configurationFileFormat.StartFullscreen = false;
  670. configurationFileUpdated = true;
  671. }
  672. if (configurationFileFormat.Version < 18)
  673. {
  674. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18.");
  675. configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9;
  676. configurationFileUpdated = true;
  677. }
  678. if (configurationFileFormat.Version < 20)
  679. {
  680. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20.");
  681. configurationFileFormat.ShowConfirmExit = true;
  682. configurationFileUpdated = true;
  683. }
  684. if (configurationFileFormat.Version < 22)
  685. {
  686. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22.");
  687. configurationFileFormat.HideCursorOnIdle = false;
  688. configurationFileUpdated = true;
  689. }
  690. if (configurationFileFormat.Version < 24)
  691. {
  692. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24.");
  693. configurationFileFormat.InputConfig = new List<InputConfig>
  694. {
  695. new StandardKeyboardInputConfig
  696. {
  697. Version = InputConfig.CurrentVersion,
  698. Backend = InputBackendType.WindowKeyboard,
  699. Id = "0",
  700. PlayerIndex = PlayerIndex.Player1,
  701. ControllerType = ControllerType.JoyconPair,
  702. LeftJoycon = new LeftJoyconCommonConfig<Key>
  703. {
  704. DpadUp = Key.Up,
  705. DpadDown = Key.Down,
  706. DpadLeft = Key.Left,
  707. DpadRight = Key.Right,
  708. ButtonMinus = Key.Minus,
  709. ButtonL = Key.E,
  710. ButtonZl = Key.Q,
  711. ButtonSl = Key.Unbound,
  712. ButtonSr = Key.Unbound
  713. },
  714. LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
  715. {
  716. StickUp = Key.W,
  717. StickDown = Key.S,
  718. StickLeft = Key.A,
  719. StickRight = Key.D,
  720. StickButton = Key.F,
  721. },
  722. RightJoycon = new RightJoyconCommonConfig<Key>
  723. {
  724. ButtonA = Key.Z,
  725. ButtonB = Key.X,
  726. ButtonX = Key.C,
  727. ButtonY = Key.V,
  728. ButtonPlus = Key.Plus,
  729. ButtonR = Key.U,
  730. ButtonZr = Key.O,
  731. ButtonSl = Key.Unbound,
  732. ButtonSr = Key.Unbound
  733. },
  734. RightJoyconStick = new JoyconConfigKeyboardStick<Key>
  735. {
  736. StickUp = Key.I,
  737. StickDown = Key.K,
  738. StickLeft = Key.J,
  739. StickRight = Key.L,
  740. StickButton = Key.H,
  741. }
  742. }
  743. };
  744. configurationFileUpdated = true;
  745. }
  746. if (configurationFileFormat.Version < 25)
  747. {
  748. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25.");
  749. configurationFileUpdated = true;
  750. }
  751. if (configurationFileFormat.Version < 26)
  752. {
  753. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 26.");
  754. configurationFileFormat.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe;
  755. configurationFileUpdated = true;
  756. }
  757. if (configurationFileFormat.Version < 27)
  758. {
  759. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 27.");
  760. configurationFileFormat.EnableMouse = false;
  761. configurationFileUpdated = true;
  762. }
  763. if (configurationFileFormat.Version < 28)
  764. {
  765. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 28.");
  766. configurationFileFormat.Hotkeys = new KeyboardHotkeys
  767. {
  768. ToggleVsync = Key.Tab,
  769. Screenshot = Key.F8
  770. };
  771. configurationFileUpdated = true;
  772. }
  773. if (configurationFileFormat.Version < 29)
  774. {
  775. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29.");
  776. configurationFileFormat.Hotkeys = new KeyboardHotkeys
  777. {
  778. ToggleVsync = Key.Tab,
  779. Screenshot = Key.F8,
  780. ShowUi = Key.F4
  781. };
  782. configurationFileUpdated = true;
  783. }
  784. if (configurationFileFormat.Version < 30)
  785. {
  786. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 30.");
  787. foreach (InputConfig config in configurationFileFormat.InputConfig)
  788. {
  789. if (config is StandardControllerInputConfig controllerConfig)
  790. {
  791. controllerConfig.Rumble = new RumbleConfigController
  792. {
  793. EnableRumble = false,
  794. StrongRumble = 1f,
  795. WeakRumble = 1f
  796. };
  797. }
  798. }
  799. configurationFileUpdated = true;
  800. }
  801. if (configurationFileFormat.Version < 31)
  802. {
  803. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 31.");
  804. configurationFileFormat.BackendThreading = BackendThreading.Auto;
  805. configurationFileUpdated = true;
  806. }
  807. if (configurationFileFormat.Version < 32)
  808. {
  809. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 32.");
  810. configurationFileFormat.Hotkeys = new KeyboardHotkeys
  811. {
  812. ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
  813. Screenshot = configurationFileFormat.Hotkeys.Screenshot,
  814. ShowUi = configurationFileFormat.Hotkeys.ShowUi,
  815. Pause = Key.F5
  816. };
  817. configurationFileUpdated = true;
  818. }
  819. if (configurationFileFormat.Version < 33)
  820. {
  821. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 33.");
  822. configurationFileFormat.Hotkeys = new KeyboardHotkeys
  823. {
  824. ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
  825. Screenshot = configurationFileFormat.Hotkeys.Screenshot,
  826. ShowUi = configurationFileFormat.Hotkeys.ShowUi,
  827. Pause = configurationFileFormat.Hotkeys.Pause,
  828. ToggleMute = Key.F2
  829. };
  830. configurationFileFormat.AudioVolume = 1;
  831. configurationFileUpdated = true;
  832. }
  833. if (configurationFileFormat.Version < 34)
  834. {
  835. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 34.");
  836. configurationFileFormat.EnableInternetAccess = false;
  837. configurationFileUpdated = true;
  838. }
  839. if (configurationFileFormat.Version < 35)
  840. {
  841. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 35.");
  842. foreach (InputConfig config in configurationFileFormat.InputConfig)
  843. {
  844. if (config is StandardControllerInputConfig controllerConfig)
  845. {
  846. controllerConfig.RangeLeft = 1.0f;
  847. controllerConfig.RangeRight = 1.0f;
  848. }
  849. }
  850. configurationFileUpdated = true;
  851. }
  852. if (configurationFileFormat.Version < 36)
  853. {
  854. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 36.");
  855. configurationFileFormat.LoggingEnableTrace = false;
  856. configurationFileUpdated = true;
  857. }
  858. if (configurationFileFormat.Version < 37)
  859. {
  860. Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37.");
  861. configurationFileFormat.ShowConsole = true;
  862. configurationFileUpdated = true;
  863. }
  864. Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
  865. Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
  866. Graphics.ResScale.Value = configurationFileFormat.ResScale;
  867. Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
  868. Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy;
  869. Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio;
  870. Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath;
  871. Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug;
  872. Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub;
  873. Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo;
  874. Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn;
  875. Logger.EnableError.Value = configurationFileFormat.LoggingEnableError;
  876. Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace;
  877. Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest;
  878. Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog;
  879. Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses;
  880. Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel;
  881. System.Language.Value = configurationFileFormat.SystemLanguage;
  882. System.Region.Value = configurationFileFormat.SystemRegion;
  883. System.TimeZone.Value = configurationFileFormat.SystemTimeZone;
  884. System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
  885. System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
  886. EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
  887. CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
  888. ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit;
  889. HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle;
  890. Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
  891. Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
  892. System.EnablePtc.Value = configurationFileFormat.EnablePtc;
  893. System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
  894. System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
  895. System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
  896. System.AudioBackend.Value = configurationFileFormat.AudioBackend;
  897. System.AudioVolume.Value = configurationFileFormat.AudioVolume;
  898. System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode;
  899. System.ExpandRam.Value = configurationFileFormat.ExpandRam;
  900. System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices;
  901. Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn;
  902. Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn;
  903. Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn;
  904. Ui.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn;
  905. Ui.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn;
  906. Ui.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn;
  907. Ui.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn;
  908. Ui.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn;
  909. Ui.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn;
  910. Ui.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn;
  911. Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId;
  912. Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending;
  913. Ui.GameDirs.Value = configurationFileFormat.GameDirs;
  914. Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme;
  915. Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath;
  916. Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
  917. Ui.ShowConsole.Value = configurationFileFormat.ShowConsole;
  918. Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
  919. Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
  920. Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;
  921. Hid.InputConfig.Value = configurationFileFormat.InputConfig;
  922. if (Hid.InputConfig.Value == null)
  923. {
  924. Hid.InputConfig.Value = new List<InputConfig>();
  925. }
  926. if (configurationFileUpdated)
  927. {
  928. ToFileFormat().SaveConfig(configurationFilePath);
  929. Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
  930. }
  931. }
  932. private static void LogValueChange<T>(object sender, ReactiveEventArgs<T> eventArgs, string valueName)
  933. {
  934. Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}");
  935. }
  936. public static void Initialize()
  937. {
  938. if (Instance != null)
  939. {
  940. throw new InvalidOperationException("Configuration is already initialized");
  941. }
  942. Instance = new ConfigurationState();
  943. }
  944. }
  945. }