Allow modding AddOnContent RomFS (#2024)

Simplify some misc logic
This commit is contained in:
mageven 2021-02-20 05:55:01 +05:30 committed by GitHub
parent d9b3f3fa3a
commit 65eb9901f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 38 deletions

View file

@ -72,9 +72,6 @@ namespace Ryujinx.HLE.HOS
_fileSystem = fileSystem; _fileSystem = fileSystem;
_controlData = new BlitStruct<ApplicationControlProperty>(1); _controlData = new BlitStruct<ApplicationControlProperty>(1);
// Clear Mods cache
_fileSystem.ModLoader.Clear();
} }
public void LoadCart(string exeFsDir, string romFsFile = null) public void LoadCart(string exeFsDir, string romFsFile = null)
@ -88,7 +85,7 @@ namespace Ryujinx.HLE.HOS
Npdm metaData = ReadNpdm(codeFs); Npdm metaData = ReadNpdm(codeFs);
_fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.ModLoader.GetModsBasePath()); _fileSystem.ModLoader.CollectMods(new[] { TitleId }, _fileSystem.ModLoader.GetModsBasePath());
if (TitleId != 0) if (TitleId != 0)
{ {
@ -377,7 +374,7 @@ namespace Ryujinx.HLE.HOS
Npdm metaData = ReadNpdm(codeFs); Npdm metaData = ReadNpdm(codeFs);
_fileSystem.ModLoader.CollectMods(TitleId, _fileSystem.ModLoader.GetModsBasePath()); _fileSystem.ModLoader.CollectMods(_contentManager.GetAocTitleIds().Prepend(TitleId), _fileSystem.ModLoader.GetModsBasePath());
if (controlNca != null) if (controlNca != null)
{ {

View file

@ -66,7 +66,7 @@ namespace Ryujinx.HLE.HOS
public List<Mod<DirectoryInfo>> NroPatches { get; } public List<Mod<DirectoryInfo>> NroPatches { get; }
public List<Mod<DirectoryInfo>> KipPatches { get; } public List<Mod<DirectoryInfo>> KipPatches { get; }
public HashSet<string> SearchedDirs { get; } internal bool Initialized { get; set; }
public PatchCache() public PatchCache()
{ {
@ -74,7 +74,7 @@ namespace Ryujinx.HLE.HOS
NroPatches = new List<Mod<DirectoryInfo>>(); NroPatches = new List<Mod<DirectoryInfo>>();
KipPatches = new List<Mod<DirectoryInfo>>(); KipPatches = new List<Mod<DirectoryInfo>>();
SearchedDirs = new HashSet<string>(); Initialized = false;
} }
} }
@ -140,9 +140,9 @@ namespace Ryujinx.HLE.HOS
} }
// Static Query Methods // Static Query Methods
public static void QueryPatchDirs(PatchCache cache, DirectoryInfo patchDir, DirectoryInfo searchDir) public static void QueryPatchDirs(PatchCache cache, DirectoryInfo patchDir)
{ {
if (!patchDir.Exists || cache.SearchedDirs.Contains(searchDir.FullName)) return; if (cache.Initialized || !patchDir.Exists) return;
var patches = cache.KipPatches; var patches = cache.KipPatches;
string type = null; string type = null;
@ -216,7 +216,7 @@ namespace Ryujinx.HLE.HOS
{ {
if (!contentsDir.Exists) return; if (!contentsDir.Exists) return;
Logger.Info?.Print(LogClass.ModLoader, $"Searching mods for Title {titleId:X16}"); Logger.Info?.Print(LogClass.ModLoader, $"Searching mods for {((titleId & 0x1000) != 0 ? "DLC" : "Title")} {titleId:X16}");
var titleDir = FindTitleDir(contentsDir, $"{titleId:x16}"); var titleDir = FindTitleDir(contentsDir, $"{titleId:x16}");
@ -226,26 +226,29 @@ namespace Ryujinx.HLE.HOS
} }
} }
public static void CollectMods(ModCache mods, PatchCache patches, ulong? titleId, params string[] searchDirPaths) // Assumes searchDirPaths don't overlap
public static void CollectMods(Dictionary<ulong, ModCache> modCaches, PatchCache patches, params string[] searchDirPaths)
{ {
static bool IsPatchesDir(string name) => StrEquals(AmsNsoPatchDir, name) || static bool IsPatchesDir(string name) => StrEquals(AmsNsoPatchDir, name) ||
StrEquals(AmsNroPatchDir, name) || StrEquals(AmsNroPatchDir, name) ||
StrEquals(AmsKipPatchDir, name); StrEquals(AmsKipPatchDir, name);
static bool TryQuery(ModCache mods, PatchCache patches, ulong? titleId, DirectoryInfo dir, DirectoryInfo searchDir) static bool IsContentsDir(string name) => StrEquals(AmsContentsDir, name);
{
if (StrEquals(AmsContentsDir, dir.Name))
{
if (titleId.HasValue)
{
QueryContentsDir(mods, dir, (ulong)titleId);
return true; static bool TryQuery(DirectoryInfo searchDir, PatchCache patches, Dictionary<ulong, ModCache> modCaches)
} {
} if (IsContentsDir(searchDir.Name))
else if (IsPatchesDir(dir.Name))
{ {
QueryPatchDirs(patches, dir, searchDir); foreach (var (titleId, cache) in modCaches)
{
QueryContentsDir(cache, searchDir, titleId);
}
return true;
}
else if (IsPatchesDir(searchDir.Name))
{
QueryPatchDirs(patches, searchDir);
return true; return true;
} }
@ -255,34 +258,35 @@ namespace Ryujinx.HLE.HOS
foreach (var path in searchDirPaths) foreach (var path in searchDirPaths)
{ {
var dir = new DirectoryInfo(path); var searchDir = new DirectoryInfo(path);
if (!dir.Exists) if (!searchDir.Exists)
{ {
Logger.Warning?.Print(LogClass.ModLoader, $"Mod Search Dir '{dir.FullName}' doesn't exist"); Logger.Warning?.Print(LogClass.ModLoader, $"Mod Search Dir '{searchDir.FullName}' doesn't exist");
continue; continue;
} }
if (!TryQuery(mods, patches, titleId, dir, dir)) if (!TryQuery(searchDir, patches, modCaches))
{ {
foreach (var subdir in dir.EnumerateDirectories()) foreach (var subdir in searchDir.EnumerateDirectories())
{ {
TryQuery(mods, patches, titleId, subdir, dir); TryQuery(subdir, patches, modCaches);
} }
} }
patches.SearchedDirs.Add(dir.FullName);
} }
patches.Initialized = true;
} }
public void CollectMods(ulong titleId, params string[] searchDirPaths) public void CollectMods(IEnumerable<ulong> titles, params string[] searchDirPaths)
{ {
if (!AppMods.TryGetValue(titleId, out ModCache mods)) Clear();
foreach (ulong titleId in titles)
{ {
mods = new ModCache(); AppMods[titleId] = new ModCache();
AppMods[titleId] = mods;
} }
CollectMods(mods, Patches, titleId, searchDirPaths); CollectMods(AppMods, Patches, searchDirPaths);
} }
internal IStorage ApplyRomFsMods(ulong titleId, IStorage baseStorage) internal IStorage ApplyRomFsMods(ulong titleId, IStorage baseStorage)

View file

@ -400,7 +400,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
{ {
Logger.Info?.Print(LogClass.Loader, $"Opened AddOnContent Data TitleID={titleId:X16}"); Logger.Info?.Print(LogClass.Loader, $"Opened AddOnContent Data TitleID={titleId:X16}");
MakeObject(context, new FileSystemProxy.IStorage(aocStorage)); MakeObject(context, new FileSystemProxy.IStorage(context.Device.FileSystem.ModLoader.ApplyRomFsMods((ulong)titleId, aocStorage)));
return ResultCode.Success; return ResultCode.Success;
} }