Compare commits

..

5 Commits

Author SHA1 Message Date
ccf23fc629 gui: Fixes the games icon when there is an update (#3148)
* gui: Fixes the games icon when there is a game update

Currently we just load the version of the update, instead of the whole NACP file. This PR fixes that. A little cleanup is made into the code to avoid duplicate things.
(Closes #3039)

* Fix condition
2022-02-22 14:53:39 +01:00
f1460d5494 A32: Fix BLX and BXWritePC (#3151) 2022-02-22 10:41:56 -03:00
644b497df1 Collapse AsSpan().Slice(..) calls into AsSpan(..) (#3145)
* Collapse AsSpan().Slice(..) calls into AsSpan(..)

Less code and a bit faster

* Collapse an Array.Clear(array, 0, array.Length) call to Array.Clear(array)
2022-02-22 10:32:10 -03:00
fb935fd201 Add dedicated ServerBase for FileSystem services (#3142)
This should prevent filesystem services from blocking other services that don't have their own ServerBase. May improve filesystem related stutters in certain titles.

Improves button advanced cutscenes such as Miqol's Request in Xenoblade: DE when the game is on a network share (used to stutter when voice lines played).

Should probably be tested to make sure no mysterious bugs have been unearthed, and to see if any other filesystem related perf issues are improved.
2022-02-19 15:29:11 +01:00
f2087ca29e PPTC version increment (#3139) 2022-02-17 23:52:42 -03:00
18 changed files with 49 additions and 50 deletions

View File

@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions
SetFlag(context, PState.TFlag, bitOne); SetFlag(context, PState.TFlag, bitOne);
EmitVirtualCall(context, addr); EmitBxWritePc(context, addr);
} }
public static void Bx(ArmEmitterContext context) public static void Bx(ArmEmitterContext context)

View File

@ -186,7 +186,7 @@ namespace ARMeilleure.Instructions
SetFlag(context, PState.TFlag, mode); SetFlag(context, PState.TFlag, mode);
Operand addr = context.ConditionalSelect(mode, pc, context.BitwiseAnd(pc, Const(~3))); Operand addr = context.ConditionalSelect(mode, context.BitwiseAnd(pc, Const(~1)), context.BitwiseAnd(pc, Const(~3)));
InstEmitFlowHelper.EmitVirtualJump(context, addr, isReturn); InstEmitFlowHelper.EmitVirtualJump(context, addr, isReturn);
} }

View File

@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 3061; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 3138; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View File

@ -113,7 +113,7 @@ namespace ARMeilleure.Translation
} }
} }
Array.Clear(localDefs, 0, localDefs.Length); Array.Clear(localDefs);
} }
// Second pass, rename variables with definitions on different blocks. // Second pass, rename variables with definitions on different blocks.

View File

@ -112,12 +112,12 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
private ReadOnlySpan<float> GetFdnDelayTimesByLateMode(ReverbLateMode lateMode) private ReadOnlySpan<float> GetFdnDelayTimesByLateMode(ReverbLateMode lateMode)
{ {
return FdnDelayTimes.AsSpan().Slice((int)lateMode * 4, 4); return FdnDelayTimes.AsSpan((int)lateMode * 4, 4);
} }
private ReadOnlySpan<float> GetDecayDelayTimesByLateMode(ReverbLateMode lateMode) private ReadOnlySpan<float> GetDecayDelayTimesByLateMode(ReverbLateMode lateMode)
{ {
return DecayDelayTimes.AsSpan().Slice((int)lateMode * 4, 4); return DecayDelayTimes.AsSpan((int)lateMode * 4, 4);
} }
public ReverbState(ref ReverbParameter parameter, ulong workBuffer, bool isLongSizePreDelaySupported) public ReverbState(ref ReverbParameter parameter, ulong workBuffer, bool isLongSizePreDelaySupported)

View File

@ -459,7 +459,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
for (int i = 0; i < Constants.VoiceWaveBufferCount; i++) for (int i = 0; i < Constants.VoiceWaveBufferCount; i++)
{ {
UpdateWaveBuffer(errorInfos.AsSpan().Slice(i * 2, 2), ref WaveBuffers[i], ref parameter.WaveBuffers[i], parameter.SampleFormat, voiceUpdateState.IsWaveBufferValid[i], ref mapper, ref behaviourContext); UpdateWaveBuffer(errorInfos.AsSpan(i * 2, 2), ref WaveBuffers[i], ref parameter.WaveBuffers[i], parameter.SampleFormat, voiceUpdateState.IsWaveBufferValid[i], ref mapper, ref behaviourContext);
} }
} }

View File

@ -113,7 +113,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
dataSpan[i++] = hash; dataSpan[i++] = hash;
} }
manifestHeader.UpdateChecksum(data.AsSpan().Slice(Unsafe.SizeOf<CacheManifestHeader>())); manifestHeader.UpdateChecksum(data.AsSpan(Unsafe.SizeOf<CacheManifestHeader>()));
MemoryMarshal.Write(data, ref manifestHeader); MemoryMarshal.Write(data, ref manifestHeader);
@ -447,12 +447,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
if (cb1DataAddress != 0 && cb1DataSize != 0) if (cb1DataAddress != 0 && cb1DataSize != 0)
{ {
memoryManager.Physical.GetSpan(cb1DataAddress, cb1DataSize).CopyTo(code.AsSpan().Slice(size, cb1DataSize)); memoryManager.Physical.GetSpan(cb1DataAddress, cb1DataSize).CopyTo(code.AsSpan(size, cb1DataSize));
} }
if (translatorContext2 != null) if (translatorContext2 != null)
{ {
memoryManager.GetSpan(translatorContext2.Address, sizeA).CopyTo(code.AsSpan().Slice(size + cb1DataSize, sizeA)); memoryManager.GetSpan(translatorContext2.Address, sizeA).CopyTo(code.AsSpan(size + cb1DataSize, sizeA));
} }
GuestGpuAccessorHeader gpuAccessorHeader = CreateGuestGpuAccessorCache(context.GpuAccessor); GuestGpuAccessorHeader gpuAccessorHeader = CreateGuestGpuAccessorCache(context.GpuAccessor);

View File

@ -206,7 +206,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
program = new ShaderProgram(entry.Header.Stage, ""); program = new ShaderProgram(entry.Header.Stage, "");
shaderProgramInfo = hostShaderEntries[0].ToShaderProgramInfo(); shaderProgramInfo = hostShaderEntries[0].ToShaderProgramInfo();
byte[] code = entry.Code.AsSpan().Slice(0, entry.Header.Size - entry.Header.Cb1DataSize).ToArray(); byte[] code = entry.Code.AsSpan(0, entry.Header.Size - entry.Header.Cb1DataSize).ToArray();
ShaderCodeHolder shader = new ShaderCodeHolder(program, shaderProgramInfo, code); ShaderCodeHolder shader = new ShaderCodeHolder(program, shaderProgramInfo, code);
@ -244,7 +244,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
return true; // Exit early, the decoding step failed. return true; // Exit early, the decoding step failed.
} }
byte[] code = entry.Code.AsSpan().Slice(0, entry.Header.Size - entry.Header.Cb1DataSize).ToArray(); byte[] code = entry.Code.AsSpan(0, entry.Header.Size - entry.Header.Cb1DataSize).ToArray();
ShaderCodeHolder shader = new ShaderCodeHolder(program, shaderProgramInfo, code); ShaderCodeHolder shader = new ShaderCodeHolder(program, shaderProgramInfo, code);
@ -394,8 +394,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
} }
// NOTE: Vertex B comes first in the shader cache. // NOTE: Vertex B comes first in the shader cache.
byte[] code = entry.Code.AsSpan().Slice(0, entry.Header.Size - entry.Header.Cb1DataSize).ToArray(); byte[] code = entry.Code.AsSpan(0, entry.Header.Size - entry.Header.Cb1DataSize).ToArray();
byte[] code2 = entry.Header.SizeA != 0 ? entry.Code.AsSpan().Slice(entry.Header.Size, entry.Header.SizeA).ToArray() : null; byte[] code2 = entry.Header.SizeA != 0 ? entry.Code.AsSpan(entry.Header.Size, entry.Header.SizeA).ToArray() : null;
shaders[i] = new ShaderCodeHolder(program, shaderProgramInfo, code, code2); shaders[i] = new ShaderCodeHolder(program, shaderProgramInfo, code, code2);

View File

@ -124,7 +124,7 @@ namespace Ryujinx.Graphics.OpenGL
GL.GetProgramBinary(Handle, size, out _, out BinaryFormat binFormat, data); GL.GetProgramBinary(Handle, size, out _, out BinaryFormat binFormat, data);
BinaryPrimitives.WriteInt32LittleEndian(data.AsSpan().Slice(size, 4), (int)binFormat); BinaryPrimitives.WriteInt32LittleEndian(data.AsSpan(size, 4), (int)binFormat);
return data; return data;
} }

View File

@ -76,6 +76,7 @@ namespace Ryujinx.HLE.HOS
internal ServerBase BsdServer { get; private set; } internal ServerBase BsdServer { get; private set; }
internal ServerBase AudRenServer { get; private set; } internal ServerBase AudRenServer { get; private set; }
internal ServerBase AudOutServer { get; private set; } internal ServerBase AudOutServer { get; private set; }
internal ServerBase FsServer { get; private set; }
internal ServerBase HidServer { get; private set; } internal ServerBase HidServer { get; private set; }
internal ServerBase NvDrvServer { get; private set; } internal ServerBase NvDrvServer { get; private set; }
internal ServerBase TimeServer { get; private set; } internal ServerBase TimeServer { get; private set; }
@ -298,6 +299,7 @@ namespace Ryujinx.HLE.HOS
BsdServer = new ServerBase(KernelContext, "BsdServer"); BsdServer = new ServerBase(KernelContext, "BsdServer");
AudRenServer = new ServerBase(KernelContext, "AudioRendererServer"); AudRenServer = new ServerBase(KernelContext, "AudioRendererServer");
AudOutServer = new ServerBase(KernelContext, "AudioOutServer"); AudOutServer = new ServerBase(KernelContext, "AudioOutServer");
FsServer = new ServerBase(KernelContext, "FsServer");
HidServer = new ServerBase(KernelContext, "HidServer"); HidServer = new ServerBase(KernelContext, "HidServer");
NvDrvServer = new ServerBase(KernelContext, "NvservicesServer"); NvDrvServer = new ServerBase(KernelContext, "NvservicesServer");
TimeServer = new ServerBase(KernelContext, "TimeServer"); TimeServer = new ServerBase(KernelContext, "TimeServer");

View File

@ -7,6 +7,8 @@ namespace Ryujinx.HLE.HOS.Services
{ {
private int _disposeState; private int _disposeState;
public DisposableIpcService(ServerBase server = null) : base(server) { }
protected abstract void Dispose(bool isDisposing); protected abstract void Dispose(bool isDisposing);
public void Dispose() public void Dispose()

View File

@ -28,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
{ {
private SharedRef<LibHac.FsSrv.Sf.IFileSystemProxy> _baseFileSystemProxy; private SharedRef<LibHac.FsSrv.Sf.IFileSystemProxy> _baseFileSystemProxy;
public IFileSystemProxy(ServiceCtx context) public IFileSystemProxy(ServiceCtx context) : base(context.Device.System.FsServer)
{ {
var applicationClient = context.Device.System.LibHacHorizonManager.ApplicationClient; var applicationClient = context.Device.System.LibHacHorizonManager.ApplicationClient;
_baseFileSystemProxy = applicationClient.Fs.Impl.GetFileSystemProxyServiceObject(); _baseFileSystemProxy = applicationClient.Fs.Impl.GetFileSystemProxyServiceObject();

View File

@ -185,7 +185,7 @@ namespace Ryujinx.HLE.HOS.Services
{ {
for (int i = 0; i < request.RecvListBuff.Count; i++) for (int i = 0; i < request.RecvListBuff.Count; i++)
{ {
ulong size = (ulong)BinaryPrimitives.ReadInt16LittleEndian(request.RawData.AsSpan().Slice(sizesOffset + i * 2, 2)); ulong size = (ulong)BinaryPrimitives.ReadInt16LittleEndian(request.RawData.AsSpan(sizesOffset + i * 2, 2));
response.PtrBuff.Add(new IpcPtrBuffDesc(tempAddr, (uint)i, size)); response.PtrBuff.Add(new IpcPtrBuffDesc(tempAddr, (uint)i, size));

View File

@ -8,9 +8,9 @@ namespace Ryujinx.HLE.Loaders.Executables
class KipExecutable : IExecutable class KipExecutable : IExecutable
{ {
public byte[] Program { get; } public byte[] Program { get; }
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)TextSize); public Span<byte> Text => Program.AsSpan((int)TextOffset, (int)TextSize);
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)RoSize); public Span<byte> Ro => Program.AsSpan((int)RoOffset, (int)RoSize);
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)DataSize); public Span<byte> Data => Program.AsSpan((int)DataOffset, (int)DataSize);
public uint TextOffset { get; } public uint TextOffset { get; }
public uint RoOffset { get; } public uint RoOffset { get; }
@ -76,7 +76,7 @@ namespace Ryujinx.HLE.Loaders.Executables
{ {
reader.GetSegmentSize(segmentType, out int uncompressedSize).ThrowIfFailure(); reader.GetSegmentSize(segmentType, out int uncompressedSize).ThrowIfFailure();
var span = program.AsSpan().Slice((int)offset, uncompressedSize); var span = program.AsSpan((int)offset, uncompressedSize);
reader.ReadSegment(segmentType, span).ThrowIfFailure(); reader.ReadSegment(segmentType, span).ThrowIfFailure();

View File

@ -7,9 +7,9 @@ namespace Ryujinx.HLE.Loaders.Executables
class NroExecutable : Nro, IExecutable class NroExecutable : Nro, IExecutable
{ {
public byte[] Program { get; } public byte[] Program { get; }
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)Header.NroSegments[0].Size); public Span<byte> Text => Program.AsSpan((int)TextOffset, (int)Header.NroSegments[0].Size);
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)Header.NroSegments[1].Size); public Span<byte> Ro => Program.AsSpan((int)RoOffset, (int)Header.NroSegments[1].Size);
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)Header.NroSegments[2].Size); public Span<byte> Data => Program.AsSpan((int)DataOffset, (int)Header.NroSegments[2].Size);
public uint TextOffset => Header.NroSegments[0].FileOffset; public uint TextOffset => Header.NroSegments[0].FileOffset;
public uint RoOffset => Header.NroSegments[1].FileOffset; public uint RoOffset => Header.NroSegments[1].FileOffset;

View File

@ -12,9 +12,9 @@ namespace Ryujinx.HLE.Loaders.Executables
class NsoExecutable : IExecutable class NsoExecutable : IExecutable
{ {
public byte[] Program { get; } public byte[] Program { get; }
public Span<byte> Text => Program.AsSpan().Slice((int)TextOffset, (int)TextSize); public Span<byte> Text => Program.AsSpan((int)TextOffset, (int)TextSize);
public Span<byte> Ro => Program.AsSpan().Slice((int)RoOffset, (int)RoSize); public Span<byte> Ro => Program.AsSpan((int)RoOffset, (int)RoSize);
public Span<byte> Data => Program.AsSpan().Slice((int)DataOffset, (int)DataSize); public Span<byte> Data => Program.AsSpan((int)DataOffset, (int)DataSize);
public uint TextOffset { get; } public uint TextOffset { get; }
public uint RoOffset { get; } public uint RoOffset { get; }
@ -58,7 +58,7 @@ namespace Ryujinx.HLE.Loaders.Executables
{ {
reader.GetSegmentSize(segmentType, out uint uncompressedSize).ThrowIfFailure(); reader.GetSegmentSize(segmentType, out uint uncompressedSize).ThrowIfFailure();
var span = Program.AsSpan().Slice((int)offset, (int)uncompressedSize); var span = Program.AsSpan((int)offset, (int)uncompressedSize);
reader.ReadSegment(segmentType, span).ThrowIfFailure(); reader.ReadSegment(segmentType, span).ThrowIfFailure();

View File

@ -85,7 +85,7 @@ namespace Ryujinx.HLE.Loaders.Mods
Logger.Info?.Print(LogClass.ModLoader, $"Patching address offset {patchOffset:x} <= {BitConverter.ToString(patch).Replace('-', ' ')} len={patchSize}"); Logger.Info?.Print(LogClass.ModLoader, $"Patching address offset {patchOffset:x} <= {BitConverter.ToString(patch).Replace('-', ' ')} len={patchSize}");
patch.AsSpan().Slice(0, patchSize).CopyTo(memory.Slice(patchOffset, patchSize)); patch.AsSpan(0, patchSize).CopyTo(memory.Slice(patchOffset, patchSize));
count++; count++;
} }

View File

@ -242,15 +242,18 @@ namespace Ryujinx.Ui.App
} }
else else
{ {
// Store the ControlFS in variable called controlFs
GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId); GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId);
// Check if there is an update available.
if (IsUpdateApplied(titleId, out IFileSystem updatedControlFs))
{
// Replace the original ControlFs by the updated one.
controlFs = updatedControlFs;
}
ReadControlData(controlFs, controlHolder.ByteSpan); ReadControlData(controlFs, controlHolder.ByteSpan);
// Get the title name, title ID, developer name and version number from the NACP GetGameInformation(ref controlHolder.Value, out titleName, out _, out developer, out version);
version = IsUpdateApplied(titleId, out string updateVersion) ? updateVersion : controlHolder.Value.DisplayVersion.ToString();
GetNameIdDeveloper(ref controlHolder.Value, out titleName, out _, out developer);
// Read the icon from the ControlFS and store it as a byte array // Read the icon from the ControlFS and store it as a byte array
try try
@ -351,10 +354,7 @@ namespace Ryujinx.Ui.App
// Read the NACP data // Read the NACP data
Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan); Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan);
// Get the title name, title ID, developer name and version number from the NACP GetGameInformation(ref controlHolder.Value, out titleName, out titleId, out developer, out version);
version = controlHolder.Value.DisplayVersion.ToString();
GetNameIdDeveloper(ref controlHolder.Value, out titleName, out titleId, out developer);
} }
else else
{ {
@ -554,7 +554,7 @@ namespace Ryujinx.Ui.App
return readableString; return readableString;
} }
private void GetNameIdDeveloper(ref ApplicationControlProperty controlData, out string titleName, out string titleId, out string publisher) private void GetGameInformation(ref ApplicationControlProperty controlData, out string titleName, out string titleId, out string publisher, out string version)
{ {
_ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage); _ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage);
@ -611,10 +611,14 @@ namespace Ryujinx.Ui.App
{ {
titleId = "0000000000000000"; titleId = "0000000000000000";
} }
version = controlData.DisplayVersion.ToString();
} }
private bool IsUpdateApplied(string titleId, out string version) private bool IsUpdateApplied(string titleId, out IFileSystem updatedControlFs)
{ {
updatedControlFs = null;
string updatePath = "(unknown)"; string updatePath = "(unknown)";
try try
@ -623,14 +627,7 @@ namespace Ryujinx.Ui.App
if (patchNca != null && controlNca != null) if (patchNca != null && controlNca != null)
{ {
ApplicationControlProperty controlData = new ApplicationControlProperty(); updatedControlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
using var nacpFile = new UniqueRef<IFile>();
controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None).OpenFile(ref nacpFile.Ref(), "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure();
nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure();
version = controlData.DisplayVersion.ToString();
return true; return true;
} }
@ -645,8 +642,6 @@ namespace Ryujinx.Ui.App
Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}. Errored File: {updatePath}"); Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}. Errored File: {updatePath}");
} }
version = "";
return false; return false;
} }
} }