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:
parent
f48828351c
commit
bec67dbef7
28 changed files with 387 additions and 215 deletions
|
@ -197,7 +197,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
}
|
}
|
||||||
|
|
||||||
// fs must contain AOC nca files in its root
|
// fs must contain AOC nca files in its root
|
||||||
public void AddAocData(IFileSystem fs, string containerPath, ulong aocBaseId)
|
public void AddAocData(IFileSystem fs, string containerPath, ulong aocBaseId, IntegrityCheckLevel integrityCheckLevel)
|
||||||
{
|
{
|
||||||
_virtualFileSystem.ImportTickets(fs);
|
_virtualFileSystem.ImportTickets(fs);
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var pfs0 = nca.OpenFileSystem(0, Switch.GetIntegrityCheckLevel());
|
using var pfs0 = nca.OpenFileSystem(0, integrityCheckLevel);
|
||||||
|
|
||||||
pfs0.OpenFile(out IFile cnmtFile, pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read);
|
pfs0.OpenFile(out IFile cnmtFile, pfs0.EnumerateEntries().Single().FullPath.ToU8Span(), OpenMode.Read);
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
|
|
||||||
public IList<ulong> GetAocTitleIds() => _aocData.Where(e => e.Value.Enabled).Select(e => e.Key).ToList();
|
public IList<ulong> GetAocTitleIds() => _aocData.Where(e => e.Value.Enabled).Select(e => e.Key).ToList();
|
||||||
|
|
||||||
public bool GetAocDataStorage(ulong aocTitleId, out IStorage aocStorage)
|
public bool GetAocDataStorage(ulong aocTitleId, out IStorage aocStorage, IntegrityCheckLevel integrityCheckLevel)
|
||||||
{
|
{
|
||||||
aocStorage = null;
|
aocStorage = null;
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
return false; // Print error?
|
return false; // Print error?
|
||||||
}
|
}
|
||||||
|
|
||||||
aocStorage = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()).OpenStorage(NcaSectionType.Data, Switch.GetIntegrityCheckLevel());
|
aocStorage = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()).OpenStorage(NcaSectionType.Data, integrityCheckLevel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -710,8 +710,6 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
|
|
||||||
SystemVersion VerifyAndGetVersionZip(ZipArchive archive)
|
SystemVersion VerifyAndGetVersionZip(ZipArchive archive)
|
||||||
{
|
{
|
||||||
IntegrityCheckLevel integrityCheckLevel = Switch.GetIntegrityCheckLevel();
|
|
||||||
|
|
||||||
SystemVersion systemVersion = null;
|
SystemVersion systemVersion = null;
|
||||||
|
|
||||||
foreach (var entry in archive.Entries)
|
foreach (var entry in archive.Entries)
|
||||||
|
@ -751,7 +749,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
{
|
{
|
||||||
Nca metaNca = new Nca(_virtualFileSystem.KeySet, ncaStream.AsStorage());
|
Nca metaNca = new Nca(_virtualFileSystem.KeySet, ncaStream.AsStorage());
|
||||||
|
|
||||||
IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel);
|
IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||||
|
|
||||||
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
|
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
|
||||||
|
|
||||||
|
@ -781,7 +779,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
{
|
{
|
||||||
Nca nca = new Nca(_virtualFileSystem.KeySet, ncaStream.AsStorage());
|
Nca nca = new Nca(_virtualFileSystem.KeySet, ncaStream.AsStorage());
|
||||||
|
|
||||||
var romfs = nca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel);
|
var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||||
|
|
||||||
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
|
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
|
||||||
{
|
{
|
||||||
|
@ -816,7 +814,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
{
|
{
|
||||||
Nca metaNca = new Nca(_virtualFileSystem.KeySet, metaNcaStream.AsStorage());
|
Nca metaNca = new Nca(_virtualFileSystem.KeySet, metaNcaStream.AsStorage());
|
||||||
|
|
||||||
IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel);
|
IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||||
|
|
||||||
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
|
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
|
||||||
|
|
||||||
|
@ -873,8 +871,6 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
|
|
||||||
SystemVersion VerifyAndGetVersion(IFileSystem filesystem)
|
SystemVersion VerifyAndGetVersion(IFileSystem filesystem)
|
||||||
{
|
{
|
||||||
IntegrityCheckLevel integrityCheckLevel = Switch.GetIntegrityCheckLevel();
|
|
||||||
|
|
||||||
SystemVersion systemVersion = null;
|
SystemVersion systemVersion = null;
|
||||||
|
|
||||||
CnmtContentMetaEntry[] metaEntries = null;
|
CnmtContentMetaEntry[] metaEntries = null;
|
||||||
|
@ -887,7 +883,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
|
|
||||||
if (nca.Header.TitleId == SystemUpdateTitleId && nca.Header.ContentType == NcaContentType.Meta)
|
if (nca.Header.TitleId == SystemUpdateTitleId && nca.Header.ContentType == NcaContentType.Meta)
|
||||||
{
|
{
|
||||||
IFileSystem fs = nca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel);
|
IFileSystem fs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||||
|
|
||||||
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
|
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
|
||||||
|
|
||||||
|
@ -905,7 +901,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
}
|
}
|
||||||
else if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data)
|
else if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data)
|
||||||
{
|
{
|
||||||
var romfs = nca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel);
|
var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||||
|
|
||||||
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
|
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
|
||||||
{
|
{
|
||||||
|
@ -952,7 +948,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
|
|
||||||
Nca metaNca = new Nca(_virtualFileSystem.KeySet, metaStorage);
|
Nca metaNca = new Nca(_virtualFileSystem.KeySet, metaStorage);
|
||||||
|
|
||||||
IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel);
|
IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||||
|
|
||||||
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
|
string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath;
|
||||||
|
|
||||||
|
@ -1004,8 +1000,6 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
|
|
||||||
public SystemVersion GetCurrentFirmwareVersion()
|
public SystemVersion GetCurrentFirmwareVersion()
|
||||||
{
|
{
|
||||||
IntegrityCheckLevel integrityCheckLevel = Switch.GetIntegrityCheckLevel();
|
|
||||||
|
|
||||||
LoadEntries();
|
LoadEntries();
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
|
@ -1024,7 +1018,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
|
|
||||||
if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data)
|
if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data)
|
||||||
{
|
{
|
||||||
var romfs = nca.OpenFileSystem(NcaSectionType.Data, integrityCheckLevel);
|
var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
|
||||||
|
|
||||||
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
|
if (romfs.OpenFile(out IFile systemVersionFile, "/file".ToU8Span(), OpenMode.Read).IsSuccess())
|
||||||
{
|
{
|
||||||
|
|
179
Ryujinx.HLE/HLEConfiguration.cs
Normal file
179
Ryujinx.HLE/HLEConfiguration.cs
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
using LibHac.FsSystem;
|
||||||
|
using Ryujinx.Audio.Integration;
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.HLE.FileSystem;
|
||||||
|
using Ryujinx.HLE.FileSystem.Content;
|
||||||
|
using Ryujinx.HLE.HOS;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// HLE configuration.
|
||||||
|
/// </summary>
|
||||||
|
public class HLEConfiguration
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The virtual file system used by the FS service.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly VirtualFileSystem VirtualFileSystem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The account manager used by the account service.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly AccountManager AccountManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The content manager used by the NCM service.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly ContentManager ContentManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The persistant information between run for multi-application capabilities.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
public readonly UserChannelPersistence UserChannelPersistence;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The GPU renderer to use for all GPU operations.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly IRenderer GpuRenderer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The audio device driver to use for all audio operations.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly IHardwareDeviceDriver AudioDeviceDriver;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The handler for various UI related operations needed outside of HLE.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly IHostUiHandler HostUiHandler;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Control the memory configuration used by the emulation context.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly MemoryConfiguration MemoryConfiguration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The system language to use in the settings service.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly SystemLanguage SystemLanguage;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The system region to use in the settings service.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly RegionCode Region;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Control the initial state of the vertical sync in the SurfaceFlinger service.
|
||||||
|
/// </summary>
|
||||||
|
internal readonly bool EnableVsync;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Control the initial state of the docked mode.
|
||||||
|
/// </summary>
|
||||||
|
internal readonly bool EnableDockedMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Control if the Profiled Translation Cache (PTC) should be used.
|
||||||
|
/// </summary>
|
||||||
|
internal readonly bool EnablePtc;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Control LibHac's integrity check level.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly IntegrityCheckLevel FsIntegrityCheckLevel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Control LibHac's global access logging level. Value must be between 0 and 3.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly int FsGlobalAccessLogMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The system time offset to apply to the time service steady and local clocks.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly long SystemTimeOffset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The system timezone used by the time service.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This cannot be changed after <see cref="Switch"/> instantiation.</remarks>
|
||||||
|
internal readonly string TimeZone;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Control the inital state of the ignore missing services setting.
|
||||||
|
/// If this is set to true, when a missing service is encountered, it will try to automatically handle it instead of throwing an exception.
|
||||||
|
/// </summary>
|
||||||
|
/// TODO: Update this again.
|
||||||
|
public bool IgnoreMissingServices { internal get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Aspect Ratio applied to the renderer window by the SurfaceFlinger service.
|
||||||
|
/// </summary>
|
||||||
|
public AspectRatio AspectRatio { internal get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An action called when HLE force a refresh of output after docked mode changed.
|
||||||
|
/// </summary>
|
||||||
|
public Action RefreshInputConfig { internal get; set; }
|
||||||
|
|
||||||
|
public HLEConfiguration(VirtualFileSystem virtualFileSystem,
|
||||||
|
ContentManager contentManager,
|
||||||
|
AccountManager accountManager,
|
||||||
|
UserChannelPersistence userChannelPersistence,
|
||||||
|
IRenderer gpuRenderer,
|
||||||
|
IHardwareDeviceDriver audioDeviceDriver,
|
||||||
|
MemoryConfiguration memoryConfiguration,
|
||||||
|
IHostUiHandler hostUiHandler,
|
||||||
|
SystemLanguage systemLanguage,
|
||||||
|
RegionCode region,
|
||||||
|
bool enableVsync,
|
||||||
|
bool enableDockedMode,
|
||||||
|
bool enablePtc,
|
||||||
|
IntegrityCheckLevel fsIntegrityCheckLevel,
|
||||||
|
int fsGlobalAccessLogMode,
|
||||||
|
long systemTimeOffset,
|
||||||
|
string timeZone,
|
||||||
|
bool ignoreMissingServices,
|
||||||
|
AspectRatio aspectRatio)
|
||||||
|
{
|
||||||
|
VirtualFileSystem = virtualFileSystem;
|
||||||
|
AccountManager = accountManager;
|
||||||
|
ContentManager = contentManager;
|
||||||
|
UserChannelPersistence = userChannelPersistence;
|
||||||
|
GpuRenderer = gpuRenderer;
|
||||||
|
AudioDeviceDriver = audioDeviceDriver;
|
||||||
|
MemoryConfiguration = memoryConfiguration;
|
||||||
|
HostUiHandler = hostUiHandler;
|
||||||
|
SystemLanguage = systemLanguage;
|
||||||
|
Region = region;
|
||||||
|
EnableVsync = enableVsync;
|
||||||
|
EnableDockedMode = enableDockedMode;
|
||||||
|
EnablePtc = enablePtc;
|
||||||
|
FsIntegrityCheckLevel = fsIntegrityCheckLevel;
|
||||||
|
FsGlobalAccessLogMode = fsGlobalAccessLogMode;
|
||||||
|
SystemTimeOffset = systemTimeOffset;
|
||||||
|
TimeZone = timeZone;
|
||||||
|
IgnoreMissingServices = ignoreMissingServices;
|
||||||
|
AspectRatio = aspectRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,6 @@ using LibHac.Ns;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.FileSystem.Content;
|
|
||||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||||
using Ryujinx.HLE.Loaders.Executables;
|
using Ryujinx.HLE.Loaders.Executables;
|
||||||
using Ryujinx.HLE.Loaders.Npdm;
|
using Ryujinx.HLE.Loaders.Npdm;
|
||||||
|
@ -50,9 +49,6 @@ namespace Ryujinx.HLE.HOS
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly Switch _device;
|
private readonly Switch _device;
|
||||||
private readonly ContentManager _contentManager;
|
|
||||||
private readonly VirtualFileSystem _fileSystem;
|
|
||||||
|
|
||||||
private string _titleName;
|
private string _titleName;
|
||||||
private string _displayVersion;
|
private string _displayVersion;
|
||||||
private BlitStruct<ApplicationControlProperty> _controlData;
|
private BlitStruct<ApplicationControlProperty> _controlData;
|
||||||
|
@ -66,12 +62,9 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
public string TitleIdText => TitleId.ToString("x16");
|
public string TitleIdText => TitleId.ToString("x16");
|
||||||
|
|
||||||
public ApplicationLoader(Switch device, VirtualFileSystem fileSystem, ContentManager contentManager)
|
public ApplicationLoader(Switch device)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_contentManager = contentManager;
|
|
||||||
_fileSystem = fileSystem;
|
|
||||||
|
|
||||||
_controlData = new BlitStruct<ApplicationControlProperty>(1);
|
_controlData = new BlitStruct<ApplicationControlProperty>(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,14 +72,14 @@ namespace Ryujinx.HLE.HOS
|
||||||
{
|
{
|
||||||
if (romFsFile != null)
|
if (romFsFile != null)
|
||||||
{
|
{
|
||||||
_fileSystem.LoadRomFs(romFsFile);
|
_device.Configuration.VirtualFileSystem.LoadRomFs(romFsFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalFileSystem codeFs = new LocalFileSystem(exeFsDir);
|
LocalFileSystem codeFs = new LocalFileSystem(exeFsDir);
|
||||||
|
|
||||||
Npdm metaData = ReadNpdm(codeFs);
|
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)
|
if (TitleId != 0)
|
||||||
{
|
{
|
||||||
|
@ -209,7 +202,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
public void LoadXci(string xciFile)
|
public void LoadXci(string xciFile)
|
||||||
{
|
{
|
||||||
FileStream file = new FileStream(xciFile, FileMode.Open, FileAccess.Read);
|
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))
|
if (!xci.HasPartition(XciPartitionType.Secure))
|
||||||
{
|
{
|
||||||
|
@ -226,7 +219,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
try
|
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)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -242,9 +235,9 @@ namespace Ryujinx.HLE.HOS
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_contentManager.LoadEntries(_device);
|
_device.Configuration.ContentManager.LoadEntries(_device);
|
||||||
_contentManager.ClearAocData();
|
_device.Configuration.ContentManager.ClearAocData();
|
||||||
_contentManager.AddAocData(securePartition, xciFile, mainNca.Header.TitleId);
|
_device.Configuration.ContentManager.AddAocData(securePartition, xciFile, mainNca.Header.TitleId, _device.Configuration.FsIntegrityCheckLevel);
|
||||||
|
|
||||||
LoadNca(mainNca, patchNca, controlNca);
|
LoadNca(mainNca, patchNca, controlNca);
|
||||||
}
|
}
|
||||||
|
@ -260,7 +253,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
try
|
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)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -278,8 +271,8 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
if (mainNca != null)
|
if (mainNca != null)
|
||||||
{
|
{
|
||||||
_contentManager.ClearAocData();
|
_device.Configuration.ContentManager.ClearAocData();
|
||||||
_contentManager.AddAocData(nsp, nspFile, mainNca.Header.TitleId);
|
_device.Configuration.ContentManager.AddAocData(nsp, nspFile, mainNca.Header.TitleId, _device.Configuration.FsIntegrityCheckLevel);
|
||||||
|
|
||||||
LoadNca(mainNca, patchNca, controlNca);
|
LoadNca(mainNca, patchNca, controlNca);
|
||||||
|
|
||||||
|
@ -293,7 +286,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
public void LoadNca(string ncaFile)
|
public void LoadNca(string ncaFile)
|
||||||
{
|
{
|
||||||
FileStream file = new FileStream(ncaFile, FileMode.Open, FileAccess.Read);
|
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);
|
LoadNca(nca, null, null);
|
||||||
}
|
}
|
||||||
|
@ -310,7 +303,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
IStorage dataStorage = null;
|
IStorage dataStorage = null;
|
||||||
IFileSystem codeFs = 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)
|
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.
|
// 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
|
// Load Aoc
|
||||||
string titleAocMetadataPath = Path.Combine(AppDataManager.GamesDirPath, mainNca.Header.TitleId.ToString("x16"), "dlc.json");
|
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)
|
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);
|
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)
|
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.
|
// 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.
|
// 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 = "";
|
string dummyTitleName = "";
|
||||||
BlitStruct<ApplicationControlProperty> dummyControl = new BlitStruct<ApplicationControlProperty>(1);
|
BlitStruct<ApplicationControlProperty> dummyControl = new BlitStruct<ApplicationControlProperty>(1);
|
||||||
|
@ -402,9 +395,9 @@ namespace Ryujinx.HLE.HOS
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (TitleId != 0)
|
||||||
|
@ -470,7 +463,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
private void LoadExeFs(IFileSystem codeFs, Npdm metaData = null)
|
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
|
metaData = null; //TODO: Check if we should retain old npdm
|
||||||
}
|
}
|
||||||
|
@ -496,7 +489,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExeFs file replacements
|
// 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
|
// collect the nsos, ignoring ones that aren't used
|
||||||
NsoExecutable[] programs = nsos.Where(x => x != null).ToArray();
|
NsoExecutable[] programs = nsos.Where(x => x != null).ToArray();
|
||||||
|
@ -507,9 +500,9 @@ namespace Ryujinx.HLE.HOS
|
||||||
metaData = modLoadResult.Npdm;
|
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;
|
bool usePtc = _device.System.EnablePtc;
|
||||||
|
|
||||||
|
@ -528,7 +521,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, executables: programs);
|
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)
|
public void LoadProgram(string filePath)
|
||||||
|
@ -569,7 +562,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
if (romfsSize != 0)
|
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)
|
if (nacpSize != 0)
|
||||||
|
@ -617,7 +610,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
executable = new NsoExecutable(new LocalStorage(filePath, FileAccess.Read), Path.GetFileNameWithoutExtension(filePath));
|
executable = new NsoExecutable(new LocalStorage(filePath, FileAccess.Read), Path.GetFileNameWithoutExtension(filePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
_contentManager.LoadEntries(_device);
|
_device.Configuration.ContentManager.LoadEntries(_device);
|
||||||
|
|
||||||
_titleName = metaData.TitleName;
|
_titleName = metaData.TitleName;
|
||||||
TitleId = metaData.Aci0.TitleId;
|
TitleId = metaData.Aci0.TitleId;
|
||||||
|
@ -629,7 +622,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, executables: executable);
|
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()
|
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.");
|
"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);
|
Result resultCode = fileSystem.EnsureApplicationCacheStorage(out _, applicationId, ref control);
|
||||||
|
|
||||||
if (resultCode.IsFailure())
|
if (resultCode.IsFailure())
|
||||||
|
|
|
@ -8,8 +8,6 @@ using Ryujinx.Audio.Integration;
|
||||||
using Ryujinx.Audio.Output;
|
using Ryujinx.Audio.Output;
|
||||||
using Ryujinx.Audio.Renderer.Device;
|
using Ryujinx.Audio.Renderer.Device;
|
||||||
using Ryujinx.Audio.Renderer.Server;
|
using Ryujinx.Audio.Renderer.Server;
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Configuration;
|
|
||||||
using Ryujinx.HLE.FileSystem.Content;
|
using Ryujinx.HLE.FileSystem.Content;
|
||||||
using Ryujinx.HLE.HOS.Font;
|
using Ryujinx.HLE.HOS.Font;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
|
@ -111,13 +109,13 @@ namespace Ryujinx.HLE.HOS
|
||||||
internal LibHac.Horizon LibHacHorizonServer { get; private set; }
|
internal LibHac.Horizon LibHacHorizonServer { get; private set; }
|
||||||
internal HorizonClient LibHacHorizonClient { 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(
|
KernelContext = new KernelContext(
|
||||||
device,
|
device,
|
||||||
device.Memory,
|
device.Memory,
|
||||||
memoryConfiguration.ToKernelMemorySize(),
|
device.Configuration.MemoryConfiguration.ToKernelMemorySize(),
|
||||||
memoryConfiguration.ToKernelMemoryArrange());
|
device.Configuration.MemoryConfiguration.ToKernelMemoryArrange());
|
||||||
|
|
||||||
Device = device;
|
Device = device;
|
||||||
|
|
||||||
|
@ -166,8 +164,8 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
DisplayResolutionChangeEvent = new KEvent(KernelContext);
|
DisplayResolutionChangeEvent = new KEvent(KernelContext);
|
||||||
|
|
||||||
AccountManager = accountManager;
|
AccountManager = device.Configuration.AccountManager;
|
||||||
ContentManager = contentManager;
|
ContentManager = device.Configuration.ContentManager;
|
||||||
CaptureManager = new CaptureManager(device);
|
CaptureManager = new CaptureManager(device);
|
||||||
|
|
||||||
// TODO: use set:sys (and get external clock source id from settings)
|
// 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);
|
TimeSpanType systemTime = TimeSpanType.FromSeconds((long)rtcValue);
|
||||||
|
|
||||||
// Configure and setup internal offset
|
// 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);
|
TimeSpanType systemTimeOffset = new TimeSpanType(systemTime.NanoSeconds + internalOffset.NanoSeconds);
|
||||||
|
|
||||||
|
@ -219,8 +217,6 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
SurfaceFlinger = new SurfaceFlinger(device);
|
SurfaceFlinger = new SurfaceFlinger(device);
|
||||||
|
|
||||||
ConfigurationState.Instance.System.EnableDockedMode.Event += OnDockedModeChange;
|
|
||||||
|
|
||||||
InitLibHacHorizon();
|
InitLibHacHorizon();
|
||||||
InitializeAudioRenderer();
|
InitializeAudioRenderer();
|
||||||
}
|
}
|
||||||
|
@ -313,11 +309,11 @@ namespace Ryujinx.HLE.HOS
|
||||||
LibHacHorizonClient = ryujinxClient;
|
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;
|
PerformanceState.PerformanceMode = State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
|
||||||
|
|
||||||
AppletState.Messages.Enqueue(MessageInfo.OperationModeChanged);
|
AppletState.Messages.Enqueue(MessageInfo.OperationModeChanged);
|
||||||
|
@ -326,8 +322,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
SignalDisplayResolutionChange();
|
SignalDisplayResolutionChange();
|
||||||
|
|
||||||
// Reconfigure controllers
|
Device.Configuration.RefreshInputConfig?.Invoke();
|
||||||
Device.Hid.RefreshInputConfig(ConfigurationState.Instance.Hid.InputConfig.Value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,8 +383,6 @@ namespace Ryujinx.HLE.HOS
|
||||||
{
|
{
|
||||||
if (!_isDisposed && disposing)
|
if (!_isDisposed && disposing)
|
||||||
{
|
{
|
||||||
ConfigurationState.Instance.System.EnableDockedMode.Event -= OnDockedModeChange;
|
|
||||||
|
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
|
|
||||||
KProcess terminationProcess = new KProcess(KernelContext);
|
KProcess terminationProcess = new KProcess(KernelContext);
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
switch (kind)
|
switch (kind)
|
||||||
{
|
{
|
||||||
case LaunchParameterKind.UserChannel:
|
case LaunchParameterKind.UserChannel:
|
||||||
storageData = context.Device.UserChannelPersistence.Pop();
|
storageData = context.Device.Configuration.UserChannelPersistence.Pop();
|
||||||
break;
|
break;
|
||||||
case LaunchParameterKind.PreselectedUser:
|
case LaunchParameterKind.PreselectedUser:
|
||||||
// Only the first 0x18 bytes of the Data seems to be actually used.
|
// 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()
|
// ClearUserChannel()
|
||||||
public ResultCode ClearUserChannel(ServiceCtx context)
|
public ResultCode ClearUserChannel(ServiceCtx context)
|
||||||
{
|
{
|
||||||
context.Device.UserChannelPersistence.Clear();
|
context.Device.Configuration.UserChannelPersistence.Clear();
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -464,7 +464,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
{
|
{
|
||||||
AppletAE.IStorage data = GetObject<AppletAE.IStorage>(context, 0);
|
AppletAE.IStorage data = GetObject<AppletAE.IStorage>(context, 0);
|
||||||
|
|
||||||
context.Device.UserChannelPersistence.Push(data.Data);
|
context.Device.Configuration.UserChannelPersistence.Push(data.Data);
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -473,7 +473,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
|
||||||
// GetPreviousProgramIndex() -> s32 program_index
|
// GetPreviousProgramIndex() -> s32 program_index
|
||||||
public ResultCode GetPreviousProgramIndex(ServiceCtx context)
|
public ResultCode GetPreviousProgramIndex(ServiceCtx context)
|
||||||
{
|
{
|
||||||
int previousProgramIndex = context.Device.UserChannelPersistence.PreviousIndex;
|
int previousProgramIndex = context.Device.Configuration.UserChannelPersistence.PreviousIndex;
|
||||||
|
|
||||||
context.ResponseData.Write(previousProgramIndex);
|
context.ResponseData.Write(previousProgramIndex);
|
||||||
|
|
||||||
|
|
|
@ -396,7 +396,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
|
||||||
|
|
||||||
// We do a mitm here to find if the request is for an AOC.
|
// 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.
|
// 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}");
|
Logger.Info?.Print(LogClass.Loader, $"Opened AddOnContent Data TitleID={titleId:X16}");
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
Npads = new NpadDevices(_device, true);
|
Npads = new NpadDevices(_device, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void RefreshInputConfig(List<InputConfig> inputConfig)
|
public void RefreshInputConfig(List<InputConfig> inputConfig)
|
||||||
{
|
{
|
||||||
ControllerConfig[] npadConfig = new ControllerConfig[inputConfig.Count];
|
ControllerConfig[] npadConfig = new ControllerConfig[inputConfig.Count];
|
||||||
|
|
||||||
|
@ -78,11 +78,6 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
_device.Hid.Npads.Configure(npadConfig);
|
_device.Hid.Npads.Configure(npadConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void RefreshInputConfigEvent(object _, ReactiveEventArgs<List<InputConfig>> args)
|
|
||||||
{
|
|
||||||
RefreshInputConfig(args.NewValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControllerKeys UpdateStickButtons(JoystickPosition leftStick, JoystickPosition rightStick)
|
public ControllerKeys UpdateStickButtons(JoystickPosition leftStick, JoystickPosition rightStick)
|
||||||
{
|
{
|
||||||
const int stickButtonThreshold = short.MaxValue / 2;
|
const int stickButtonThreshold = short.MaxValue / 2;
|
||||||
|
|
|
@ -109,7 +109,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
bool serviceExists = service.HipcCommands.TryGetValue(commandId, out MethodInfo processRequest);
|
bool serviceExists = service.HipcCommands.TryGetValue(commandId, out MethodInfo processRequest);
|
||||||
|
|
||||||
if (ServiceConfiguration.IgnoreMissingServices || serviceExists)
|
if (context.Device.Configuration.IgnoreMissingServices || serviceExists)
|
||||||
{
|
{
|
||||||
ResultCode result = ResultCode.Success;
|
ResultCode result = ResultCode.Success;
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
bool serviceExists = TipcCommands.TryGetValue(commandId, out MethodInfo processRequest);
|
bool serviceExists = TipcCommands.TryGetValue(commandId, out MethodInfo processRequest);
|
||||||
|
|
||||||
if (ServiceConfiguration.IgnoreMissingServices || serviceExists)
|
if (context.Device.Configuration.IgnoreMissingServices || serviceExists)
|
||||||
{
|
{
|
||||||
ResultCode result = ResultCode.Success;
|
ResultCode result = ResultCode.Success;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Ryujinx.HLE.HOS.Services
|
|
||||||
{
|
|
||||||
public static class ServiceConfiguration
|
|
||||||
{
|
|
||||||
public static bool IgnoreMissingServices { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -98,7 +98,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ServiceConfiguration.IgnoreMissingServices)
|
if (context.Device.Configuration.IgnoreMissingServices)
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.Service, $"Missing service {name} ignored");
|
Logger.Warning?.Print(LogClass.Service, $"Missing service {name} ignored");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Configuration;
|
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
|
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 flipX = item.Transform.HasFlag(NativeWindowTransform.FlipX);
|
||||||
bool flipY = item.Transform.HasFlag(NativeWindowTransform.FlipY);
|
bool flipY = item.Transform.HasFlag(NativeWindowTransform.FlipY);
|
||||||
|
|
||||||
AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
|
AspectRatio aspectRatio = _device.Configuration.AspectRatio;
|
||||||
bool isStretched = aspectRatio == AspectRatio.Stretched;
|
bool isStretched = aspectRatio == AspectRatio.Stretched;
|
||||||
|
|
||||||
ImageCrop crop = new ImageCrop(
|
ImageCrop crop = new ImageCrop(
|
||||||
|
|
|
@ -5,7 +5,6 @@ using LibHac.Fs.Fsa;
|
||||||
using LibHac.FsSystem;
|
using LibHac.FsSystem;
|
||||||
using LibHac.FsSystem.NcaUtils;
|
using LibHac.FsSystem.NcaUtils;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Configuration;
|
|
||||||
using Ryujinx.HLE.Exceptions;
|
using Ryujinx.HLE.Exceptions;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.FileSystem.Content;
|
using Ryujinx.HLE.FileSystem.Content;
|
||||||
|
@ -47,10 +46,8 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
InitializeLocationNameCache();
|
InitializeLocationNameCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SanityCheckDeviceLocationName()
|
public string SanityCheckDeviceLocationName(string locationName)
|
||||||
{
|
{
|
||||||
string locationName = ConfigurationState.Instance.System.TimeZone;
|
|
||||||
|
|
||||||
if (IsLocationNameValid(locationName))
|
if (IsLocationNameValid(locationName))
|
||||||
{
|
{
|
||||||
return 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");
|
Logger.Warning?.Print(LogClass.ServiceTime, $"Invalid device TimeZone {locationName}, switching back to UTC");
|
||||||
|
|
||||||
ConfigurationState.Instance.System.TimeZone.Value = "UTC";
|
|
||||||
|
|
||||||
return "UTC";
|
return "UTC";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +64,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
|
|
||||||
SteadyClockTimePoint timeZoneUpdatedTimePoint = timeManager.StandardSteadyClock.GetCurrentTimePoint(null);
|
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);
|
ResultCode result = GetTimeZoneBinary(deviceLocationName, out Stream timeZoneBinaryStream, out LocalStorage ncaFile);
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
using LibHac.FsSystem;
|
|
||||||
using Ryujinx.Audio.Backends.CompatLayer;
|
using Ryujinx.Audio.Backends.CompatLayer;
|
||||||
using Ryujinx.Audio.Integration;
|
using Ryujinx.Audio.Integration;
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Configuration;
|
|
||||||
using Ryujinx.Graphics.GAL;
|
|
||||||
using Ryujinx.Graphics.Gpu;
|
using Ryujinx.Graphics.Gpu;
|
||||||
using Ryujinx.Graphics.Host1x;
|
using Ryujinx.Graphics.Host1x;
|
||||||
using Ryujinx.Graphics.Nvdec;
|
using Ryujinx.Graphics.Nvdec;
|
||||||
using Ryujinx.Graphics.Vic;
|
using Ryujinx.Graphics.Vic;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.FileSystem.Content;
|
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using Ryujinx.HLE.HOS.Services;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Apm;
|
using Ryujinx.HLE.HOS.Services.Apm;
|
||||||
using Ryujinx.HLE.HOS.Services.Hid;
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices;
|
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
@ -24,69 +16,60 @@ namespace Ryujinx.HLE
|
||||||
{
|
{
|
||||||
public class Switch : IDisposable
|
public class Switch : IDisposable
|
||||||
{
|
{
|
||||||
private MemoryConfiguration _memoryConfiguration;
|
public HLEConfiguration Configuration { get; }
|
||||||
|
|
||||||
public IHardwareDeviceDriver AudioDeviceDriver { get; private set; }
|
public IHardwareDeviceDriver AudioDeviceDriver { get; }
|
||||||
|
|
||||||
internal MemoryBlock Memory { get; private set; }
|
internal MemoryBlock Memory { get; }
|
||||||
|
|
||||||
public GpuContext Gpu { get; private set; }
|
public GpuContext Gpu { get; }
|
||||||
|
|
||||||
internal NvMemoryAllocator MemoryAllocator { get; private set; }
|
internal NvMemoryAllocator MemoryAllocator { get; }
|
||||||
|
|
||||||
internal Host1xDevice Host1x { get; }
|
internal Host1xDevice Host1x { get; }
|
||||||
|
|
||||||
public VirtualFileSystem FileSystem { get; private set; }
|
public VirtualFileSystem FileSystem => Configuration.VirtualFileSystem;
|
||||||
|
|
||||||
public Horizon System { get; private set; }
|
public Horizon System { get; }
|
||||||
|
|
||||||
public ApplicationLoader Application { get; }
|
public ApplicationLoader Application { get; }
|
||||||
|
|
||||||
public PerformanceStatistics Statistics { get; private set; }
|
public PerformanceStatistics Statistics { get; }
|
||||||
|
|
||||||
public UserChannelPersistence UserChannelPersistence { get; }
|
public Hid Hid { get; }
|
||||||
|
|
||||||
public Hid Hid { get; private set; }
|
public TamperMachine TamperMachine { get; }
|
||||||
|
|
||||||
public TamperMachine TamperMachine { get; private set; }
|
public IHostUiHandler UiHandler { get; }
|
||||||
|
|
||||||
public IHostUiHandler UiHandler { get; set; }
|
|
||||||
|
|
||||||
public bool EnableDeviceVsync { get; set; } = true;
|
public bool EnableDeviceVsync { get; set; } = true;
|
||||||
|
|
||||||
public Switch(
|
public Switch(HLEConfiguration configuration)
|
||||||
VirtualFileSystem fileSystem,
|
|
||||||
ContentManager contentManager,
|
|
||||||
AccountManager accountManager,
|
|
||||||
UserChannelPersistence userChannelPersistence,
|
|
||||||
IRenderer renderer,
|
|
||||||
IHardwareDeviceDriver audioDeviceDriver,
|
|
||||||
MemoryConfiguration memoryConfiguration)
|
|
||||||
{
|
{
|
||||||
if (renderer == null)
|
if (configuration.GpuRenderer == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(renderer));
|
throw new ArgumentNullException(nameof(configuration.GpuRenderer));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioDeviceDriver == null)
|
if (configuration.AudioDeviceDriver == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(audioDeviceDriver));
|
throw new ArgumentNullException(nameof(configuration.AudioDeviceDriver));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userChannelPersistence == null)
|
if (configuration.UserChannelPersistence== null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(userChannelPersistence));
|
throw new ArgumentNullException(nameof(configuration.UserChannelPersistence));
|
||||||
}
|
}
|
||||||
|
|
||||||
UserChannelPersistence = userChannelPersistence;
|
Configuration = configuration;
|
||||||
|
|
||||||
_memoryConfiguration = memoryConfiguration;
|
UiHandler = configuration.HostUiHandler;
|
||||||
|
|
||||||
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(audioDeviceDriver);
|
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(configuration.AudioDeviceDriver);
|
||||||
|
|
||||||
Memory = new MemoryBlock(memoryConfiguration.ToDramSize());
|
Memory = new MemoryBlock(configuration.MemoryConfiguration.ToDramSize());
|
||||||
|
|
||||||
Gpu = new GpuContext(renderer);
|
Gpu = new GpuContext(configuration.GpuRenderer);
|
||||||
|
|
||||||
MemoryAllocator = new NvMemoryAllocator();
|
MemoryAllocator = new NvMemoryAllocator();
|
||||||
|
|
||||||
|
@ -111,9 +94,7 @@ namespace Ryujinx.HLE
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
FileSystem = fileSystem;
|
System = new Horizon(this);
|
||||||
|
|
||||||
System = new Horizon(this, contentManager, accountManager, memoryConfiguration);
|
|
||||||
System.InitializeServices();
|
System.InitializeServices();
|
||||||
|
|
||||||
Statistics = new PerformanceStatistics();
|
Statistics = new PerformanceStatistics();
|
||||||
|
@ -121,45 +102,30 @@ namespace Ryujinx.HLE
|
||||||
Hid = new Hid(this, System.HidBaseAddress);
|
Hid = new Hid(this, System.HidBaseAddress);
|
||||||
Hid.InitDevices();
|
Hid.InitDevices();
|
||||||
|
|
||||||
Application = new ApplicationLoader(this, fileSystem, contentManager);
|
Application = new ApplicationLoader(this);
|
||||||
|
|
||||||
TamperMachine = new TamperMachine();
|
TamperMachine = new TamperMachine();
|
||||||
|
|
||||||
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
System.State.SetLanguage((SystemLanguage)ConfigurationState.Instance.System.Language.Value);
|
System.State.SetLanguage(Configuration.SystemLanguage);
|
||||||
|
|
||||||
System.State.SetRegion((RegionCode)ConfigurationState.Instance.System.Region.Value);
|
System.State.SetRegion(Configuration.Region);
|
||||||
|
|
||||||
EnableDeviceVsync = ConfigurationState.Instance.Graphics.EnableVsync;
|
EnableDeviceVsync = Configuration.EnableVsync;
|
||||||
|
|
||||||
System.State.DockedMode = ConfigurationState.Instance.System.EnableDockedMode;
|
System.State.DockedMode = Configuration.EnableDockedMode;
|
||||||
|
|
||||||
System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
|
System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default;
|
||||||
|
|
||||||
System.EnablePtc = ConfigurationState.Instance.System.EnablePtc;
|
System.EnablePtc = Configuration.EnablePtc;
|
||||||
|
|
||||||
System.FsIntegrityCheckLevel = GetIntegrityCheckLevel();
|
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
|
||||||
|
|
||||||
System.GlobalAccessLogMode = ConfigurationState.Instance.System.FsGlobalAccessLogMode;
|
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
|
||||||
|
|
||||||
ServiceConfiguration.IgnoreMissingServices = ConfigurationState.Instance.System.IgnoreMissingServices;
|
|
||||||
ConfigurationState.Instance.System.IgnoreMissingServices.Event += (object _, ReactiveEventArgs<bool> args) =>
|
|
||||||
{
|
|
||||||
ServiceConfiguration.IgnoreMissingServices = args.NewValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Configure controllers
|
|
||||||
Hid.RefreshInputConfig(ConfigurationState.Instance.Hid.InputConfig.Value);
|
|
||||||
ConfigurationState.Instance.Hid.InputConfig.Event += Hid.RefreshInputConfigEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntegrityCheckLevel GetIntegrityCheckLevel()
|
|
||||||
{
|
|
||||||
return ConfigurationState.Instance.System.EnableFsIntegrityChecks
|
|
||||||
? IntegrityCheckLevel.ErrorOnInvalid
|
|
||||||
: IntegrityCheckLevel.None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadCart(string exeFsDir, string romFsFile = null)
|
public void LoadCart(string exeFsDir, string romFsFile = null)
|
||||||
|
@ -223,8 +189,6 @@ namespace Ryujinx.HLE
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
ConfigurationState.Instance.Hid.InputConfig.Event -= Hid.RefreshInputConfigEvent;
|
|
||||||
|
|
||||||
System.Dispose();
|
System.Dispose();
|
||||||
Host1x.Dispose();
|
Host1x.Dispose();
|
||||||
AudioDeviceDriver.Dispose();
|
AudioDeviceDriver.Dispose();
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
using Ryujinx.Common.Configuration.Hid;
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||||
using Ryujinx.Configuration;
|
|
||||||
using Ryujinx.HLE.HOS;
|
|
||||||
using Ryujinx.HLE.HOS.Services.Hid;
|
using Ryujinx.HLE.HOS.Services.Hid;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -10,6 +8,7 @@ using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
|
using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
|
||||||
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
|
|
||||||
namespace Ryujinx.Input.HLE
|
namespace Ryujinx.Input.HLE
|
||||||
{
|
{
|
||||||
|
@ -31,30 +30,41 @@ namespace Ryujinx.Input.HLE
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
||||||
private List<InputConfig> _inputConfig;
|
private List<InputConfig> _inputConfig;
|
||||||
|
private bool _enableKeyboard;
|
||||||
|
private Switch _device;
|
||||||
|
|
||||||
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver)
|
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver)
|
||||||
{
|
{
|
||||||
_controllers = new NpadController[MaxControllers];
|
_controllers = new NpadController[MaxControllers];
|
||||||
_cemuHookClient = new CemuHookClient();
|
_cemuHookClient = new CemuHookClient(this);
|
||||||
|
|
||||||
_keyboardDriver = keyboardDriver;
|
_keyboardDriver = keyboardDriver;
|
||||||
_gamepadDriver = gamepadDriver;
|
_gamepadDriver = gamepadDriver;
|
||||||
_inputConfig = ConfigurationState.Instance.Hid.InputConfig.Value;
|
_inputConfig = new List<InputConfig>();
|
||||||
|
_enableKeyboard = false;
|
||||||
|
|
||||||
_gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
_gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||||
_gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
_gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RefreshInputConfigForHLE()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_device.Hid.RefreshInputConfig(_inputConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleOnGamepadDisconnected(string obj)
|
private void HandleOnGamepadDisconnected(string obj)
|
||||||
{
|
{
|
||||||
// Force input reload
|
// Force input reload
|
||||||
ReloadConfiguration(ConfigurationState.Instance.Hid.InputConfig.Value);
|
ReloadConfiguration(_inputConfig, _enableKeyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleOnGamepadConnected(string id)
|
private void HandleOnGamepadConnected(string id)
|
||||||
{
|
{
|
||||||
// Force input reload
|
// Force input reload
|
||||||
ReloadConfiguration(ConfigurationState.Instance.Hid.InputConfig.Value);
|
ReloadConfiguration(_inputConfig, _enableKeyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@ -83,7 +93,7 @@ namespace Ryujinx.Input.HLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReloadConfiguration(List<InputConfig> inputConfig)
|
public void ReloadConfiguration(List<InputConfig> inputConfig, bool enableKeyboard)
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
|
@ -110,10 +120,9 @@ namespace Ryujinx.Input.HLE
|
||||||
}
|
}
|
||||||
|
|
||||||
_inputConfig = inputConfig;
|
_inputConfig = inputConfig;
|
||||||
|
_enableKeyboard = enableKeyboard;
|
||||||
|
|
||||||
// Enforce an update of the property that will be updated by HLE.
|
_device.Hid.RefreshInputConfig(inputConfig);
|
||||||
// TODO: Move that in the input manager maybe?
|
|
||||||
ConfigurationState.Instance.Hid.InputConfig.Value = inputConfig;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +142,15 @@ namespace Ryujinx.Input.HLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(Hid hleHid, TamperMachine tamperMachine)
|
public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard)
|
||||||
|
{
|
||||||
|
_device = device;
|
||||||
|
_device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE;
|
||||||
|
|
||||||
|
ReloadConfiguration(inputConfig, enableKeyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
|
@ -159,11 +176,11 @@ namespace Ryujinx.Input.HLE
|
||||||
|
|
||||||
inputState = controller.GetHLEInputState();
|
inputState = controller.GetHLEInputState();
|
||||||
|
|
||||||
inputState.Buttons |= hleHid.UpdateStickButtons(inputState.LStick, inputState.RStick);
|
inputState.Buttons |= _device.Hid.UpdateStickButtons(inputState.LStick, inputState.RStick);
|
||||||
|
|
||||||
motionState = controller.GetHLEMotionState();
|
motionState = controller.GetHLEMotionState();
|
||||||
|
|
||||||
if (ConfigurationState.Instance.Hid.EnableKeyboard)
|
if (_enableKeyboard)
|
||||||
{
|
{
|
||||||
hleKeyboardInput = controller.GetHLEKeyboardInput();
|
hleKeyboardInput = controller.GetHLEKeyboardInput();
|
||||||
}
|
}
|
||||||
|
@ -181,15 +198,23 @@ namespace Ryujinx.Input.HLE
|
||||||
hleMotionStates.Add(motionState);
|
hleMotionStates.Add(motionState);
|
||||||
}
|
}
|
||||||
|
|
||||||
hleHid.Npads.Update(hleInputStates);
|
_device.Hid.Npads.Update(hleInputStates);
|
||||||
hleHid.Npads.UpdateSixAxis(hleMotionStates);
|
_device.Hid.Npads.UpdateSixAxis(hleMotionStates);
|
||||||
|
|
||||||
if (hleKeyboardInput.HasValue)
|
if (hleKeyboardInput.HasValue)
|
||||||
{
|
{
|
||||||
hleHid.Keyboard.Update(hleKeyboardInput.Value);
|
_device.Hid.Keyboard.Update(hleKeyboardInput.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
tamperMachine.UpdateInput(hleInputStates);
|
_device.TamperMachine.UpdateInput(hleInputStates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal InputConfig GetPlayerInputConfigByIndex(int index)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _inputConfig.Find(x => x.PlayerIndex == (Ryujinx.Common.Configuration.Hid.PlayerIndex)index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ using Ryujinx.Common.Configuration.Hid;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Configuration;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.Input.Motion.CemuHook.Protocol;
|
using Ryujinx.Input.Motion.CemuHook.Protocol;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -29,9 +29,11 @@ namespace Ryujinx.Input.Motion.CemuHook
|
||||||
|
|
||||||
private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues(typeof(PlayerIndex)).Length];
|
private readonly bool[] _clientErrorStatus = new bool[Enum.GetValues(typeof(PlayerIndex)).Length];
|
||||||
private readonly long[] _clientRetryTimer = new long[Enum.GetValues(typeof(PlayerIndex)).Length];
|
private readonly long[] _clientRetryTimer = new long[Enum.GetValues(typeof(PlayerIndex)).Length];
|
||||||
|
private NpadManager _npadManager;
|
||||||
|
|
||||||
public Client()
|
public Client(NpadManager npadManager)
|
||||||
{
|
{
|
||||||
|
_npadManager = npadManager;
|
||||||
_hosts = new Dictionary<int, IPEndPoint>();
|
_hosts = new Dictionary<int, IPEndPoint>();
|
||||||
_motionData = new Dictionary<int, Dictionary<int, MotionInput>>();
|
_motionData = new Dictionary<int, Dictionary<int, MotionInput>>();
|
||||||
_clients = new Dictionary<int, UdpClient>();
|
_clients = new Dictionary<int, UdpClient>();
|
||||||
|
@ -323,7 +325,7 @@ namespace Ryujinx.Input.Motion.CemuHook
|
||||||
|
|
||||||
ulong timestamp = inputData.MotionTimestamp;
|
ulong timestamp = inputData.MotionTimestamp;
|
||||||
|
|
||||||
InputConfig config = ConfigurationState.Instance.Hid.InputConfig.Value.Find(x => x.PlayerIndex == (PlayerIndex)clientId);
|
InputConfig config = _npadManager.GetPlayerInputConfigByIndex(clientId);
|
||||||
|
|
||||||
lock (_motionData)
|
lock (_motionData)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Ryujinx.Configuration
|
namespace Ryujinx.Configuration
|
||||||
{
|
{
|
|
@ -131,7 +131,7 @@ namespace Ryujinx.Ui.Applet
|
||||||
|
|
||||||
public void ExecuteProgram(HLE.Switch device, ProgramSpecifyKind kind, ulong value)
|
public void ExecuteProgram(HLE.Switch device, ProgramSpecifyKind kind, ulong value)
|
||||||
{
|
{
|
||||||
device.UserChannelPersistence.ExecuteProgram(kind, value);
|
device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
|
||||||
((MainWindow)_parent).RendererWidget?.Exit();
|
((MainWindow)_parent).RendererWidget?.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,14 @@ using ARMeilleure.Translation;
|
||||||
using ARMeilleure.Translation.PTC;
|
using ARMeilleure.Translation.PTC;
|
||||||
using Gtk;
|
using Gtk;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
|
using LibHac.FsSystem;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
using Ryujinx.Audio.Backends.Dummy;
|
using Ryujinx.Audio.Backends.Dummy;
|
||||||
using Ryujinx.Audio.Backends.OpenAL;
|
using Ryujinx.Audio.Backends.OpenAL;
|
||||||
using Ryujinx.Audio.Backends.SDL2;
|
using Ryujinx.Audio.Backends.SDL2;
|
||||||
using Ryujinx.Audio.Backends.SoundIo;
|
using Ryujinx.Audio.Backends.SoundIo;
|
||||||
using Ryujinx.Audio.Integration;
|
using Ryujinx.Audio.Integration;
|
||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.System;
|
using Ryujinx.Common.System;
|
||||||
|
@ -18,6 +20,7 @@ using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.FileSystem.Content;
|
using Ryujinx.HLE.FileSystem.Content;
|
||||||
using Ryujinx.HLE.HOS;
|
using Ryujinx.HLE.HOS;
|
||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using Ryujinx.Input.GTK3;
|
using Ryujinx.Input.GTK3;
|
||||||
using Ryujinx.Input.HLE;
|
using Ryujinx.Input.HLE;
|
||||||
using Ryujinx.Input.SDL2;
|
using Ryujinx.Input.SDL2;
|
||||||
|
@ -166,6 +169,10 @@ namespace Ryujinx.Ui
|
||||||
|
|
||||||
RendererWidgetBase.StatusUpdatedEvent += Update_StatusBar;
|
RendererWidgetBase.StatusUpdatedEvent += Update_StatusBar;
|
||||||
|
|
||||||
|
ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState;
|
||||||
|
ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState;
|
||||||
|
ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState;
|
||||||
|
|
||||||
if (ConfigurationState.Instance.Ui.StartFullscreen)
|
if (ConfigurationState.Instance.Ui.StartFullscreen)
|
||||||
{
|
{
|
||||||
_startFullScreen.Active = true;
|
_startFullScreen.Active = true;
|
||||||
|
@ -236,6 +243,30 @@ namespace Ryujinx.Ui
|
||||||
InputManager = new InputManager(new GTK3KeyboardDriver(this), new SDL2GamepadDriver());
|
InputManager = new InputManager(new GTK3KeyboardDriver(this), new SDL2GamepadDriver());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs<bool> args)
|
||||||
|
{
|
||||||
|
if (_emulationContext != null)
|
||||||
|
{
|
||||||
|
_emulationContext.Configuration.IgnoreMissingServices = args.NewValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAspectRatioState(object sender, ReactiveEventArgs<AspectRatio> args)
|
||||||
|
{
|
||||||
|
if (_emulationContext != null)
|
||||||
|
{
|
||||||
|
_emulationContext.Configuration.AspectRatio = args.NewValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDockedModeState(object sender, ReactiveEventArgs<bool> e)
|
||||||
|
{
|
||||||
|
if (_emulationContext != null)
|
||||||
|
{
|
||||||
|
_emulationContext.System.ChangeDockedModeState(e.NewValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void WindowStateEvent_Changed(object o, WindowStateEventArgs args)
|
private void WindowStateEvent_Changed(object o, WindowStateEventArgs args)
|
||||||
{
|
{
|
||||||
_fullScreen.Label = args.Event.NewWindowState.HasFlag(Gdk.WindowState.Fullscreen) ? "Exit Fullscreen" : "Enter Fullscreen";
|
_fullScreen.Label = args.Event.NewWindowState.HasFlag(Gdk.WindowState.Fullscreen) ? "Exit Fullscreen" : "Enter Fullscreen";
|
||||||
|
@ -380,19 +411,29 @@ namespace Ryujinx.Ui
|
||||||
? HLE.MemoryConfiguration.MemoryConfiguration6GB
|
? HLE.MemoryConfiguration.MemoryConfiguration6GB
|
||||||
: HLE.MemoryConfiguration.MemoryConfiguration4GB;
|
: HLE.MemoryConfiguration.MemoryConfiguration4GB;
|
||||||
|
|
||||||
_emulationContext = new HLE.Switch(
|
IntegrityCheckLevel fsIntegrityCheckLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None;
|
||||||
_virtualFileSystem,
|
|
||||||
|
HLE.HLEConfiguration configuration = new HLE.HLEConfiguration(_virtualFileSystem,
|
||||||
_contentManager,
|
_contentManager,
|
||||||
_accountManager,
|
_accountManager,
|
||||||
_userChannelPersistence,
|
_userChannelPersistence,
|
||||||
renderer,
|
renderer,
|
||||||
deviceDriver,
|
deviceDriver,
|
||||||
memoryConfiguration)
|
memoryConfiguration,
|
||||||
{
|
_uiHandler,
|
||||||
UiHandler = _uiHandler
|
(SystemLanguage)ConfigurationState.Instance.System.Language.Value,
|
||||||
};
|
(RegionCode)ConfigurationState.Instance.System.Region.Value,
|
||||||
|
ConfigurationState.Instance.Graphics.EnableVsync,
|
||||||
|
ConfigurationState.Instance.System.EnableDockedMode,
|
||||||
|
ConfigurationState.Instance.System.EnablePtc,
|
||||||
|
fsIntegrityCheckLevel,
|
||||||
|
ConfigurationState.Instance.System.FsGlobalAccessLogMode,
|
||||||
|
ConfigurationState.Instance.System.SystemTimeOffset,
|
||||||
|
ConfigurationState.Instance.System.TimeZone,
|
||||||
|
ConfigurationState.Instance.System.IgnoreMissingServices,
|
||||||
|
ConfigurationState.Instance.Graphics.AspectRatio);
|
||||||
|
|
||||||
_emulationContext.Initialize();
|
_emulationContext = new HLE.Switch(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupProgressUiHandlers()
|
private void SetupProgressUiHandlers()
|
||||||
|
|
|
@ -73,8 +73,6 @@ namespace Ryujinx.Ui
|
||||||
NpadManager = _inputManager.CreateNpadManager();
|
NpadManager = _inputManager.CreateNpadManager();
|
||||||
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
|
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
|
||||||
|
|
||||||
NpadManager.ReloadConfiguration(ConfigurationState.Instance.Hid.InputConfig.Value.ToList());
|
|
||||||
|
|
||||||
WaitEvent = new ManualResetEvent(false);
|
WaitEvent = new ManualResetEvent(false);
|
||||||
|
|
||||||
_glLogLevel = glLogLevel;
|
_glLogLevel = glLogLevel;
|
||||||
|
@ -300,6 +298,8 @@ namespace Ryujinx.Ui
|
||||||
Device = device;
|
Device = device;
|
||||||
Renderer = Device.Gpu.Renderer;
|
Renderer = Device.Gpu.Renderer;
|
||||||
Renderer?.Window.SetSize(_windowWidth, _windowHeight);
|
Renderer?.Window.SetSize(_windowWidth, _windowHeight);
|
||||||
|
|
||||||
|
NpadManager.Initialize(device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render()
|
public void Render()
|
||||||
|
@ -488,7 +488,7 @@ namespace Ryujinx.Ui
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
NpadManager.Update(Device.Hid, Device.TamperMachine);
|
NpadManager.Update();
|
||||||
|
|
||||||
if (_isFocused)
|
if (_isFocused)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1143,7 +1143,7 @@ namespace Ryujinx.Ui.Windows
|
||||||
|
|
||||||
if (_mainWindow.RendererWidget != null)
|
if (_mainWindow.RendererWidget != null)
|
||||||
{
|
{
|
||||||
_mainWindow.RendererWidget.NpadManager.ReloadConfiguration(newConfig);
|
_mainWindow.RendererWidget.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atomically replace and signal input change.
|
// Atomically replace and signal input change.
|
||||||
|
|
|
@ -263,7 +263,7 @@ namespace Ryujinx.Ui.Windows
|
||||||
}
|
}
|
||||||
|
|
||||||
_systemTimeZoneEntry.WidthChars = Math.Max(20, maxLocationLength + 1); // Ensure minimum Entry width
|
_systemTimeZoneEntry.WidthChars = Math.Max(20, maxLocationLength + 1); // Ensure minimum Entry width
|
||||||
_systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName();
|
_systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(ConfigurationState.Instance.System.TimeZone);
|
||||||
|
|
||||||
_systemTimeZoneCompletion.MatchFunc = TimeZoneMatchFunc;
|
_systemTimeZoneCompletion.MatchFunc = TimeZoneMatchFunc;
|
||||||
|
|
||||||
|
@ -462,7 +462,7 @@ namespace Ryujinx.Ui.Windows
|
||||||
{
|
{
|
||||||
if (!_validTzRegions.Contains(_systemTimeZoneEntry.Text))
|
if (!_validTzRegions.Contains(_systemTimeZoneEntry.Text))
|
||||||
{
|
{
|
||||||
_systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName();
|
_systemTimeZoneEntry.Text = _timeZoneContentManager.SanityCheckDeviceLocationName(ConfigurationState.Instance.System.TimeZone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue