Support loading DLC data from XCIs

This commit is contained in:
gdkchan 2019-01-31 15:55:36 -02:00
commit f59ba2180b
4 changed files with 96 additions and 21 deletions

View file

@ -12,17 +12,22 @@ namespace Ryujinx.HLE.FileSystem.Content
{ {
private Dictionary<StorageId, LinkedList<LocationEntry>> _locationEntries; private Dictionary<StorageId, LinkedList<LocationEntry>> _locationEntries;
private Dictionary<string, long> _sharedFontTitleDictionary;
private SortedDictionary<(ulong, ContentType), string> _contentDictionary; private SortedDictionary<(ulong, ContentType), string> _contentDictionary;
private Dictionary<ulong, (int, Nca)> _currentApplicationAocData;
private Dictionary<string, long> _sharedFontTitleDictionary;
private Switch _device; private Switch _device;
public ContentManager(Switch device) public ContentManager(Switch device)
{ {
_contentDictionary = new SortedDictionary<(ulong, ContentType), string>();
_locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>(); _locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>();
_contentDictionary = new SortedDictionary<(ulong, ContentType), string>();
_currentApplicationAocData = new Dictionary<ulong, (int, Nca)>();
_sharedFontTitleDictionary = new Dictionary<string, long> _sharedFontTitleDictionary = new Dictionary<string, long>
{ {
{ "FontStandard", 0x0100000000000811 }, { "FontStandard", 0x0100000000000811 },
@ -293,5 +298,34 @@ namespace Ryujinx.HLE.FileSystem.Content
return locationList.ToList().Find(x => x.TitleId == titleId && x.ContentType == contentType); return locationList.ToList().Find(x => x.TitleId == titleId && x.ContentType == contentType);
} }
public void SetCurrentApplicationAocData(int index, Nca aocData)
{
_currentApplicationAocData.Add(aocData.Header.TitleId, (index, aocData));
}
public Nca GetCurrentApplicationAocData(long titleId)
{
return _currentApplicationAocData[(ulong)titleId].Item2;
}
public int GetCurrentApplicationAocDataCount()
{
return _currentApplicationAocData.Count;
}
public int[] GetCurrentApplicationAocDataIndices()
{
List<int> indices = new List<int>();
foreach ((int index, Nca aocData) tuple in _currentApplicationAocData.Values)
{
indices.Add(tuple.index);
}
indices.Sort();
return indices.ToArray();
}
} }
} }

View file

@ -292,6 +292,8 @@ namespace Ryujinx.HLE.HOS
Nca nca = new Nca(KeySet, ncaStorage, true); Nca nca = new Nca(KeySet, ncaStorage, true);
nca.Filename = fileEntry.Name;
if (nca.Header.ContentType == ContentType.Program) if (nca.Header.ContentType == ContentType.Program)
{ {
if (nca.Sections.Any(x => x?.Type == SectionType.Romfs)) if (nca.Sections.Any(x => x?.Type == SectionType.Romfs))
@ -303,6 +305,10 @@ namespace Ryujinx.HLE.HOS
patchNca = nca; patchNca = nca;
} }
} }
else if (nca.Header.ContentType == ContentType.AocData)
{
ContentManager.SetCurrentApplicationAocData(fileEntry.Index, nca);
}
else if (nca.Header.ContentType == ContentType.Control) else if (nca.Header.ContentType == ContentType.Control)
{ {
controlNca = nca; controlNca = nca;

View file

@ -151,6 +151,19 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
byte[] padding = context.RequestData.ReadBytes(7); byte[] padding = context.RequestData.ReadBytes(7);
long titleId = context.RequestData.ReadInt64(); long titleId = context.RequestData.ReadInt64();
if (storageId == StorageId.None)
{
Nca nca = context.Device.System.ContentManager.GetCurrentApplicationAocData(titleId);
NcaSection romfsSection = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs);
Stream romfsStream = nca.OpenSection(romfsSection.SectionNum, false, context.Device.System.FsIntegrityCheckLevel, false).AsStream();
MakeObject(context, new IStorage(romfsStream));
return 0;
}
ContentType contentType = ContentType.Data; ContentType contentType = ContentType.Data;
StorageId installedStorage = StorageId installedStorage =
@ -176,8 +189,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
if (File.Exists(ncaPath)) if (File.Exists(ncaPath))
{ {
LibHac.IO.IStorage ncaStorage = new FileStream(ncaPath, FileMode.Open, FileAccess.Read).AsStorage(); LibHac.IO.IStorage ncaStorage = new FileStream(ncaPath, FileMode.Open, FileAccess.Read).AsStorage();
Nca nca = new Nca(context.Device.System.KeySet, ncaStorage, false); Nca nca = new Nca(context.Device.System.KeySet, ncaStorage, false);
NcaSection romfsSection = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs); NcaSection romfsSection = nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs);
Stream romfsStream = nca.OpenSection(romfsSection.SectionNum, false, context.Device.System.FsIntegrityCheckLevel, false).AsStream(); Stream romfsStream = nca.OpenSection(romfsSection.SectionNum, false, context.Device.System.FsIntegrityCheckLevel, false).AsStream();
MakeObject(context, new IStorage(romfsStream)); MakeObject(context, new IStorage(romfsStream));

View file

@ -15,26 +15,45 @@ namespace Ryujinx.HLE.HOS.Services.Ns
_commands = new Dictionary<int, ServiceProcessRequest> _commands = new Dictionary<int, ServiceProcessRequest>
{ {
{ 2, CountAddOnContent }, { 2, CountAddOnContent },
{ 3, ListAddOnContent } { 3, ListAddOnContent },
{ 5, GetAddOnContentBaseId },
{ 7, PrepareAddOnContent }
}; };
} }
public static long CountAddOnContent(ServiceCtx context) public static long CountAddOnContent(ServiceCtx context)
{ {
context.ResponseData.Write(0); context.ResponseData.Write(context.Device.System.ContentManager.GetCurrentApplicationAocDataCount());
Logger.PrintStub(LogClass.ServiceNs);
return 0; return 0;
} }
public static long ListAddOnContent(ServiceCtx context) public static long ListAddOnContent(ServiceCtx context)
{ {
Logger.PrintStub(LogClass.ServiceNs); int[] aocIndices = context.Device.System.ContentManager.GetCurrentApplicationAocDataIndices();
//TODO: This is supposed to write a u32 array aswell. for (int index = 0; index < aocIndices.Length; index++)
//It's unknown what it contains. {
context.ResponseData.Write(0); long address = context.Request.ReceiveBuff[0].Position + index * 4;
context.Memory.WriteInt32(address, aocIndices[index]);
}
context.ResponseData.Write(aocIndices.Length);
return 0;
}
public static long GetAddOnContentBaseId(ServiceCtx context)
{
context.ResponseData.Write(context.Process.TitleId + 0x1000);
return 0;
}
public static long PrepareAddOnContent(ServiceCtx context)
{
Logger.PrintStub(LogClass.ServiceNs);
return 0; return 0;
} }