Compare commits

..

5 Commits

Author SHA1 Message Date
riperiperi
086564c3c8 HLE: Fix Mii crc generation and minor issues (#5766)
* HLE: Fix Mii crc generation

Validating CRCs for data and device involves calculating the crc of all data including the crc being checked, which should then be 0.

The crc should be _generated_ on all data _before_ the crc in the struct. It shouldn't include the crcs themselves.

This fixes all generated miis (eg. default) having invalid crcs. This does not affect mii maker, as that generates its own charinfo.

Does not fix MK8D crash.

* Fix other mii issues

* Fully define all fields for Nickname and Ver3StoreData

Fixes an issue where the nickname for a mii would only have the first character on some method calls.

* Add Array96 type
2023-10-06 19:23:39 -03:00
gdkchan
b6ac45d36d Fix SPIR-V call out arguments regression (#5767)
* Fix SPIR-V call out arguments regression

* Shader cache version bump
2023-10-06 00:18:30 -03:00
dependabot[bot]
7afae8c699 nuget: bump Microsoft.CodeAnalysis.CSharp from 4.6.0 to 4.7.0 (#5608)
Bumps [Microsoft.CodeAnalysis.CSharp](https://github.com/dotnet/roslyn) from 4.6.0 to 4.7.0.
- [Release notes](https://github.com/dotnet/roslyn/releases)
- [Changelog](https://github.com/dotnet/roslyn/blob/main/docs/Breaking%20API%20Changes.md)
- [Commits](https://github.com/dotnet/roslyn/commits)

---
updated-dependencies:
- dependency-name: Microsoft.CodeAnalysis.CSharp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-05 13:40:03 +02:00
Marco Carvalho
7835968214 Strings should not be concatenated using '+' in a loop (#5664)
* Strings should not be concatenated using '+' in a loop

* fix IDE0090

* undo GenerateLoadOrStore

* prefer string interpolation

* Update src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs

Co-authored-by: Mary <thog@protonmail.com>

---------

Co-authored-by: Mary <thog@protonmail.com>
2023-10-05 12:41:00 +02:00
gdkchan
0aceb534cb Fix SPIR-V function calls (#5764)
* Fix SPIR-V function calls

* Shader cache version bump
2023-10-04 21:35:26 -03:00
22 changed files with 122 additions and 81 deletions

View File

@@ -20,7 +20,7 @@
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" /> <PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
<PackageVersion Include="LibHac" Version="0.18.0" /> <PackageVersion Include="LibHac" Version="0.18.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" /> <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.7.2" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" /> <PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" /> <PackageVersion Include="MsgPack.Cli" Version="1.0.1" />

View File

@@ -1,6 +1,7 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Text;
namespace ARMeilleure.Diagnostics namespace ARMeilleure.Diagnostics
{ {
@@ -48,14 +49,15 @@ namespace ARMeilleure.Diagnostics
ulong diff = address - symbol.Start; ulong diff = address - symbol.Start;
ulong rem = diff % symbol.ElementSize; ulong rem = diff % symbol.ElementSize;
result = symbol.Name + "_" + diff / symbol.ElementSize; StringBuilder resultBuilder = new();
resultBuilder.Append($"{symbol.Name}_{diff / symbol.ElementSize}");
if (rem != 0) if (rem != 0)
{ {
result += "+" + rem; resultBuilder.Append($"+{rem}");
} }
_symbols.TryAdd(address, result); _symbols.TryAdd(address, resultBuilder.ToString());
return result; return result;
} }

View File

@@ -327,7 +327,7 @@ namespace Ryujinx.Ava.UI.ViewModels
string imageUrl = _amiiboList.Find(amiibo => amiibo.Equals(selected)).Image; string imageUrl = _amiiboList.Find(amiibo => amiibo.Equals(selected)).Image;
string usageString = ""; StringBuilder usageStringBuilder = new();
for (int i = 0; i < _amiiboList.Count; i++) for (int i = 0; i < _amiiboList.Count; i++)
{ {
@@ -341,20 +341,19 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
foreach (AmiiboApiUsage usageItem in item.AmiiboUsage) foreach (AmiiboApiUsage usageItem in item.AmiiboUsage)
{ {
usageString += Environment.NewLine + usageStringBuilder.Append($"{Environment.NewLine}- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}");
$"- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}";
writable = usageItem.Write; writable = usageItem.Write;
} }
} }
} }
if (usageString.Length == 0) if (usageStringBuilder.Length == 0)
{ {
usageString = LocaleManager.Instance[LocaleKeys.Unknown] + "."; usageStringBuilder.Append($"{LocaleManager.Instance[LocaleKeys.Unknown]}.");
} }
Usage = $"{LocaleManager.Instance[LocaleKeys.Usage]} {(writable ? $" ({LocaleManager.Instance[LocaleKeys.Writable]})" : "")} : {usageString}"; Usage = $"{LocaleManager.Instance[LocaleKeys.Usage]} {(writable ? $" ({LocaleManager.Instance[LocaleKeys.Writable]})" : "")} : {usageStringBuilder}";
} }
} }

View File

@@ -756,6 +756,18 @@ namespace Ryujinx.Common.Memory
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array96<T> : IArray<T> where T : unmanaged
{
T _e0;
Array64<T> _other;
Array31<T> _other2;
public readonly int Length => 96;
public ref T this[int index] => ref AsSpan()[index];
[Pure]
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
}
public struct Array127<T> : IArray<T> where T : unmanaged public struct Array127<T> : IArray<T> where T : unmanaged
{ {
T _e0; T _e0;

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2; private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 5757; private const uint CodeGenVersion = 5767;
private const string SharedTocFileName = "shared.toc"; private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data"; private const string SharedDataFileName = "shared.data";

View File

@@ -92,14 +92,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static string GetIndentation(int level) private static string GetIndentation(int level)
{ {
string indentation = string.Empty; StringBuilder indentationBuilder = new();
for (int index = 0; index < level; index++) for (int index = 0; index < level; index++)
{ {
indentation += Tab; indentationBuilder.Append(Tab);
} }
return indentation; return indentationBuilder.ToString();
} }
} }
} }

View File

@@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Text;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenBallot; using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenBallot;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenCall; using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenCall;
@@ -67,11 +68,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
int arity = (int)(info.Type & InstType.ArityMask); int arity = (int)(info.Type & InstType.ArityMask);
string args = string.Empty; StringBuilder builder = new();
if (atomic && (operation.StorageKind == StorageKind.StorageBuffer || operation.StorageKind == StorageKind.SharedMemory)) if (atomic && (operation.StorageKind == StorageKind.StorageBuffer || operation.StorageKind == StorageKind.SharedMemory))
{ {
args = GenerateLoadOrStore(context, operation, isStore: false); builder.Append(GenerateLoadOrStore(context, operation, isStore: false));
AggregateType dstType = operation.Inst == Instruction.AtomicMaxS32 || operation.Inst == Instruction.AtomicMinS32 AggregateType dstType = operation.Inst == Instruction.AtomicMaxS32 || operation.Inst == Instruction.AtomicMinS32
? AggregateType.S32 ? AggregateType.S32
@@ -79,7 +80,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
for (int argIndex = operation.SourcesCount - arity + 2; argIndex < operation.SourcesCount; argIndex++) for (int argIndex = operation.SourcesCount - arity + 2; argIndex < operation.SourcesCount; argIndex++)
{ {
args += ", " + GetSoureExpr(context, operation.GetSource(argIndex), dstType); builder.Append($", {GetSoureExpr(context, operation.GetSource(argIndex), dstType)}");
} }
} }
else else
@@ -88,16 +89,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
if (argIndex != 0) if (argIndex != 0)
{ {
args += ", "; builder.Append(", ");
} }
AggregateType dstType = GetSrcVarType(inst, argIndex); AggregateType dstType = GetSrcVarType(inst, argIndex);
args += GetSoureExpr(context, operation.GetSource(argIndex), dstType); builder.Append(GetSoureExpr(context, operation.GetSource(argIndex), dstType));
} }
} }
return info.OpName + '(' + args + ')'; return $"{info.OpName}({builder})";
} }
else if ((info.Type & InstType.Op) != 0) else if ((info.Type & InstType.Op) != 0)
{ {

View File

@@ -779,17 +779,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
private static string GetMaskMultiDest(int mask) private static string GetMaskMultiDest(int mask)
{ {
string swizzle = "."; StringBuilder swizzleBuilder = new();
swizzleBuilder.Append('.');
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
if ((mask & (1 << i)) != 0) if ((mask & (1 << i)) != 0)
{ {
swizzle += "xyzw"[i]; swizzleBuilder.Append("xyzw"[i]);
} }
} }
return swizzle; return swizzleBuilder.ToString();
} }
} }
} }

View File

@@ -316,16 +316,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
var operand = operation.GetSource(i + 1); var operand = operation.GetSource(i + 1);
if (i >= function.InArguments.Length) AstOperand local = (AstOperand)operand;
{ Debug.Assert(local.Type == OperandType.LocalVariable);
args[i] = context.GetLocalPointer((AstOperand)operand); args[i] = context.GetLocalPointer(local);
}
else
{
var type = function.GetArgumentType(i);
args[i] = context.Get(type, operand);
}
} }
var retType = function.ReturnType; var retType = function.ReturnType;

View File

@@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics; using System.Numerics;
namespace Ryujinx.Graphics.Shader.StructuredIr namespace Ryujinx.Graphics.Shader.StructuredIr
@@ -62,7 +63,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
} }
else else
{ {
AddOperation(context, operation, targetLanguage); AddOperation(context, operation, targetLanguage, functions);
} }
} }
} }
@@ -77,7 +78,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
return context.Info; return context.Info;
} }
private static void AddOperation(StructuredProgramContext context, Operation operation, TargetLanguage targetLanguage) private static void AddOperation(StructuredProgramContext context, Operation operation, TargetLanguage targetLanguage, IReadOnlyList<Function> functions)
{ {
Instruction inst = operation.Inst; Instruction inst = operation.Inst;
StorageKind storageKind = operation.StorageKind; StorageKind storageKind = operation.StorageKind;
@@ -124,14 +125,29 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
// (or at least that's what the Khronos compiler does). // (or at least that's what the Khronos compiler does).
// First one is the function index. // First one is the function index.
sources[0] = context.GetOperandOrCbLoad(operation.GetSource(0)); Operand funcIndexOperand = operation.GetSource(0);
Debug.Assert(funcIndexOperand.Type == OperandType.Constant);
int funcIndex = funcIndexOperand.Value;
sources[0] = new AstOperand(OperandType.Constant, funcIndex);
int inArgsCount = functions[funcIndex].InArgumentsCount;
// Remaining ones are parameters, copy them to a temp local variable. // Remaining ones are parameters, copy them to a temp local variable.
for (int index = 1; index < operation.SourcesCount; index++) for (int index = 1; index < operation.SourcesCount; index++)
{ {
AstOperand argTemp = context.NewTemp(FuncParameterType); IAstNode source = context.GetOperandOrCbLoad(operation.GetSource(index));
context.AddNode(new AstAssignment(argTemp, context.GetOperandOrCbLoad(operation.GetSource(index))));
sources[index] = argTemp; if (index - 1 < inArgsCount)
{
AstOperand argTemp = context.NewTemp(FuncParameterType);
context.AddNode(new AstAssignment(argTemp, source));
sources[index] = argTemp;
}
else
{
sources[index] = source;
}
} }
} }
else else

View File

@@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
namespace Ryujinx.Graphics.Shader.Translation.Optimizations namespace Ryujinx.Graphics.Shader.Translation.Optimizations
@@ -785,30 +786,31 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
private static string GetFunctionName(Operation baseOp, bool isMultiTarget, IReadOnlyList<uint> targetCbs) private static string GetFunctionName(Operation baseOp, bool isMultiTarget, IReadOnlyList<uint> targetCbs)
{ {
string name = baseOp.Inst.ToString(); StringBuilder nameBuilder = new();
nameBuilder.Append(baseOp.Inst.ToString());
name += baseOp.StorageKind switch nameBuilder.Append(baseOp.StorageKind switch
{ {
StorageKind.GlobalMemoryS8 => "S8", StorageKind.GlobalMemoryS8 => "S8",
StorageKind.GlobalMemoryS16 => "S16", StorageKind.GlobalMemoryS16 => "S16",
StorageKind.GlobalMemoryU8 => "U8", StorageKind.GlobalMemoryU8 => "U8",
StorageKind.GlobalMemoryU16 => "U16", StorageKind.GlobalMemoryU16 => "U16",
_ => string.Empty, _ => string.Empty,
}; });
if (isMultiTarget) if (isMultiTarget)
{ {
name += "Multi"; nameBuilder.Append("Multi");
} }
foreach (uint targetCb in targetCbs) foreach (uint targetCb in targetCbs)
{ {
(int sbCbSlot, int sbCbOffset) = UnpackCbSlotAndOffset(targetCb); (int sbCbSlot, int sbCbOffset) = UnpackCbSlotAndOffset(targetCb);
name += $"_c{sbCbSlot}o{sbCbOffset}"; nameBuilder.Append($"_c{sbCbSlot}o{sbCbOffset}");
} }
return name; return nameBuilder.ToString();
} }
private static bool TryGenerateStorageOp( private static bool TryGenerateStorageOp(

View File

@@ -19,6 +19,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Text;
using Path = System.IO.Path; using Path = System.IO.Path;
namespace Ryujinx.HLE.FileSystem namespace Ryujinx.HLE.FileSystem
@@ -817,13 +818,13 @@ namespace Ryujinx.HLE.FileSystem
if (updateNcas.Count > 0) if (updateNcas.Count > 0)
{ {
string extraNcas = string.Empty; StringBuilder extraNcas = new();
foreach (var entry in updateNcas) foreach (var entry in updateNcas)
{ {
foreach (var (type, path) in entry.Value) foreach (var (type, path) in entry.Value)
{ {
extraNcas += path + Environment.NewLine; extraNcas.AppendLine(path);
} }
} }
@@ -954,13 +955,13 @@ namespace Ryujinx.HLE.FileSystem
if (updateNcas.Count > 0) if (updateNcas.Count > 0)
{ {
string extraNcas = string.Empty; StringBuilder extraNcas = new();
foreach (var entry in updateNcas) foreach (var entry in updateNcas)
{ {
foreach (var (type, path) in entry.Value) foreach (var (type, path) in entry.Value)
{ {
extraNcas += path + Environment.NewLine; extraNcas.AppendLine(path);
} }
} }

View File

@@ -436,14 +436,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
uint nameIndex = sym.NameOffset; uint nameIndex = sym.NameOffset;
string name = string.Empty; StringBuilder nameBuilder = new();
for (int chr; (chr = memory.Read<byte>(strTblAddr + nameIndex++)) != 0;) for (int chr; (chr = memory.Read<byte>(strTblAddr + nameIndex++)) != 0;)
{ {
name += (char)chr; nameBuilder.Append((char)chr);
} }
return new ElfSymbol(name, sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size); return new ElfSymbol(nameBuilder.ToString(), sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size);
} }
private static ElfSymbol GetSymbol32(IVirtualMemoryManager memory, ulong address, ulong strTblAddr) private static ElfSymbol GetSymbol32(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
@@ -452,14 +452,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
uint nameIndex = sym.NameOffset; uint nameIndex = sym.NameOffset;
string name = string.Empty; StringBuilder nameBuilder = new();
for (int chr; (chr = memory.Read<byte>(strTblAddr + nameIndex++)) != 0;) for (int chr; (chr = memory.Read<byte>(strTblAddr + nameIndex++)) != 0;)
{ {
name += (char)chr; nameBuilder.Append((char)chr);
} }
return new ElfSymbol(name, sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size); return new ElfSymbol(nameBuilder.ToString(), sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size);
} }
} }
} }

View File

@@ -290,7 +290,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
{ {
coreData = new CoreData(); coreData = new CoreData();
if (charInfo.IsValid()) if (!charInfo.IsValid())
{ {
return ResultCode.InvalidCharInfo; return ResultCode.InvalidCharInfo;
} }

View File

@@ -1,4 +1,5 @@
using System; using Ryujinx.Common.Memory;
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static Ryujinx.HLE.HOS.Services.Mii.Types.RandomMiiConstants; using static Ryujinx.HLE.HOS.Services.Mii.Types.RandomMiiConstants;
@@ -10,9 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
{ {
public const int Size = 0x30; public const int Size = 0x30;
private byte _storage; private Array48<byte> _storage;
public Span<byte> Storage => MemoryMarshal.CreateSpan(ref _storage, Size); public Span<byte> Storage => _storage.AsSpan();
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0x18)] [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0x18)]
public struct ElementInfo public struct ElementInfo

View File

@@ -1,4 +1,5 @@
using System; using Ryujinx.Common.Memory;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@@ -10,12 +11,12 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
public const int CharCount = 10; public const int CharCount = 10;
private const int SizeConst = (CharCount + 1) * 2; private const int SizeConst = (CharCount + 1) * 2;
private byte _storage; private Array22<byte> _storage;
public static Nickname Default => FromString("no name"); public static Nickname Default => FromString("no name");
public static Nickname Question => FromString("???"); public static Nickname Question => FromString("???");
public Span<byte> Raw => MemoryMarshal.CreateSpan(ref _storage, SizeConst); public Span<byte> Raw => _storage.AsSpan();
private ReadOnlySpan<ushort> Characters => MemoryMarshal.Cast<byte, ushort>(Raw); private ReadOnlySpan<ushort> Characters => MemoryMarshal.Cast<byte, ushort>(Raw);

View File

@@ -62,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
private ushort CalculateDataCrc() private ushort CalculateDataCrc()
{ {
return Helper.CalculateCrc16(AsSpanWithoutDeviceCrc(), 0, true); return Helper.CalculateCrc16(AsSpanWithoutCrcs(), 0, true);
} }
private ushort CalculateDeviceCrc() private ushort CalculateDeviceCrc()
@@ -71,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
ushort deviceIdCrc16 = Helper.CalculateCrc16(SpanHelpers.AsByteSpan(ref deviceId), 0, false); ushort deviceIdCrc16 = Helper.CalculateCrc16(SpanHelpers.AsByteSpan(ref deviceId), 0, false);
return Helper.CalculateCrc16(AsSpan(), deviceIdCrc16, true); return Helper.CalculateCrc16(AsSpanWithoutDeviceCrc(), deviceIdCrc16, true);
} }
private ReadOnlySpan<byte> AsSpan() private ReadOnlySpan<byte> AsSpan()
@@ -84,6 +84,11 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
return AsSpan()[..(Size - 2)]; return AsSpan()[..(Size - 2)];
} }
private ReadOnlySpan<byte> AsSpanWithoutCrcs()
{
return AsSpan()[..(Size - 4)];
}
public static StoreData BuildDefault(UtilityImpl utilImpl, uint index) public static StoreData BuildDefault(UtilityImpl utilImpl, uint index)
{ {
StoreData result = new() StoreData result = new()

View File

@@ -1,4 +1,6 @@
using System; using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Mii.Types namespace Ryujinx.HLE.HOS.Services.Mii.Types
@@ -8,9 +10,9 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
{ {
public const int Size = 0x60; public const int Size = 0x60;
private byte _storage; private Array96<byte> _storage;
public Span<byte> Storage => MemoryMarshal.CreateSpan(ref _storage, Size); public Span<byte> Storage => _storage.AsSpan();
// TODO: define all getters/setters // TODO: define all getters/setters
} }

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
namespace Ryujinx.HLE.HOS.Services.Sm namespace Ryujinx.HLE.HOS.Services.Sm
{ {
@@ -235,7 +236,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
private static string ReadName(ServiceCtx context) private static string ReadName(ServiceCtx context)
{ {
string name = string.Empty; StringBuilder nameBuilder = new();
for (int index = 0; index < 8 && for (int index = 0; index < 8 &&
context.RequestData.BaseStream.Position < context.RequestData.BaseStream.Position <
@@ -245,11 +246,11 @@ namespace Ryujinx.HLE.HOS.Services.Sm
if (chr >= 0x20 && chr < 0x7f) if (chr >= 0x20 && chr < 0x7f)
{ {
name += (char)chr; nameBuilder.Append((char)chr);
} }
} }
return name; return nameBuilder.ToString();
} }
public override void DestroyAtExit() public override void DestroyAtExit()

View File

@@ -142,7 +142,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
// OpenDisplay(nn::vi::DisplayName) -> u64 display_id // OpenDisplay(nn::vi::DisplayName) -> u64 display_id
public ResultCode OpenDisplay(ServiceCtx context) public ResultCode OpenDisplay(ServiceCtx context)
{ {
string name = ""; StringBuilder nameBuilder = new();
for (int index = 0; index < 8 && context.RequestData.BaseStream.Position < context.RequestData.BaseStream.Length; index++) for (int index = 0; index < 8 && context.RequestData.BaseStream.Position < context.RequestData.BaseStream.Length; index++)
{ {
@@ -150,11 +150,11 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
if (chr >= 0x20 && chr < 0x7f) if (chr >= 0x20 && chr < 0x7f)
{ {
name += (char)chr; nameBuilder.Append((char)chr);
} }
} }
return OpenDisplayImpl(context, name); return OpenDisplayImpl(context, nameBuilder.ToString());
} }
[CommandCmif(1011)] [CommandCmif(1011)]

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
namespace Ryujinx.Horizon.Sdk.Sm namespace Ryujinx.Horizon.Sdk.Sm
{ {
@@ -78,7 +79,7 @@ namespace Ryujinx.Horizon.Sdk.Sm
public override string ToString() public override string ToString()
{ {
string name = string.Empty; StringBuilder nameBuilder = new();
for (int index = 0; index < sizeof(ulong); index++) for (int index = 0; index < sizeof(ulong); index++)
{ {
@@ -89,10 +90,10 @@ namespace Ryujinx.Horizon.Sdk.Sm
break; break;
} }
name += (char)character; nameBuilder.Append((char)character);
} }
return name; return nameBuilder.ToString();
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Text;
namespace Ryujinx.Ui.LocaleGenerator namespace Ryujinx.Ui.LocaleGenerator
{ {
@@ -15,15 +16,17 @@ namespace Ryujinx.Ui.LocaleGenerator
context.RegisterSourceOutput(contents, (spc, content) => context.RegisterSourceOutput(contents, (spc, content) =>
{ {
var lines = content.Split('\n').Where(x => x.Trim().StartsWith("\"")).Select(x => x.Split(':')[0].Trim().Replace("\"", "")); var lines = content.Split('\n').Where(x => x.Trim().StartsWith("\"")).Select(x => x.Split(':')[0].Trim().Replace("\"", ""));
string enumSource = "namespace Ryujinx.Ava.Common.Locale;\n"; StringBuilder enumSourceBuilder = new();
enumSource += "internal enum LocaleKeys\n{\n"; enumSourceBuilder.AppendLine("namespace Ryujinx.Ava.Common.Locale;");
enumSourceBuilder.AppendLine("internal enum LocaleKeys");
enumSourceBuilder.AppendLine("{");
foreach (var line in lines) foreach (var line in lines)
{ {
enumSource += $" {line},\n"; enumSourceBuilder.AppendLine($" {line},");
} }
enumSource += "}\n"; enumSourceBuilder.AppendLine("}");
spc.AddSource("LocaleKeys", enumSource); spc.AddSource("LocaleKeys", enumSourceBuilder.ToString());
}); });
} }
} }