misc: Move configuration management to the Ryujinx project (#2269)

* Decouple configuration from Ryujinx.HLE and Ryujinx.Input

* Move Configuration to the Ryujinx project
This commit is contained in:
Mary 2021-05-16 17:12:14 +02:00 committed by GitHub
parent f48828351c
commit bec67dbef7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 387 additions and 215 deletions

View file

@ -10,7 +10,6 @@ using LibHac.Ns;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.FileSystem.Content;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.HLE.Loaders.Npdm;
@ -49,10 +48,7 @@ namespace Ryujinx.HLE.HOS
"sdk"
};
private readonly Switch _device;
private readonly ContentManager _contentManager;
private readonly VirtualFileSystem _fileSystem;
private readonly Switch _device;
private string _titleName;
private string _displayVersion;
private BlitStruct<ApplicationControlProperty> _controlData;
@ -66,12 +62,9 @@ namespace Ryujinx.HLE.HOS
public string TitleIdText => TitleId.ToString("x16");
public ApplicationLoader(Switch device, VirtualFileSystem fileSystem, ContentManager contentManager)
public ApplicationLoader(Switch device)
{
_device = device;
_contentManager = contentManager;
_fileSystem = fileSystem;
_device = device;
_controlData = new BlitStruct<ApplicationControlProperty>(1);
}
@ -79,14 +72,14 @@ namespace Ryujinx.HLE.HOS
{
if (romFsFile != null)
{
_fileSystem.LoadRomFs(romFsFile);
_device.Configuration.VirtualFileSystem.LoadRomFs(romFsFile);
}
LocalFileSystem codeFs = new LocalFileSystem(exeFsDir);
Npdm metaData = ReadNpdm(codeFs);
_fileSystem.ModLoader.CollectMods(new[] { TitleId }, _fileSystem.ModLoader.GetModsBasePath());
_device.Configuration.VirtualFileSystem.ModLoader.CollectMods(new[] { TitleId }, _device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath());
if (TitleId != 0)
{
@ -209,7 +202,7 @@ namespace Ryujinx.HLE.HOS
public void LoadXci(string xciFile)
{
FileStream file = new FileStream(xciFile, FileMode.Open, FileAccess.Read);
Xci xci = new Xci(_fileSystem.KeySet, file.AsStorage());
Xci xci = new Xci(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage());
if (!xci.HasPartition(XciPartitionType.Secure))
{
@ -226,7 +219,7 @@ namespace Ryujinx.HLE.HOS
try
{
(mainNca, patchNca, controlNca) = GetGameData(_fileSystem, securePartition, _device.UserChannelPersistence.Index);
(mainNca, patchNca, controlNca) = GetGameData(_device.Configuration.VirtualFileSystem, securePartition, _device.Configuration.UserChannelPersistence.Index);
}
catch (Exception e)
{
@ -242,9 +235,9 @@ namespace Ryujinx.HLE.HOS
return;
}
_contentManager.LoadEntries(_device);
_contentManager.ClearAocData();
_contentManager.AddAocData(securePartition, xciFile, mainNca.Header.TitleId);
_device.Configuration.ContentManager.LoadEntries(_device);
_device.Configuration.ContentManager.ClearAocData();
_device.Configuration.ContentManager.AddAocData(securePartition, xciFile, mainNca.Header.TitleId, _device.Configuration.FsIntegrityCheckLevel);
LoadNca(mainNca, patchNca, controlNca);
}
@ -260,7 +253,7 @@ namespace Ryujinx.HLE.HOS
try
{
(mainNca, patchNca, controlNca) = GetGameData(_fileSystem, nsp, _device.UserChannelPersistence.Index);
(mainNca, patchNca, controlNca) = GetGameData(_device.Configuration.VirtualFileSystem, nsp, _device.Configuration.UserChannelPersistence.Index);
}
catch (Exception e)
{
@ -278,8 +271,8 @@ namespace Ryujinx.HLE.HOS
if (mainNca != null)
{
_contentManager.ClearAocData();
_contentManager.AddAocData(nsp, nspFile, mainNca.Header.TitleId);
_device.Configuration.ContentManager.ClearAocData();
_device.Configuration.ContentManager.AddAocData(nsp, nspFile, mainNca.Header.TitleId, _device.Configuration.FsIntegrityCheckLevel);
LoadNca(mainNca, patchNca, controlNca);
@ -293,7 +286,7 @@ namespace Ryujinx.HLE.HOS
public void LoadNca(string ncaFile)
{
FileStream file = new FileStream(ncaFile, FileMode.Open, FileAccess.Read);
Nca nca = new Nca(_fileSystem.KeySet, file.AsStorage(false));
Nca nca = new Nca(_device.Configuration.VirtualFileSystem.KeySet, file.AsStorage(false));
LoadNca(nca, null, null);
}
@ -310,7 +303,7 @@ namespace Ryujinx.HLE.HOS
IStorage dataStorage = null;
IFileSystem codeFs = null;
(Nca updatePatchNca, Nca updateControlNca) = GetGameUpdateData(_fileSystem, mainNca.Header.TitleId.ToString("x16"), _device.UserChannelPersistence.Index, out _);
(Nca updatePatchNca, Nca updateControlNca) = GetGameUpdateData(_device.Configuration.VirtualFileSystem, mainNca.Header.TitleId.ToString("x16"), _device.Configuration.UserChannelPersistence.Index, out _);
if (updatePatchNca != null)
{
@ -323,7 +316,7 @@ namespace Ryujinx.HLE.HOS
}
// Load program 0 control NCA as we are going to need it for display version.
(_, Nca updateProgram0ControlNca) = GetGameUpdateData(_fileSystem, mainNca.Header.TitleId.ToString("x16"), 0, out _);
(_, Nca updateProgram0ControlNca) = GetGameUpdateData(_device.Configuration.VirtualFileSystem, mainNca.Header.TitleId.ToString("x16"), 0, out _);
// Load Aoc
string titleAocMetadataPath = Path.Combine(AppDataManager.GamesDirPath, mainNca.Header.TitleId.ToString("x16"), "dlc.json");
@ -336,7 +329,7 @@ namespace Ryujinx.HLE.HOS
{
foreach (DlcNca dlcNca in dlcContainer.DlcNcaList)
{
_contentManager.AddAocItem(dlcNca.TitleId, dlcContainer.Path, dlcNca.Path, dlcNca.Enabled);
_device.Configuration.ContentManager.AddAocItem(dlcNca.TitleId, dlcContainer.Path, dlcNca.Path, dlcNca.Enabled);
}
}
}
@ -375,7 +368,7 @@ namespace Ryujinx.HLE.HOS
Npdm metaData = ReadNpdm(codeFs);
_fileSystem.ModLoader.CollectMods(_contentManager.GetAocTitleIds().Prepend(TitleId), _fileSystem.ModLoader.GetModsBasePath());
_device.Configuration.VirtualFileSystem.ModLoader.CollectMods(_device.Configuration.ContentManager.GetAocTitleIds().Prepend(TitleId), _device.Configuration.VirtualFileSystem.ModLoader.GetModsBasePath());
if (controlNca != null)
{
@ -388,7 +381,7 @@ namespace Ryujinx.HLE.HOS
// NOTE: Nintendo doesn't guarantee that the display version will be updated on sub programs when updating a multi program application.
// BODY: As such, to avoid PTC cache confusion, we only trust the the program 0 display version when launching a sub program.
if (updateProgram0ControlNca != null && _device.UserChannelPersistence.Index != 0)
if (updateProgram0ControlNca != null && _device.Configuration.UserChannelPersistence.Index != 0)
{
string dummyTitleName = "";
BlitStruct<ApplicationControlProperty> dummyControl = new BlitStruct<ApplicationControlProperty>(1);
@ -402,9 +395,9 @@ namespace Ryujinx.HLE.HOS
}
else
{
IStorage newStorage = _fileSystem.ModLoader.ApplyRomFsMods(TitleId, dataStorage);
IStorage newStorage = _device.Configuration.VirtualFileSystem.ModLoader.ApplyRomFsMods(TitleId, dataStorage);
_fileSystem.SetRomFs(newStorage.AsStream(FileAccess.Read));
_device.Configuration.VirtualFileSystem.SetRomFs(newStorage.AsStream(FileAccess.Read));
}
if (TitleId != 0)
@ -470,7 +463,7 @@ namespace Ryujinx.HLE.HOS
private void LoadExeFs(IFileSystem codeFs, Npdm metaData = null)
{
if (_fileSystem.ModLoader.ReplaceExefsPartition(TitleId, ref codeFs))
if (_device.Configuration.VirtualFileSystem.ModLoader.ReplaceExefsPartition(TitleId, ref codeFs))
{
metaData = null; //TODO: Check if we should retain old npdm
}
@ -496,7 +489,7 @@ namespace Ryujinx.HLE.HOS
}
// ExeFs file replacements
ModLoadResult modLoadResult = _fileSystem.ModLoader.ApplyExefsMods(TitleId, nsos);
ModLoadResult modLoadResult = _device.Configuration.VirtualFileSystem.ModLoader.ApplyExefsMods(TitleId, nsos);
// collect the nsos, ignoring ones that aren't used
NsoExecutable[] programs = nsos.Where(x => x != null).ToArray();
@ -507,9 +500,9 @@ namespace Ryujinx.HLE.HOS
metaData = modLoadResult.Npdm;
}
_fileSystem.ModLoader.ApplyNsoPatches(TitleId, programs);
_device.Configuration.VirtualFileSystem.ModLoader.ApplyNsoPatches(TitleId, programs);
_contentManager.LoadEntries(_device);
_device.Configuration.ContentManager.LoadEntries(_device);
bool usePtc = _device.System.EnablePtc;
@ -528,7 +521,7 @@ namespace Ryujinx.HLE.HOS
ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, executables: programs);
_fileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine);
_device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine);
}
public void LoadProgram(string filePath)
@ -569,7 +562,7 @@ namespace Ryujinx.HLE.HOS
if (romfsSize != 0)
{
_fileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset));
_device.Configuration.VirtualFileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset));
}
if (nacpSize != 0)
@ -617,7 +610,7 @@ namespace Ryujinx.HLE.HOS
executable = new NsoExecutable(new LocalStorage(filePath, FileAccess.Read), Path.GetFileNameWithoutExtension(filePath));
}
_contentManager.LoadEntries(_device);
_device.Configuration.ContentManager.LoadEntries(_device);
_titleName = metaData.TitleName;
TitleId = metaData.Aci0.TitleId;
@ -629,7 +622,7 @@ namespace Ryujinx.HLE.HOS
ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, executables: executable);
_fileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine);
_device.Configuration.VirtualFileSystem.ModLoader.LoadCheats(TitleId, tamperInfo, _device.TamperMachine);
}
private Npdm GetDefaultNpdm()
@ -664,7 +657,7 @@ namespace Ryujinx.HLE.HOS
"No control file was found for this game. Using a dummy one instead. This may cause inaccuracies in some games.");
}
FileSystemClient fileSystem = _fileSystem.FsClient;
FileSystemClient fileSystem = _device.Configuration.VirtualFileSystem.FsClient;
Result resultCode = fileSystem.EnsureApplicationCacheStorage(out _, applicationId, ref control);
if (resultCode.IsFailure())

View file

@ -8,8 +8,6 @@ using Ryujinx.Audio.Integration;
using Ryujinx.Audio.Output;
using Ryujinx.Audio.Renderer.Device;
using Ryujinx.Audio.Renderer.Server;
using Ryujinx.Common;
using Ryujinx.Configuration;
using Ryujinx.HLE.FileSystem.Content;
using Ryujinx.HLE.HOS.Font;
using Ryujinx.HLE.HOS.Kernel;
@ -111,13 +109,13 @@ namespace Ryujinx.HLE.HOS
internal LibHac.Horizon LibHacHorizonServer { get; private set; }
internal HorizonClient LibHacHorizonClient { get; private set; }
public Horizon(Switch device, ContentManager contentManager, AccountManager accountManager, MemoryConfiguration memoryConfiguration)
public Horizon(Switch device)
{
KernelContext = new KernelContext(
device,
device.Memory,
memoryConfiguration.ToKernelMemorySize(),
memoryConfiguration.ToKernelMemoryArrange());
device.Configuration.MemoryConfiguration.ToKernelMemorySize(),
device.Configuration.MemoryConfiguration.ToKernelMemoryArrange());
Device = device;
@ -166,8 +164,8 @@ namespace Ryujinx.HLE.HOS
DisplayResolutionChangeEvent = new KEvent(KernelContext);
AccountManager = accountManager;
ContentManager = contentManager;
AccountManager = device.Configuration.AccountManager;
ContentManager = device.Configuration.ContentManager;
CaptureManager = new CaptureManager(device);
// TODO: use set:sys (and get external clock source id from settings)
@ -179,7 +177,7 @@ namespace Ryujinx.HLE.HOS
TimeSpanType systemTime = TimeSpanType.FromSeconds((long)rtcValue);
// Configure and setup internal offset
TimeSpanType internalOffset = TimeSpanType.FromSeconds(ConfigurationState.Instance.System.SystemTimeOffset);
TimeSpanType internalOffset = TimeSpanType.FromSeconds(device.Configuration.SystemTimeOffset);
TimeSpanType systemTimeOffset = new TimeSpanType(systemTime.NanoSeconds + internalOffset.NanoSeconds);
@ -219,8 +217,6 @@ namespace Ryujinx.HLE.HOS
SurfaceFlinger = new SurfaceFlinger(device);
ConfigurationState.Instance.System.EnableDockedMode.Event += OnDockedModeChange;
InitLibHacHorizon();
InitializeAudioRenderer();
}
@ -313,11 +309,11 @@ namespace Ryujinx.HLE.HOS
LibHacHorizonClient = ryujinxClient;
}
private void OnDockedModeChange(object sender, ReactiveEventArgs<bool> e)
public void ChangeDockedModeState(bool newState)
{
if (e.NewValue != State.DockedMode)
if (newState != State.DockedMode)
{
State.DockedMode = e.NewValue;
State.DockedMode = newState;
PerformanceState.PerformanceMode = State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
AppletState.Messages.Enqueue(MessageInfo.OperationModeChanged);
@ -326,8 +322,7 @@ namespace Ryujinx.HLE.HOS
SignalDisplayResolutionChange();
// Reconfigure controllers
Device.Hid.RefreshInputConfig(ConfigurationState.Instance.Hid.InputConfig.Value);
Device.Configuration.RefreshInputConfig?.Invoke();
}
}
@ -388,8 +383,6 @@ namespace Ryujinx.HLE.HOS
{
if (!_isDisposed && disposing)
{
ConfigurationState.Instance.System.EnableDockedMode.Event -= OnDockedModeChange;
_isDisposed = true;
KProcess terminationProcess = new KProcess(KernelContext);

View file

@ -57,7 +57,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
switch (kind)
{
case LaunchParameterKind.UserChannel:
storageData = context.Device.UserChannelPersistence.Pop();
storageData = context.Device.Configuration.UserChannelPersistence.Pop();
break;
case LaunchParameterKind.PreselectedUser:
// Only the first 0x18 bytes of the Data seems to be actually used.
@ -453,7 +453,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
// ClearUserChannel()
public ResultCode ClearUserChannel(ServiceCtx context)
{
context.Device.UserChannelPersistence.Clear();
context.Device.Configuration.UserChannelPersistence.Clear();
return ResultCode.Success;
}
@ -464,7 +464,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
{
AppletAE.IStorage data = GetObject<AppletAE.IStorage>(context, 0);
context.Device.UserChannelPersistence.Push(data.Data);
context.Device.Configuration.UserChannelPersistence.Push(data.Data);
return ResultCode.Success;
}
@ -473,7 +473,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
// GetPreviousProgramIndex() -> s32 program_index
public ResultCode GetPreviousProgramIndex(ServiceCtx context)
{
int previousProgramIndex = context.Device.UserChannelPersistence.PreviousIndex;
int previousProgramIndex = context.Device.Configuration.UserChannelPersistence.PreviousIndex;
context.ResponseData.Write(previousProgramIndex);

View file

@ -396,7 +396,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
// We do a mitm here to find if the request is for an AOC.
// This is because AOC can be distributed over multiple containers in the emulator.
if (context.Device.System.ContentManager.GetAocDataStorage((ulong)titleId, out LibHac.Fs.IStorage aocStorage))
if (context.Device.System.ContentManager.GetAocDataStorage((ulong)titleId, out LibHac.Fs.IStorage aocStorage, context.Device.Configuration.FsIntegrityCheckLevel))
{
Logger.Info?.Print(LogClass.Loader, $"Opened AddOnContent Data TitleID={titleId:X16}");

View file

@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
Npads = new NpadDevices(_device, true);
}
internal void RefreshInputConfig(List<InputConfig> inputConfig)
public void RefreshInputConfig(List<InputConfig> inputConfig)
{
ControllerConfig[] npadConfig = new ControllerConfig[inputConfig.Count];
@ -78,11 +78,6 @@ namespace Ryujinx.HLE.HOS.Services.Hid
_device.Hid.Npads.Configure(npadConfig);
}
internal void RefreshInputConfigEvent(object _, ReactiveEventArgs<List<InputConfig>> args)
{
RefreshInputConfig(args.NewValue);
}
public ControllerKeys UpdateStickButtons(JoystickPosition leftStick, JoystickPosition rightStick)
{
const int stickButtonThreshold = short.MaxValue / 2;

View file

@ -109,7 +109,7 @@ namespace Ryujinx.HLE.HOS.Services
bool serviceExists = service.HipcCommands.TryGetValue(commandId, out MethodInfo processRequest);
if (ServiceConfiguration.IgnoreMissingServices || serviceExists)
if (context.Device.Configuration.IgnoreMissingServices || serviceExists)
{
ResultCode result = ResultCode.Success;
@ -163,7 +163,7 @@ namespace Ryujinx.HLE.HOS.Services
bool serviceExists = TipcCommands.TryGetValue(commandId, out MethodInfo processRequest);
if (ServiceConfiguration.IgnoreMissingServices || serviceExists)
if (context.Device.Configuration.IgnoreMissingServices || serviceExists)
{
ResultCode result = ResultCode.Success;

View file

@ -1,7 +0,0 @@
namespace Ryujinx.HLE.HOS.Services
{
public static class ServiceConfiguration
{
public static bool IgnoreMissingServices { get; set; }
}
}

View file

@ -98,7 +98,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
}
else
{
if (ServiceConfiguration.IgnoreMissingServices)
if (context.Device.Configuration.IgnoreMissingServices)
{
Logger.Warning?.Print(LogClass.Service, $"Missing service {name} ignored");
}

View file

@ -1,6 +1,5 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Configuration;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
@ -351,7 +350,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
bool flipX = item.Transform.HasFlag(NativeWindowTransform.FlipX);
bool flipY = item.Transform.HasFlag(NativeWindowTransform.FlipY);
AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
AspectRatio aspectRatio = _device.Configuration.AspectRatio;
bool isStretched = aspectRatio == AspectRatio.Stretched;
ImageCrop crop = new ImageCrop(

View file

@ -5,7 +5,6 @@ using LibHac.Fs.Fsa;
using LibHac.FsSystem;
using LibHac.FsSystem.NcaUtils;
using Ryujinx.Common.Logging;
using Ryujinx.Configuration;
using Ryujinx.HLE.Exceptions;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.FileSystem.Content;
@ -47,10 +46,8 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
InitializeLocationNameCache();
}
public string SanityCheckDeviceLocationName()
public string SanityCheckDeviceLocationName(string locationName)
{
string locationName = ConfigurationState.Instance.System.TimeZone;
if (IsLocationNameValid(locationName))
{
return locationName;
@ -58,8 +55,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
Logger.Warning?.Print(LogClass.ServiceTime, $"Invalid device TimeZone {locationName}, switching back to UTC");
ConfigurationState.Instance.System.TimeZone.Value = "UTC";
return "UTC";
}
@ -69,7 +64,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
SteadyClockTimePoint timeZoneUpdatedTimePoint = timeManager.StandardSteadyClock.GetCurrentTimePoint(null);
string deviceLocationName = SanityCheckDeviceLocationName();
string deviceLocationName = SanityCheckDeviceLocationName(device.Configuration.TimeZone);
ResultCode result = GetTimeZoneBinary(deviceLocationName, out Stream timeZoneBinaryStream, out LocalStorage ncaFile);