DownloadableContentsHelper.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using LibHac.Common;
  2. using LibHac.Fs;
  3. using LibHac.Fs.Fsa;
  4. using LibHac.Tools.FsSystem;
  5. using LibHac.Tools.FsSystem.NcaUtils;
  6. using Ryujinx.Ava.Common.Models;
  7. using Ryujinx.Common.Configuration;
  8. using Ryujinx.Common.Logging;
  9. using Ryujinx.Common.Utilities;
  10. using Ryujinx.HLE.FileSystem;
  11. using Ryujinx.HLE.Utilities;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.IO;
  15. using Path = System.IO.Path;
  16. namespace Ryujinx.Ava.Utilities
  17. {
  18. public static class DownloadableContentsHelper
  19. {
  20. private static readonly DownloadableContentJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
  21. public static List<(DownloadableContentModel, bool IsEnabled)> LoadDownloadableContentsJson(VirtualFileSystem vfs, ulong applicationIdBase)
  22. {
  23. var downloadableContentJsonPath = PathToGameDLCJson(applicationIdBase);
  24. if (!File.Exists(downloadableContentJsonPath))
  25. {
  26. return [];
  27. }
  28. try
  29. {
  30. var downloadableContentContainerList = JsonHelper.DeserializeFromFile(downloadableContentJsonPath,
  31. _serializerContext.ListDownloadableContentContainer);
  32. return LoadDownloadableContents(vfs, downloadableContentContainerList);
  33. }
  34. catch
  35. {
  36. Logger.Error?.Print(LogClass.Configuration, "Downloadable Content JSON failed to deserialize.");
  37. return [];
  38. }
  39. }
  40. public static void SaveDownloadableContentsJson(ulong applicationIdBase, List<(DownloadableContentModel, bool IsEnabled)> dlcs)
  41. {
  42. DownloadableContentContainer container = default;
  43. List<DownloadableContentContainer> downloadableContentContainerList = new();
  44. foreach ((DownloadableContentModel dlc, bool isEnabled) in dlcs)
  45. {
  46. if (container.ContainerPath != dlc.ContainerPath)
  47. {
  48. if (!string.IsNullOrWhiteSpace(container.ContainerPath))
  49. {
  50. downloadableContentContainerList.Add(container);
  51. }
  52. container = new DownloadableContentContainer
  53. {
  54. ContainerPath = dlc.ContainerPath,
  55. DownloadableContentNcaList = [],
  56. };
  57. }
  58. container.DownloadableContentNcaList.Add(new DownloadableContentNca
  59. {
  60. Enabled = isEnabled,
  61. TitleId = dlc.TitleId,
  62. FullPath = dlc.FullPath,
  63. });
  64. }
  65. if (!string.IsNullOrWhiteSpace(container.ContainerPath))
  66. {
  67. downloadableContentContainerList.Add(container);
  68. }
  69. var downloadableContentJsonPath = PathToGameDLCJson(applicationIdBase);
  70. JsonHelper.SerializeToFile(downloadableContentJsonPath, downloadableContentContainerList, _serializerContext.ListDownloadableContentContainer);
  71. }
  72. private static List<(DownloadableContentModel, bool IsEnabled)> LoadDownloadableContents(VirtualFileSystem vfs, List<DownloadableContentContainer> downloadableContentContainers)
  73. {
  74. var result = new List<(DownloadableContentModel, bool IsEnabled)>();
  75. foreach (DownloadableContentContainer downloadableContentContainer in downloadableContentContainers)
  76. {
  77. if (!File.Exists(downloadableContentContainer.ContainerPath))
  78. {
  79. continue;
  80. }
  81. using IFileSystem partitionFileSystem = PartitionFileSystemUtils.OpenApplicationFileSystem(downloadableContentContainer.ContainerPath, vfs);
  82. foreach (DownloadableContentNca downloadableContentNca in downloadableContentContainer.DownloadableContentNcaList)
  83. {
  84. using UniqueRef<IFile> ncaFile = new();
  85. partitionFileSystem.OpenFile(ref ncaFile.Ref, downloadableContentNca.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
  86. Nca nca = TryOpenNca(vfs, ncaFile.Get.AsStorage());
  87. if (nca == null)
  88. {
  89. continue;
  90. }
  91. var content = new DownloadableContentModel(nca.Header.TitleId,
  92. downloadableContentContainer.ContainerPath,
  93. downloadableContentNca.FullPath);
  94. result.Add((content, downloadableContentNca.Enabled));
  95. }
  96. }
  97. return result;
  98. }
  99. private static Nca TryOpenNca(VirtualFileSystem vfs, IStorage ncaStorage)
  100. {
  101. try
  102. {
  103. return new Nca(vfs.KeySet, ncaStorage);
  104. }
  105. catch (Exception) { }
  106. return null;
  107. }
  108. private static string PathToGameDLCJson(ulong applicationIdBase)
  109. {
  110. return Path.Combine(AppDataManager.GamesDirPath, applicationIdBase.ToString("x16"), "dlc.json");
  111. }
  112. }
  113. }