From 1039797c30ffc2b9f091d3dc813c2494320acba8 Mon Sep 17 00:00:00 2001 From: Merry Date: Tue, 20 Feb 2018 10:41:55 +0000 Subject: [PATCH 01/67] Implement Zip1, Zip2 (#25) --- Ryujinx.Tests/Cpu/CpuTestSimdMove.cs | 45 ++++++++++++++++++++ Ryujinx/Cpu/AOpCodeTable.cs | 2 + Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs | 34 +++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 Ryujinx.Tests/Cpu/CpuTestSimdMove.cs diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdMove.cs b/Ryujinx.Tests/Cpu/CpuTestSimdMove.cs new file mode 100644 index 000000000..d77ac9e52 --- /dev/null +++ b/Ryujinx.Tests/Cpu/CpuTestSimdMove.cs @@ -0,0 +1,45 @@ +using ChocolArm64.State; +using NUnit.Framework; + +namespace Ryujinx.Tests.Cpu +{ + [TestFixture] + public partial class CpuTest + { + [TestCase(0u, 0u, 0x2313221221112010ul, 0x0000000000000000ul)] + [TestCase(1u, 0u, 0x2313221221112010ul, 0x2717261625152414ul)] + [TestCase(0u, 1u, 0x2322131221201110ul, 0x0000000000000000ul)] + [TestCase(1u, 1u, 0x2322131221201110ul, 0x2726171625241514ul)] + [TestCase(0u, 2u, 0x2322212013121110ul, 0x0000000000000000ul)] + [TestCase(1u, 2u, 0x2322212013121110ul, 0x2726252417161514ul)] + [TestCase(1u, 3u, 0x1716151413121110ul, 0x2726252423222120ul)] + public void Zip1_V(uint Q, uint size, ulong Result_0, ulong Result_1) + { + // ZIP1 V0., V1., V2. + uint Opcode = 0x0E023820 | (Q << 30) | (size << 22); + AVec V1 = new AVec { X0 = 0x1716151413121110, X1 = 0x1F1E1D1C1B1A1918 }; + AVec V2 = new AVec { X0 = 0x2726252423222120, X1 = 0x2F2E2D2C2B2A2928 }; + AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2); + Assert.AreEqual(Result_0, ThreadState.V0.X0); + Assert.AreEqual(Result_1, ThreadState.V0.X1); + } + + [TestCase(0u, 0u, 0x2717261625152414ul, 0x0000000000000000ul)] + [TestCase(1u, 0u, 0x2B1B2A1A29192818ul, 0x2F1F2E1E2D1D2C1Cul)] + [TestCase(0u, 1u, 0x2726171625241514ul, 0x0000000000000000ul)] + [TestCase(1u, 1u, 0x2B2A1B1A29281918ul, 0x2F2E1F1E2D2C1D1Cul)] + [TestCase(0u, 2u, 0x2726252417161514ul, 0x0000000000000000ul)] + [TestCase(1u, 2u, 0x2B2A29281B1A1918ul, 0x2F2E2D2C1F1E1D1Cul)] + [TestCase(1u, 3u, 0x1F1E1D1C1B1A1918ul, 0x2F2E2D2C2B2A2928ul)] + public void Zip2_V(uint Q, uint size, ulong Result_0, ulong Result_1) + { + // ZIP2 V0., V1., V2. + uint Opcode = 0x0E027820 | (Q << 30) | (size << 22); + AVec V1 = new AVec { X0 = 0x1716151413121110, X1 = 0x1F1E1D1C1B1A1918 }; + AVec V2 = new AVec { X0 = 0x2726252423222120, X1 = 0x2F2E2D2C2B2A2928 }; + AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2); + Assert.AreEqual(Result_0, ThreadState.V0.X0); + Assert.AreEqual(Result_1, ThreadState.V0.X1); + } + } +} diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index e42136b8c..43a0e63b1 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -256,6 +256,8 @@ namespace ChocolArm64 Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg)); Set("0x001110xx0xxxxx010110xxxxxxxxxx", AInstEmit.Uzp2_V, typeof(AOpCodeSimdReg)); Set("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd)); + Set("0x001110xx0xxxxx001110xxxxxxxxxx", AInstEmit.Zip1_V, typeof(AOpCodeSimdReg)); + Set("0x001110xx0xxxxx011110xxxxxxxxxx", AInstEmit.Zip2_V, typeof(AOpCodeSimdReg)); #endregion } diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs index c8f690328..aabb8f347 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs @@ -263,6 +263,16 @@ namespace ChocolArm64.Instruction } } + public static void Zip1_V(AILEmitterCtx Context) + { + EmitVectorZip(Context, Part: 0); + } + + public static void Zip2_V(AILEmitterCtx Context) + { + EmitVectorZip(Context, Part: 1); + } + private static void EmitIntZeroHigherIfNeeded(AILEmitterCtx Context) { if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) @@ -295,5 +305,29 @@ namespace ChocolArm64.Instruction EmitVectorZeroUpper(Context, Op.Rd); } } + + private static void EmitVectorZip(AILEmitterCtx Context, int Part) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + int Elems = Bytes >> Op.Size; + int Half = Elems >> 1; + + for (int Index = 0; Index < Elems; Index++) + { + int Elem = Part * Half + (Index >> 1); + + EmitVectorExtractZx(Context, (Index & 1) == 0 ? Op.Rn : Op.Rm, Elem, Op.Size); + + EmitVectorInsert(Context, Op.Rd, Index, Op.Size); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } } } \ No newline at end of file From dff28df84eafec61de1eb460e8c17cb1651f8983 Mon Sep 17 00:00:00 2001 From: Merry Date: Tue, 20 Feb 2018 10:52:35 +0000 Subject: [PATCH 02/67] Resize display to window size (#27) --- Ryujinx/Ui/GLScreen.cs | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 0f03d4a0f..8101648ea 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -137,6 +137,8 @@ namespace Ryujinx precision highp float; +uniform vec2 window_size; + layout(location = 0) in vec3 in_position; layout(location = 1) in vec4 in_color; layout(location = 2) in vec2 in_tex_coord; @@ -144,10 +146,20 @@ layout(location = 2) in vec2 in_tex_coord; out vec4 color; out vec2 tex_coord; +// Have a fixed aspect ratio, fit the image within the available space. +vec3 get_scale_ratio() { + vec2 native_size = vec2(1280, 720); + vec2 ratio = vec2( + (window_size.y * native_size.x) / (native_size.y * window_size.x), + (window_size.x * native_size.y) / (native_size.x * window_size.y) + ); + return vec3(min(ratio, vec2(1, 1)), 1); +} + void main(void) { color = in_color; tex_coord = in_tex_coord; - gl_Position = vec4((in_position + vec3(-960, 270, 0)) / vec3(1920, 270, 1), 1); + gl_Position = vec4(in_position * get_scale_ratio(), 1); }"; private string FragShaderSource = @" @@ -168,6 +180,8 @@ void main(void) { private int VtxShaderHandle, FragShaderHandle, PrgShaderHandle; + + private int WindowSizeUniformLocation; private int VaoHandle; private int VboHandle; @@ -216,10 +230,10 @@ void main(void) { uint[] Buffer = new uint[] { - 0xc4700000, 0x80000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x45340000, 0x80000000, 0x00000000, 0xffffffff, 0x00000000, 0x3f800000, 0x00000000, - 0xc4700000, 0xc4070000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x3f800000, - 0x45340000, 0xc4070000, 0x00000000, 0xffffffff, 0x00000000, 0x3f800000, 0x3f800000 + 0xbf800000, 0x3f800000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0xffffffff, 0x00000000, 0x3f800000, 0x00000000, + 0xbf800000, 0xbf800000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x3f800000, + 0x3f800000, 0xbf800000, 0x00000000, 0xffffffff, 0x00000000, 0x3f800000, 0x3f800000 }; IntPtr Length = new IntPtr(Buffer.Length * 4); @@ -269,8 +283,10 @@ void main(void) { GL.UseProgram(PrgShaderHandle); int TexLocation = GL.GetUniformLocation(PrgShaderHandle, "tex"); - GL.Uniform1(TexLocation, 0); + + WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size"); + GL.Uniform2(WindowSizeUniformLocation, new Vector2(1280.0f, 720.0f)); } protected override void OnUpdateFrame(FrameEventArgs e) @@ -335,7 +351,7 @@ void main(void) { protected override void OnRenderFrame(FrameEventArgs e) { - GL.Viewport(0, 0, 1280, 720); + GL.Viewport(0, 0, Width, Height); Title = $"Ryujinx Screen - (Vsync: {VSync} - FPS: {1f / e.Time:0})"; @@ -352,6 +368,12 @@ void main(void) { SwapBuffers(); } + protected override void OnResize(EventArgs e) + { + GL.UseProgram(PrgShaderHandle); + GL.Uniform2(WindowSizeUniformLocation, new Vector2(Width, Height)); + } + void RenderFb() { GL.ActiveTexture(TextureUnit.Texture0); From 068f9bff2e7beafe365f4767d5ec1685a47d38af Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 20 Feb 2018 02:54:00 -0800 Subject: [PATCH 03/67] Misc language usage simplifications (#26) un-nest some logic add some xmldoc simplify ini parse --- Ryujinx/Config.cs | 23 +++++++++++++---------- Ryujinx/Cpu/Translation/AILOpCodeStore.cs | 4 +--- Ryujinx/Hid/HidController.cs | 6 +++++- Ryujinx/Hid/JoyCon.cs | 3 +++ Ryujinx/Logging.cs | 2 +- Ryujinx/OsHle/Handles/HSharedMem.cs | 10 ++-------- Ryujinx/OsHle/Horizon.cs | 7 +------ Ryujinx/Switch.cs | 5 +---- Ryujinx/VirtualFs.cs | 8 ++++---- 9 files changed, 31 insertions(+), 37 deletions(-) diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs index e211441fb..b53614211 100644 --- a/Ryujinx/Config.cs +++ b/Ryujinx/Config.cs @@ -20,7 +20,9 @@ namespace Ryujinx public static void Read() { - IniParser Parser = new IniParser(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Ryujinx.conf")); + var iniFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + var iniPath = Path.Combine(iniFolder, "Ryujinx.conf"); + IniParser Parser = new IniParser(iniPath); LoggingEnableInfo = Convert.ToBoolean(Parser.Value("Logging_Enable_Info")); LoggingEnableTrace = Convert.ToBoolean(Parser.Value("Logging_Enable_Trace")); @@ -70,23 +72,24 @@ namespace Ryujinx // https://stackoverflow.com/a/37772571 public class IniParser { - private Dictionary Values; + private readonly Dictionary Values; public IniParser(string Path) { Values = File.ReadLines(Path) - .Where(Line => (!String.IsNullOrWhiteSpace(Line) && !Line.StartsWith("#"))) - .Select(Line => Line.Split(new char[] { '=' }, 2, 0)) + .Where(Line => !string.IsNullOrWhiteSpace(Line) && !Line.StartsWith('#')) + .Select(Line => Line.Split('=', 2)) .ToDictionary(Parts => Parts[0].Trim(), Parts => Parts.Length > 1 ? Parts[1].Trim() : null); } - public string Value(string Name, string Value = null) + /// + /// Gets the setting value for the requested setting . + /// + /// Setting Name + /// Default value of the setting + public string Value(string Name, string defaultValue = null) { - if (Values != null && Values.ContainsKey(Name)) - { - return Values[Name]; - } - return Value; + return Values.TryGetValue(Name, out var value) ? value : defaultValue; } } } diff --git a/Ryujinx/Cpu/Translation/AILOpCodeStore.cs b/Ryujinx/Cpu/Translation/AILOpCodeStore.cs index 34b26fe28..c4ea53aba 100644 --- a/Ryujinx/Cpu/Translation/AILOpCodeStore.cs +++ b/Ryujinx/Cpu/Translation/AILOpCodeStore.cs @@ -10,10 +10,8 @@ namespace ChocolArm64.Translation public AIoType IoType { get; private set; } public ARegisterSize RegisterSize { get; private set; } - - public AILOpCodeStore(int Index, AIoType IoType) : this(Index, IoType, ARegisterSize.Int64) { } - public AILOpCodeStore(int Index, AIoType IoType, ARegisterSize RegisterSize) + public AILOpCodeStore(int Index, AIoType IoType, ARegisterSize RegisterSize = ARegisterSize.Int64) { this.IoType = IoType; this.Index = Index; diff --git a/Ryujinx/Hid/HidController.cs b/Ryujinx/Hid/HidController.cs index 433d7b9ba..7dd198412 100644 --- a/Ryujinx/Hid/HidController.cs +++ b/Ryujinx/Hid/HidController.cs @@ -1,7 +1,9 @@ -using System.Runtime.InteropServices; +using System; +using System.Runtime.InteropServices; namespace Ryujinx { + [Flags] public enum HidControllerKeys { KEY_A = (1 << 0), @@ -79,12 +81,14 @@ namespace Ryujinx Main } + [Flags] public enum HidControllerConnectionState { Controller_State_Connected = (1 << 0), Controller_State_Wired = (1 << 1) } + [Flags] public enum HidControllerType { ControllerType_ProController = (1 << 0), diff --git a/Ryujinx/Hid/JoyCon.cs b/Ryujinx/Hid/JoyCon.cs index 9dde2b70a..8c9518e58 100644 --- a/Ryujinx/Hid/JoyCon.cs +++ b/Ryujinx/Hid/JoyCon.cs @@ -1,5 +1,8 @@ namespace Ryujinx { + /// + /// Common RGB color hex codes for JoyCon coloring. + /// public enum JoyConColor //Thanks to CTCaer { Body_Grey = 0x828282, diff --git a/Ryujinx/Logging.cs b/Ryujinx/Logging.cs index 308f068f8..2ae858b4e 100644 --- a/Ryujinx/Logging.cs +++ b/Ryujinx/Logging.cs @@ -7,7 +7,7 @@ namespace Ryujinx public static class Logging { private static Stopwatch ExecutionTime = new Stopwatch(); - private static string LogFileName = "Ryujinx.log"; + private const string LogFileName = "Ryujinx.log"; public static bool EnableInfo = Config.LoggingEnableInfo; public static bool EnableTrace = Config.LoggingEnableTrace; diff --git a/Ryujinx/OsHle/Handles/HSharedMem.cs b/Ryujinx/OsHle/Handles/HSharedMem.cs index a493276a2..4f943ebcd 100644 --- a/Ryujinx/OsHle/Handles/HSharedMem.cs +++ b/Ryujinx/OsHle/Handles/HSharedMem.cs @@ -23,10 +23,7 @@ namespace Ryujinx.OsHle.Handles { Positions.Add(Position); - if (MemoryMapped != null) - { - MemoryMapped(this, EventArgs.Empty); - } + MemoryMapped?.Invoke(this, EventArgs.Empty); } } @@ -36,10 +33,7 @@ namespace Ryujinx.OsHle.Handles { Positions.Remove(Position); - if (MemoryUnmapped != null) - { - MemoryUnmapped(this, EventArgs.Empty); - } + MemoryUnmapped?.Invoke(this, EventArgs.Empty); } } diff --git a/Ryujinx/OsHle/Horizon.cs b/Ryujinx/OsHle/Horizon.cs index e72c62dc0..b9af69c2f 100644 --- a/Ryujinx/OsHle/Horizon.cs +++ b/Ryujinx/OsHle/Horizon.cs @@ -165,12 +165,7 @@ namespace Ryujinx.OsHle internal bool TryGetProcess(int ProcessId, out Process Process) { - if (!Processes.TryGetValue(ProcessId, out Process)) - { - return false; - } - - return true; + return Processes.TryGetValue(ProcessId, out Process); } internal void CloseHandle(int Handle) diff --git a/Ryujinx/Switch.cs b/Ryujinx/Switch.cs index b5874051e..4022061bc 100644 --- a/Ryujinx/Switch.cs +++ b/Ryujinx/Switch.cs @@ -30,10 +30,7 @@ namespace Ryujinx internal virtual void OnFinish(EventArgs e) { - if (Finish != null) - { - Finish(this, e); - } + Finish?.Invoke(this, e); } public void Dispose() diff --git a/Ryujinx/VirtualFs.cs b/Ryujinx/VirtualFs.cs index e5579bcf1..98298053f 100644 --- a/Ryujinx/VirtualFs.cs +++ b/Ryujinx/VirtualFs.cs @@ -37,7 +37,7 @@ namespace Ryujinx public string GetGameSavesPath() => MakeDirAndGetFullPath(SavesPath); - private string MakeDirAndGetFullPath(string Dir) + private static string MakeDirAndGetFullPath(string Dir) { string FullPath = Path.Combine(GetBasePath(), Dir); @@ -49,7 +49,7 @@ namespace Ryujinx return FullPath; } - public string GetBasePath() + public static string GetBasePath() { return Path.Combine(Directory.GetCurrentDirectory(), BasePath); } @@ -61,9 +61,9 @@ namespace Ryujinx protected virtual void Dispose(bool disposing) { - if (disposing && RomFs != null) + if (disposing) { - RomFs.Dispose(); + RomFs?.Dispose(); } } } From 01b753856011540fc7ab247401b6bd49532e8c01 Mon Sep 17 00:00:00 2001 From: Ezekiel Bethel Date: Tue, 20 Feb 2018 11:03:04 +0000 Subject: [PATCH 04/67] Lots of FS HLE fixes and implementation of missing functions/objects. (#24) * Initial pass - fixes IFileSystem OpenFile, implements IFileSystem CreateFile/DeleteFile, fixes IFile Read and implements IFile GetSize/SetSize * Implement IFileSystem Directory* methods, as well as RenameFile. Add IDirectory, and implement its Read and GetEntryCount methods. * missing TODO * hey, this is kinda bad * Update IDirectory.cs Fixed :) * Some cleanups to IDirectory, fix for OpenDirectory on a non-existent directory. * Item -> Index * This should work. * Update IDirectory.cs Marshalling version --- Ryujinx/OsHle/Objects/FspSrv/IDirectory.cs | 133 +++++++++++++++ Ryujinx/OsHle/Objects/FspSrv/IFile.cs | 24 ++- Ryujinx/OsHle/Objects/FspSrv/IFileSystem.cs | 176 +++++++++++++++++++- 3 files changed, 324 insertions(+), 9 deletions(-) create mode 100644 Ryujinx/OsHle/Objects/FspSrv/IDirectory.cs diff --git a/Ryujinx/OsHle/Objects/FspSrv/IDirectory.cs b/Ryujinx/OsHle/Objects/FspSrv/IDirectory.cs new file mode 100644 index 000000000..828674511 --- /dev/null +++ b/Ryujinx/OsHle/Objects/FspSrv/IDirectory.cs @@ -0,0 +1,133 @@ +using ChocolArm64.Memory; +using Ryujinx.OsHle.Ipc; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Ryujinx.OsHle.Objects.FspSrv +{ + [StructLayout(LayoutKind.Sequential, Size = 0x310)] + struct DirectoryEntry + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x300)] + public byte[] Name; + public int Unknown; + public byte Type; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x3)] + public byte[] Padding; + public long Size; + } + + enum DirectoryEntryType + { + Directory, + File + } + + class IDirectory : IIpcInterface + { + private List DirectoryEntries = new List(); + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private string HostPath; + + public IDirectory(string HostPath, int flags) + { + m_Commands = new Dictionary() + { + { 0, Read }, + { 1, GetEntryCount } + }; + + this.HostPath = HostPath; + + if ((flags & 1) == 1) + { + string[] Directories = Directory.GetDirectories(HostPath, "*", SearchOption.TopDirectoryOnly). + Where(x => (new FileInfo(x).Attributes & FileAttributes.Hidden) == 0).ToArray(); + + foreach (string Directory in Directories) + { + DirectoryEntry Info = new DirectoryEntry + { + Name = Encoding.UTF8.GetBytes(Directory), + Type = (byte)DirectoryEntryType.Directory, + Size = 0 + }; + + Array.Resize(ref Info.Name, 0x300); + DirectoryEntries.Add(Info); + } + } + + if ((flags & 2) == 2) + { + string[] Files = Directory.GetFiles(HostPath, "*", SearchOption.TopDirectoryOnly). + Where(x => (new FileInfo(x).Attributes & FileAttributes.Hidden) == 0).ToArray(); + + foreach (string FileName in Files) + { + DirectoryEntry Info = new DirectoryEntry + { + Name = Encoding.UTF8.GetBytes(Path.GetFileName(FileName)), + Type = (byte)DirectoryEntryType.File, + Size = new FileInfo(Path.Combine(HostPath, FileName)).Length + }; + + Array.Resize(ref Info.Name, 0x300); + DirectoryEntries.Add(Info); + } + } + } + + private int LastItem = 0; + public long Read(ServiceCtx Context) + { + long BufferPosition = Context.Request.ReceiveBuff[0].Position; + long BufferLen = Context.Request.ReceiveBuff[0].Size; + long MaxDirectories = BufferLen / Marshal.SizeOf(typeof(DirectoryEntry)); + + if (MaxDirectories > DirectoryEntries.Count - LastItem) + { + MaxDirectories = DirectoryEntries.Count - LastItem; + } + + int CurrentIndex; + for (CurrentIndex = 0; CurrentIndex < MaxDirectories; CurrentIndex++) + { + int CurrentItem = LastItem + CurrentIndex; + + byte[] DirectoryEntry = new byte[Marshal.SizeOf(typeof(DirectoryEntry))]; + IntPtr Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DirectoryEntry))); + Marshal.StructureToPtr(DirectoryEntries[CurrentItem], Ptr, true); + Marshal.Copy(Ptr, DirectoryEntry, 0, Marshal.SizeOf(typeof(DirectoryEntry))); + Marshal.FreeHGlobal(Ptr); + + AMemoryHelper.WriteBytes(Context.Memory, BufferPosition + Marshal.SizeOf(typeof(DirectoryEntry)) * CurrentIndex, DirectoryEntry); + } + + if (LastItem < DirectoryEntries.Count) + { + LastItem += CurrentIndex; + Context.ResponseData.Write((long)CurrentIndex); // index = number of entries written this call. + } + else + { + Context.ResponseData.Write((long)0); + } + + return 0; + } + + public long GetEntryCount(ServiceCtx Context) + { + Context.ResponseData.Write((long)DirectoryEntries.Count); + return 0; + } + } +} diff --git a/Ryujinx/OsHle/Objects/FspSrv/IFile.cs b/Ryujinx/OsHle/Objects/FspSrv/IFile.cs index 1c6cc2e29..2f3899909 100644 --- a/Ryujinx/OsHle/Objects/FspSrv/IFile.cs +++ b/Ryujinx/OsHle/Objects/FspSrv/IFile.cs @@ -19,7 +19,10 @@ namespace Ryujinx.OsHle.Objects.FspSrv m_Commands = new Dictionary() { { 0, Read }, - { 1, Write } + { 1, Write }, + // { 2, Flush }, + { 3, SetSize }, + { 4, GetSize } }; this.BaseStream = BaseStream; @@ -35,14 +38,12 @@ namespace Ryujinx.OsHle.Objects.FspSrv byte[] Data = new byte[Size]; + BaseStream.Seek(Offset, SeekOrigin.Begin); int ReadSize = BaseStream.Read(Data, 0, (int)Size); AMemoryHelper.WriteBytes(Context.Memory, Position, Data); - //TODO: Use ReadSize, we need to return the size that was REALLY read from the file. - //This is a workaround because we are doing something wrong and the game expects to read - //data from a file that doesn't yet exists -- and breaks if it can't read anything. - Context.ResponseData.Write((long)Size); + Context.ResponseData.Write((long)ReadSize); return 0; } @@ -63,6 +64,19 @@ namespace Ryujinx.OsHle.Objects.FspSrv return 0; } + public long GetSize(ServiceCtx Context) + { + Context.ResponseData.Write(BaseStream.Length); + return 0; + } + + public long SetSize(ServiceCtx Context) + { + long Size = Context.RequestData.ReadInt64(); + BaseStream.SetLength(Size); + return 0; + } + public void Dispose() { Dispose(true); diff --git a/Ryujinx/OsHle/Objects/FspSrv/IFileSystem.cs b/Ryujinx/OsHle/Objects/FspSrv/IFileSystem.cs index bf501594f..c3edf2712 100644 --- a/Ryujinx/OsHle/Objects/FspSrv/IFileSystem.cs +++ b/Ryujinx/OsHle/Objects/FspSrv/IFileSystem.cs @@ -17,16 +17,151 @@ namespace Ryujinx.OsHle.Objects.FspSrv public IFileSystem(string Path) { + //TODO: implement. m_Commands = new Dictionary() { + { 0, CreateFile }, + { 1, DeleteFile }, + { 2, CreateDirectory }, + { 3, DeleteDirectory }, + { 4, DeleteDirectoryRecursively }, + { 5, RenameFile }, + { 6, RenameDirectory }, { 7, GetEntryType }, { 8, OpenFile }, - { 10, Commit } + { 9, OpenDirectory }, + { 10, Commit }, + //{ 11, GetFreeSpaceSize }, + //{ 12, GetTotalSpaceSize }, + //{ 13, CleanDirectoryRecursively }, + //{ 14, GetFileTimeStampRaw } }; this.Path = Path; } + public long CreateFile(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + ulong Mode = Context.RequestData.ReadUInt64(); + uint Size = Context.RequestData.ReadUInt32(); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (FileName != null) + { + FileStream NewFile = File.Create(FileName); + NewFile.SetLength(Size); + NewFile.Close(); + return 0; + } + + //TODO: Correct error code. + return -1; + } + + public long DeleteFile(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (FileName != null) + { + File.Delete(FileName); + return 0; + } + + //TODO: Correct error code. + return -1; + } + + public long CreateDirectory(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (FileName != null) + { + Directory.CreateDirectory(FileName); + return 0; + } + + //TODO: Correct error code. + return -1; + } + + public long DeleteDirectory(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (FileName != null) + { + Directory.Delete(FileName); + return 0; + } + + // TODO: Correct error code. + return -1; + } + + public long DeleteDirectoryRecursively(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (FileName != null) + { + Directory.Delete(FileName, true); // recursive = true + return 0; + } + + // TODO: Correct error code. + return -1; + } + + public long RenameFile(ServiceCtx Context) + { + long OldPosition = Context.Request.PtrBuff[0].Position; + long NewPosition = Context.Request.PtrBuff[0].Position; + string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); + string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + string OldFileName = Context.Ns.VFs.GetFullPath(Path, OldName); + string NewFileName = Context.Ns.VFs.GetFullPath(Path, NewName); + + if (OldFileName != null && NewFileName != null) + { + File.Move(OldFileName, NewFileName); + return 0; + } + + // TODO: Correct error code. + return -1; + } + + public long RenameDirectory(ServiceCtx Context) + { + long OldPosition = Context.Request.PtrBuff[0].Position; + long NewPosition = Context.Request.PtrBuff[0].Position; + string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); + string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + string OldDirName = Context.Ns.VFs.GetFullPath(Path, OldName); + string NewDirName = Context.Ns.VFs.GetFullPath(Path, NewName); + + if (OldDirName != null && NewDirName != null) + { + Directory.Move(OldDirName, NewDirName); + return 0; + } + + // TODO: Correct error code. + return -1; + } + public long GetEntryType(ServiceCtx Context) { long Position = Context.Request.PtrBuff[0].Position; @@ -64,11 +199,44 @@ namespace Ryujinx.OsHle.Objects.FspSrv return -1; } - FileStream Stream = new FileStream(FileName, FileMode.OpenOrCreate); + if (File.Exists(FileName)) + { + FileStream Stream = new FileStream(FileName, FileMode.OpenOrCreate); + MakeObject(Context, new IFile(Stream)); - MakeObject(Context, new IFile(Stream)); + return 0; + } - return 0; + //TODO: Correct error code. + return -1; + } + + public long OpenDirectory(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + int FilterFlags = Context.RequestData.ReadInt32(); + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string DirName = Context.Ns.VFs.GetFullPath(Path, Name); + + if(DirName != null) + { + if (Directory.Exists(DirName)) + { + MakeObject(Context, new IDirectory(DirName, FilterFlags)); + return 0; + } + else + { + // TODO: correct error code. + return -1; + } + } + + // TODO: Correct error code. + return -1; } public long Commit(ServiceCtx Context) From b4a1cfde107d6201e549c7493ed5bd794cf2cd62 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 20 Feb 2018 14:39:03 -0300 Subject: [PATCH 05/67] Add SMULL (vector), USHR (scalar), FCCMPE, FNMSUB, fixed a some instructions --- Ryujinx/Cpu/AOpCodeTable.cs | 5 ++ Ryujinx/Cpu/Instruction/AInstEmitAlu.cs | 10 +++ Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs | 19 +++++ Ryujinx/Cpu/Instruction/AInstEmitBfm.cs | 29 ++++--- .../Instruction/AInstEmitSimdArithmetic.cs | 27 ++++++- Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs | 75 +++++++++---------- Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs | 2 +- .../Cpu/Instruction/AInstEmitSimdHelper.cs | 46 ++++++++++-- Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs | 71 ++++++++---------- Ryujinx/Cpu/Instruction/ASoftFallback.cs | 51 +++++-------- 10 files changed, 205 insertions(+), 130 deletions(-) diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index 43a0e63b1..01134ee32 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -47,6 +47,7 @@ namespace ChocolArm64 Set("x1011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csneg, typeof(AOpCodeCsel)); Set("11010101000000110011xxxx10111111", AInstEmit.Dmb, typeof(AOpCodeSystem)); Set("11010101000000110011xxxx10011111", AInstEmit.Dsb, typeof(AOpCodeSystem)); + Set("x1001010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eon, typeof(AOpCodeAluRs)); Set("x10100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm)); Set("x1001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs)); Set("x00100111x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs)); @@ -147,6 +148,7 @@ namespace ChocolArm64 Set("00011110xx1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg)); Set("0x0011100x1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond)); + Set("00011110xx1xxxxxxxxx01xxxxx1xxxx", AInstEmit.Fccmpe_S, typeof(AOpCodeSimdFcond)); Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond)); @@ -183,6 +185,7 @@ namespace ChocolArm64 Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); Set("0x0011111<>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm)); Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg)); Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg)); + Set("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg)); Set("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg)); Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm)); Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm)); @@ -251,6 +255,7 @@ namespace ChocolArm64 Set("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns)); Set("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg)); Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm)); + Set("011111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_S, typeof(AOpCodeSimdShImm)); Set("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm)); Set("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm)); Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg)); diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs index 073a45e7a..72903f5b3 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs @@ -107,6 +107,16 @@ namespace ChocolArm64.Instruction Context.EmitStintzr(Op.Rd); } + public static void Eon(AILEmitterCtx Context) + { + EmitDataLoadOpers(Context); + + Context.Emit(OpCodes.Not); + Context.Emit(OpCodes.Xor); + + EmitDataStore(Context); + } + public static void Eor(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Xor); public static void Extr(AILEmitterCtx Context) diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs b/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs index 57ec25dd0..e848742d0 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs @@ -145,5 +145,24 @@ namespace ChocolArm64.Instruction Context.EmitStint(Op.Rd); } } + + public static void EmitSetNZCV(AILEmitterCtx Context, int NZCV) + { + Context.EmitLdc_I4((NZCV >> 0) & 1); + + Context.EmitStflg((int)APState.VBit); + + Context.EmitLdc_I4((NZCV >> 1) & 1); + + Context.EmitStflg((int)APState.CBit); + + Context.EmitLdc_I4((NZCV >> 2) & 1); + + Context.EmitStflg((int)APState.ZBit); + + Context.EmitLdc_I4((NZCV >> 3) & 1); + + Context.EmitStflg((int)APState.NBit); + } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs b/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs index 4eff013d1..823af7385 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs @@ -36,7 +36,7 @@ namespace ChocolArm64.Instruction if (Op.Pos + 1 == BitsCount) { - EmitBfmShift(Context, OpCodes.Shr); + EmitSbfmShift(Context); } else if (Op.Pos < Op.Shift) { @@ -87,7 +87,7 @@ namespace ChocolArm64.Instruction if (Op.Pos + 1 == Op.GetBitsCount()) { - EmitBfmShift(Context, OpCodes.Shr_Un); + EmitUbfmShift(Context); } else if (Op.Pos < Op.Shift) { @@ -166,19 +166,28 @@ namespace ChocolArm64.Instruction Context.EmitStintzr(Op.Rd); } - private static void EmitBfmShift(AILEmitterCtx Context, OpCode ILOp) + private static void EmitSbfmShift(AILEmitterCtx Context) + { + EmitBfmShift(Context, true); + } + + private static void EmitUbfmShift(AILEmitterCtx Context) + { + EmitBfmShift(Context, false); + } + + private static void EmitBfmShift(AILEmitterCtx Context, bool Signed) { AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp; - if (Op.Shift > 0) - { - Context.EmitLdintzr(Op.Rn); - Context.EmitLdc_I4(Op.Shift); + Context.EmitLdintzr(Op.Rn); + Context.EmitLdc_I4(Op.Shift); - Context.Emit(ILOp); + Context.Emit(Signed + ? OpCodes.Shr + : OpCodes.Shr_Un); - Context.EmitStintzr(Op.Rd); - } + Context.EmitStintzr(Op.Rd); } private static void EmitBfmLsl(AILEmitterCtx Context) diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs index d6ebcc3ff..08991a90e 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs @@ -215,6 +215,24 @@ namespace ChocolArm64.Instruction }); } + public static void Fnmsub_S(AILEmitterCtx Context) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int SizeF = Op.Size & 1; + + EmitVectorExtractF(Context, Op.Rn, 0, SizeF); + EmitVectorExtractF(Context, Op.Rm, 0, SizeF); + + Context.Emit(OpCodes.Mul); + + EmitVectorExtractF(Context, Op.Ra, 0, SizeF); + + Context.Emit(OpCodes.Sub); + + EmitScalarSetF(Context, Op.Rd, SizeF); + } + public static void Frinta_S(AILEmitterCtx Context) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; @@ -282,7 +300,7 @@ namespace ChocolArm64.Instruction public static void Saddw_V(AILEmitterCtx Context) { - EmitVectorWidenBinaryOpSx(Context, () => Context.Emit(OpCodes.Add)); + EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Add)); } public static void Smax_V(AILEmitterCtx Context) @@ -303,6 +321,11 @@ namespace ChocolArm64.Instruction EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo)); } + public static void Smull_V(AILEmitterCtx Context) + { + EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul)); + } + public static void Sub_S(AILEmitterCtx Context) { EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub)); @@ -333,7 +356,7 @@ namespace ChocolArm64.Instruction public static void Uaddw_V(AILEmitterCtx Context) { - EmitVectorWidenBinaryOpZx(Context, () => Context.Emit(OpCodes.Add)); + EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add)); } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs index 92361fbd3..97ccf0ab4 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs @@ -4,6 +4,7 @@ using ChocolArm64.Translation; using System; using System.Reflection.Emit; +using static ChocolArm64.Instruction.AInstEmitAluHelper; using static ChocolArm64.Instruction.AInstEmitSimdHelper; namespace ChocolArm64.Instruction @@ -54,24 +55,9 @@ namespace ChocolArm64.Instruction Context.EmitCondBranch(LblTrue, Op.Cond); - //TODO: Share this logic with Ccmp. - Context.EmitLdc_I4((Op.NZCV >> 0) & 1); + EmitSetNZCV(Context, Op.NZCV); - Context.EmitStflg((int)APState.VBit); - - Context.EmitLdc_I4((Op.NZCV >> 1) & 1); - - Context.EmitStflg((int)APState.CBit); - - Context.EmitLdc_I4((Op.NZCV >> 2) & 1); - - Context.EmitStflg((int)APState.ZBit); - - Context.EmitLdc_I4((Op.NZCV >> 3) & 1); - - Context.EmitStflg((int)APState.NBit); - - Context.Emit(OpCodes.Br_S, LblEnd); + Context.Emit(OpCodes.Br, LblEnd); Context.MarkLabel(LblTrue); @@ -80,12 +66,35 @@ namespace ChocolArm64.Instruction Context.MarkLabel(LblEnd); } + public static void Fccmpe_S(AILEmitterCtx Context) + { + Fccmp_S(Context); + } + public static void Fcmp_S(AILEmitterCtx Context) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false; + //Handle NaN case. If any number is NaN, then NZCV = 0011. + if (CmpWithZero) + { + EmitNaNCheck(Context, Op.Rn); + } + else + { + EmitNaNCheck(Context, Op.Rn); + EmitNaNCheck(Context, Op.Rm); + + Context.Emit(OpCodes.Or); + } + + AILLabel LblNaN = new AILLabel(); + AILLabel LblEnd = new AILLabel(); + + Context.Emit(OpCodes.Brtrue_S, LblNaN); + void EmitLoadOpers() { EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); @@ -102,7 +111,7 @@ namespace ChocolArm64.Instruction //Z = Rn == Rm EmitLoadOpers(); - + Context.Emit(OpCodes.Ceq); Context.Emit(OpCodes.Dup); @@ -123,30 +132,18 @@ namespace ChocolArm64.Instruction Context.EmitStflg((int)APState.NBit); - //Handle NaN case. If any number is NaN, then NZCV = 0011. - AILLabel LblNotNaN = new AILLabel(); + //V = 0 + Context.EmitLdc_I4(0); - if (CmpWithZero) - { - EmitNaNCheck(Context, Op.Rn); - } - else - { - EmitNaNCheck(Context, Op.Rn); - EmitNaNCheck(Context, Op.Rm); - - Context.Emit(OpCodes.Or); - } - - Context.Emit(OpCodes.Brfalse_S, LblNotNaN); - - Context.EmitLdc_I4(1); - Context.EmitLdc_I4(1); - - Context.EmitStflg((int)APState.CBit); Context.EmitStflg((int)APState.VBit); - Context.MarkLabel(LblNotNaN); + Context.Emit(OpCodes.Br_S, LblEnd); + + Context.MarkLabel(LblNaN); + + EmitSetNZCV(Context, 0b0011); + + Context.MarkLabel(LblEnd); } public static void Fcmpe_S(AILEmitterCtx Context) diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs index fbb0dfda5..00c2fe9b5 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs @@ -91,7 +91,7 @@ namespace ChocolArm64.Instruction { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - EmitVectorExtractSx(Context, Op.Rd, 0, Op.Size + 2); + EmitVectorExtractSx(Context, Op.Rn, 0, Op.Size + 2); EmitFloatCast(Context, Op.Size); diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs index 97f288161..20c8be26d 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs @@ -133,7 +133,7 @@ namespace ChocolArm64.Instruction public static void EmitScalarOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed) { - AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; if (Opers.HasFlag(OperFlags.Rd)) { @@ -147,7 +147,7 @@ namespace ChocolArm64.Instruction if (Opers.HasFlag(OperFlags.Rm)) { - EmitVectorExtract(Context, Op.Rm, 0, Op.Size, Signed); + EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, 0, Op.Size, Signed); } Emit(); @@ -383,17 +383,17 @@ namespace ChocolArm64.Instruction } } - public static void EmitVectorWidenBinaryOpSx(AILEmitterCtx Context, Action Emit) + public static void EmitVectorWidenRmBinaryOpSx(AILEmitterCtx Context, Action Emit) { - EmitVectorWidenBinaryOp(Context, Emit, true); + EmitVectorWidenRmBinaryOp(Context, Emit, true); } - public static void EmitVectorWidenBinaryOpZx(AILEmitterCtx Context, Action Emit) + public static void EmitVectorWidenRmBinaryOpZx(AILEmitterCtx Context, Action Emit) { - EmitVectorWidenBinaryOp(Context, Emit, false); + EmitVectorWidenRmBinaryOp(Context, Emit, false); } - public static void EmitVectorWidenBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed) + public static void EmitVectorWidenRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; @@ -415,6 +415,38 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Op.Rd); } + public static void EmitVectorWidenRnRmBinaryOpSx(AILEmitterCtx Context, Action Emit) + { + EmitVectorWidenRnRmBinaryOp(Context, Emit, true); + } + + public static void EmitVectorWidenRnRmBinaryOpZx(AILEmitterCtx Context, Action Emit) + { + EmitVectorWidenRnRmBinaryOp(Context, Emit, false); + } + + public static void EmitVectorWidenRnRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int Elems = 8 >> Op.Size; + + int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; + + for (int Index = 0; Index < Elems; Index++) + { + EmitVectorExtract(Context, Op.Rn, Part + Index, Op.Size, Signed); + EmitVectorExtract(Context, Op.Rm, Part + Index, Op.Size, Signed); + + Emit(); + + EmitVectorInsertTmp(Context, Index, Op.Size + 1); + } + + Context.EmitLdvectmp(); + Context.EmitStvec(Op.Rd); + } + public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size) { EmitVectorZeroAll(Context, Reg); diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs index 165642342..8740ba4d6 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs @@ -10,15 +10,6 @@ namespace ChocolArm64.Instruction { static partial class AInstEmit { - [Flags] - private enum ShrFlags - { - None = 0, - Signed = 1 << 0, - Rounding = 1 << 1, - Accumulate = 1 << 2 - } - public static void Shl_S(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; @@ -100,14 +91,43 @@ namespace ChocolArm64.Instruction EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift); } + public static void Ushr_S(AILEmitterCtx Context) + { + AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + + EmitScalarUnaryOpZx(Context, () => + { + Context.EmitLdc_I4(GetImmShr(Op)); + + Context.Emit(OpCodes.Shr_Un); + }); + } + public static void Ushr_V(AILEmitterCtx Context) { - EmitVectorShr(Context, ShrFlags.None); + AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + + EmitVectorUnaryOpZx(Context, () => + { + Context.EmitLdc_I4(GetImmShr(Op)); + + Context.Emit(OpCodes.Shr_Un); + }); } public static void Usra_V(AILEmitterCtx Context) { - EmitVectorShr(Context, ShrFlags.Accumulate); + AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + + Action Emit = () => + { + Context.EmitLdc_I4(GetImmShr(Op)); + + Context.Emit(OpCodes.Shr_Un); + Context.Emit(OpCodes.Add); + }; + + EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false); } private static void EmitVectorShl(AILEmitterCtx Context, bool Signed) @@ -173,35 +193,6 @@ namespace ChocolArm64.Instruction } } - private static void EmitVectorShr(AILEmitterCtx Context, ShrFlags Flags) - { - AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; - - int Shift = (8 << (Op.Size + 1)) - Op.Imm; - - if (Flags.HasFlag(ShrFlags.Accumulate)) - { - Action Emit = () => - { - Context.EmitLdc_I4(Shift); - - Context.Emit(OpCodes.Shr_Un); - Context.Emit(OpCodes.Add); - }; - - EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false); - } - else - { - EmitVectorUnaryOpZx(Context, () => - { - Context.EmitLdc_I4(Shift); - - Context.Emit(OpCodes.Shr_Un); - }); - } - } - private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm) { EmitVectorShImmBinaryOp(Context, Emit, Imm, true); diff --git a/Ryujinx/Cpu/Instruction/ASoftFallback.cs b/Ryujinx/Cpu/Instruction/ASoftFallback.cs index b70d0b4f4..a57966baf 100644 --- a/Ryujinx/Cpu/Instruction/ASoftFallback.cs +++ b/Ryujinx/Cpu/Instruction/ASoftFallback.cs @@ -1,6 +1,7 @@ using ChocolArm64.State; using ChocolArm64.Translation; using System; +using System.Numerics; using System.Runtime.CompilerServices; namespace ChocolArm64.Instruction @@ -101,6 +102,8 @@ namespace ChocolArm64.Instruction [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SatF32ToS32(float Value) { + if (float.IsNaN(Value)) return 0; + return Value > int.MaxValue ? int.MaxValue : Value < int.MinValue ? int.MinValue : (int)Value; } @@ -108,6 +111,8 @@ namespace ChocolArm64.Instruction [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long SatF32ToS64(float Value) { + if (float.IsNaN(Value)) return 0; + return Value > long.MaxValue ? long.MaxValue : Value < long.MinValue ? long.MinValue : (long)Value; } @@ -115,6 +120,8 @@ namespace ChocolArm64.Instruction [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint SatF32ToU32(float Value) { + if (float.IsNaN(Value)) return 0; + return Value > uint.MaxValue ? uint.MaxValue : Value < uint.MinValue ? uint.MinValue : (uint)Value; } @@ -122,6 +129,8 @@ namespace ChocolArm64.Instruction [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong SatF32ToU64(float Value) { + if (float.IsNaN(Value)) return 0; + return Value > ulong.MaxValue ? ulong.MaxValue : Value < ulong.MinValue ? ulong.MinValue : (ulong)Value; } @@ -129,6 +138,8 @@ namespace ChocolArm64.Instruction [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SatF64ToS32(double Value) { + if (double.IsNaN(Value)) return 0; + return Value > int.MaxValue ? int.MaxValue : Value < int.MinValue ? int.MinValue : (int)Value; } @@ -136,6 +147,8 @@ namespace ChocolArm64.Instruction [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long SatF64ToS64(double Value) { + if (double.IsNaN(Value)) return 0; + return Value > long.MaxValue ? long.MaxValue : Value < long.MinValue ? long.MinValue : (long)Value; } @@ -143,6 +156,8 @@ namespace ChocolArm64.Instruction [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint SatF64ToU32(double Value) { + if (double.IsNaN(Value)) return 0; + return Value > uint.MaxValue ? uint.MaxValue : Value < uint.MinValue ? uint.MinValue : (uint)Value; } @@ -150,46 +165,20 @@ namespace ChocolArm64.Instruction [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong SatF64ToU64(double Value) { + if (double.IsNaN(Value)) return 0; + return Value > ulong.MaxValue ? ulong.MaxValue : Value < ulong.MinValue ? ulong.MinValue : (ulong)Value; } - public static ulong SMulHi128(ulong LHS, ulong RHS) + public static long SMulHi128(long LHS, long RHS) { - long LLo = (uint)(LHS >> 0); - long LHi = (int)(LHS >> 32); - long RLo = (uint)(RHS >> 0); - long RHi = (int)(RHS >> 32); - - long LHiRHi = LHi * RHi; - long LHiRLo = LHi * RLo; - long LLoRHi = LLo * RHi; - long LLoRLo = LLo * RLo; - - long Carry = ((uint)LHiRLo + ((uint)LLoRHi + (LLoRLo >> 32))) >> 32; - - long ResHi = LHiRHi + (LHiRLo >> 32) + (LLoRHi >> 32) + Carry; - - return (ulong)ResHi; + return (long)(BigInteger.Multiply(LHS, RHS) >> 64); } public static ulong UMulHi128(ulong LHS, ulong RHS) { - ulong LLo = (uint)(LHS >> 0); - ulong LHi = (uint)(LHS >> 32); - ulong RLo = (uint)(RHS >> 0); - ulong RHi = (uint)(RHS >> 32); - - ulong LHiRHi = LHi * RHi; - ulong LHiRLo = LHi * RLo; - ulong LLoRHi = LLo * RHi; - ulong LLoRLo = LLo * RLo; - - ulong Carry = ((uint)LHiRLo + ((uint)LLoRHi + (LLoRLo >> 32))) >> 32; - - ulong ResHi = LHiRHi + (LHiRLo >> 32) + (LLoRHi >> 32) + Carry; - - return ResHi; + return (ulong)(BigInteger.Multiply(LHS, RHS) >> 64); } public static int CountSetBits8(byte Value) From cb665bb715834526d73c9469d16114b287faaecd Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 20 Feb 2018 16:04:22 -0300 Subject: [PATCH 06/67] Add FDIV (vector) instruction --- Ryujinx/Cpu/AOpCodeTable.cs | 13 +++++++------ Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs | 5 +++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/Ryujinx/Cpu/AOpCodeTable.cs index 01134ee32..ff2796b81 100644 --- a/Ryujinx/Cpu/AOpCodeTable.cs +++ b/Ryujinx/Cpu/AOpCodeTable.cs @@ -146,7 +146,7 @@ namespace ChocolArm64 Set("0x101110001xxxxx000111xxxxxxxxxx", AInstEmit.Eor_V, typeof(AOpCodeSimdReg)); Set("00011110xx100000110000xxxxxxxxxx", AInstEmit.Fabs_S, typeof(AOpCodeSimd)); Set("00011110xx1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg)); - Set("0x0011100x1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg)); + Set("0>0011100<1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond)); Set("00011110xx1xxxxxxxxx01xxxxx1xxxx", AInstEmit.Fccmpe_S, typeof(AOpCodeSimdFcond)); Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg)); @@ -159,19 +159,20 @@ namespace ChocolArm64 Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt)); Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt)); Set("x0011110xx011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Gp_Fix, typeof(AOpCodeSimdCvt)); - Set("0x0011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd)); + Set("0>0011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd)); Set("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimdShImm)); Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_Gp, typeof(AOpCodeSimdCvt)); Set("x0011110xx011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Gp_Fix, typeof(AOpCodeSimdCvt)); - Set("0x1011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd)); + Set("0>1011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd)); Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimdShImm)); Set("00011110xx1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg)); + Set("0>1011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Fdiv_V, typeof(AOpCodeSimdReg)); Set("00011111xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg)); - Set("0x0011100x1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg)); + Set("0>0011100<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg)); Set("0x0011111<1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); Set("0x0011111<0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg)); Set("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns)); Set("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns)); Set("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs)); diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs index 08991a90e..21ec11a7e 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs @@ -124,6 +124,11 @@ namespace ChocolArm64.Instruction EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Div)); } + public static void Fdiv_V(AILEmitterCtx Context) + { + EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Div)); + } + public static void Fmadd_S(AILEmitterCtx Context) { EmitScalarTernaryRaOpF(Context, () => From 62b827f474f0aa2152dd339fcc7cf31084e16a0b Mon Sep 17 00:00:00 2001 From: emmauss Date: Tue, 20 Feb 2018 22:09:23 +0200 Subject: [PATCH 07/67] Split main project into core,graphics and chocolarm4 subproject (#29) --- {Ryujinx/Cpu => ChocolArm64}/ABitUtils.cs | 0 {Ryujinx/Cpu => ChocolArm64}/AOpCodeTable.cs | 0 .../Cpu => ChocolArm64}/AOptimizations.cs | 0 {Ryujinx/Cpu => ChocolArm64}/AThread.cs | 0 .../Cpu => ChocolArm64}/ATranslatedSub.cs | 0 {Ryujinx/Cpu => ChocolArm64}/ATranslator.cs | 0 ChocolArm64/ChocolArm64.csproj | 15 ++++++ .../Cpu => ChocolArm64}/Decoder/ABlock.cs | 0 {Ryujinx/Cpu => ChocolArm64}/Decoder/ACond.cs | 0 .../Cpu => ChocolArm64}/Decoder/ADataOp.cs | 0 .../Cpu => ChocolArm64}/Decoder/ADecoder.cs | 0 .../Decoder/ADecoderHelper.cs | 0 .../Cpu => ChocolArm64}/Decoder/AIntType.cs | 0 .../Cpu => ChocolArm64}/Decoder/AOpCode.cs | 0 .../Cpu => ChocolArm64}/Decoder/AOpCodeAdr.cs | 0 .../Cpu => ChocolArm64}/Decoder/AOpCodeAlu.cs | 0 .../Decoder/AOpCodeAluImm.cs | 0 .../Decoder/AOpCodeAluRs.cs | 0 .../Decoder/AOpCodeAluRx.cs | 0 .../Decoder/AOpCodeBImm.cs | 0 .../Decoder/AOpCodeBImmAl.cs | 0 .../Decoder/AOpCodeBImmCmp.cs | 0 .../Decoder/AOpCodeBImmCond.cs | 0 .../Decoder/AOpCodeBImmTest.cs | 0 .../Decoder/AOpCodeBReg.cs | 0 .../Cpu => ChocolArm64}/Decoder/AOpCodeBfm.cs | 0 .../Decoder/AOpCodeCcmp.cs | 0 .../Decoder/AOpCodeCcmpImm.cs | 0 .../Decoder/AOpCodeCcmpReg.cs | 0 .../Decoder/AOpCodeCsel.cs | 0 .../Decoder/AOpCodeException.cs | 0 .../Cpu => ChocolArm64}/Decoder/AOpCodeMem.cs | 0 .../Decoder/AOpCodeMemEx.cs | 0 .../Decoder/AOpCodeMemImm.cs | 0 .../Decoder/AOpCodeMemLit.cs | 0 .../Decoder/AOpCodeMemPair.cs | 0 .../Decoder/AOpCodeMemReg.cs | 0 .../Cpu => ChocolArm64}/Decoder/AOpCodeMov.cs | 0 .../Cpu => ChocolArm64}/Decoder/AOpCodeMul.cs | 0 .../Decoder/AOpCodeSimd.cs | 0 .../Decoder/AOpCodeSimdCvt.cs | 0 .../Decoder/AOpCodeSimdFcond.cs | 0 .../Decoder/AOpCodeSimdFmov.cs | 0 .../Decoder/AOpCodeSimdImm.cs | 0 .../Decoder/AOpCodeSimdIns.cs | 0 .../Decoder/AOpCodeSimdMemImm.cs | 0 .../Decoder/AOpCodeSimdMemLit.cs | 0 .../Decoder/AOpCodeSimdMemMs.cs | 0 .../Decoder/AOpCodeSimdMemPair.cs | 0 .../Decoder/AOpCodeSimdMemReg.cs | 0 .../Decoder/AOpCodeSimdMemSs.cs | 0 .../Decoder/AOpCodeSimdReg.cs | 0 .../Decoder/AOpCodeSimdRegElem.cs | 0 .../Decoder/AOpCodeSimdShImm.cs | 0 .../Decoder/AOpCodeSimdTbl.cs | 0 .../Decoder/AOpCodeSystem.cs | 0 .../Cpu => ChocolArm64}/Decoder/AShiftType.cs | 0 .../Cpu => ChocolArm64}/Decoder/IAOpCode.cs | 0 .../Decoder/IAOpCodeAlu.cs | 0 .../Decoder/IAOpCodeAluImm.cs | 0 .../Decoder/IAOpCodeAluRs.cs | 0 .../Decoder/IAOpCodeAluRx.cs | 0 .../Decoder/IAOpCodeCond.cs | 0 .../Decoder/IAOpCodeLit.cs | 0 .../Decoder/IAOpCodeSimd.cs | 0 .../Exceptions/VmmAccessViolationException.cs | 0 .../Exceptions/VmmOutOfMemoryException.cs | 0 .../Exceptions/VmmPageFaultException.cs | 0 .../Cpu => ChocolArm64}/Instruction/AInst.cs | 0 .../Instruction/AInstEmitAlu.cs | 0 .../Instruction/AInstEmitAluHelper.cs | 0 .../Instruction/AInstEmitBfm.cs | 0 .../Instruction/AInstEmitCcmp.cs | 0 .../Instruction/AInstEmitCsel.cs | 0 .../Instruction/AInstEmitException.cs | 0 .../Instruction/AInstEmitFlow.cs | 0 .../Instruction/AInstEmitMemory.cs | 0 .../Instruction/AInstEmitMemoryEx.cs | 0 .../Instruction/AInstEmitMemoryHelper.cs | 0 .../Instruction/AInstEmitMove.cs | 0 .../Instruction/AInstEmitMul.cs | 0 .../Instruction/AInstEmitSimdArithmetic.cs | 0 .../Instruction/AInstEmitSimdCmp.cs | 0 .../Instruction/AInstEmitSimdCvt.cs | 0 .../Instruction/AInstEmitSimdHelper.cs | 0 .../Instruction/AInstEmitSimdLogical.cs | 0 .../Instruction/AInstEmitSimdMemory.cs | 0 .../Instruction/AInstEmitSimdMove.cs | 0 .../Instruction/AInstEmitSimdShift.cs | 0 .../Instruction/AInstEmitSystem.cs | 0 .../Instruction/AInstEmitter.cs | 0 .../Instruction/ASoftFallback.cs | 0 .../Cpu => ChocolArm64}/Memory/AMemory.cs | 0 .../Memory/AMemoryAlloc.cs | 0 .../Memory/AMemoryHelper.cs | 0 .../Memory/AMemoryMapInfo.cs | 0 .../Cpu => ChocolArm64}/Memory/AMemoryMgr.cs | 0 .../Cpu => ChocolArm64}/Memory/AMemoryPerm.cs | 0 .../State/AInstExceptEventArgs.cs | 0 .../State/AInstUndEventArgs.cs | 0 {Ryujinx/Cpu => ChocolArm64}/State/APState.cs | 0 .../Cpu => ChocolArm64}/State/ARegister.cs | 0 .../State/ARegisterSize.cs | 0 .../State/ARegisterType.cs | 0 .../Cpu => ChocolArm64}/State/AThreadState.cs | 0 {Ryujinx/Cpu => ChocolArm64}/State/AVec.cs | 0 .../Translation/AILBlock.cs | 0 .../Translation/AILEmitter.cs | 0 .../Translation/AILEmitterCtx.cs | 0 .../Translation/AILLabel.cs | 0 .../Translation/AILOpCode.cs | 0 .../Translation/AILOpCodeBranch.cs | 0 .../Translation/AILOpCodeCall.cs | 0 .../Translation/AILOpCodeConst.cs | 0 .../Translation/AILOpCodeLoad.cs | 0 .../Translation/AILOpCodeLog.cs | 0 .../Translation/AILOpCodeStore.cs | 0 .../Translation/AIoType.cs | 0 .../Translation/ALocalAlloc.cs | 0 .../Translation/IAILEmit.cs | 0 .../Translation/ILGeneratorEx.cs | 0 {Ryujinx => Ryujinx.Core}/Config.cs | 2 +- {Ryujinx => Ryujinx.Core}/Hid.cs | 4 +- .../Hid/HidController.cs | 2 +- {Ryujinx => Ryujinx.Core}/Hid/HidKeyboard.cs | 2 +- {Ryujinx => Ryujinx.Core}/Hid/HidMouse.cs | 2 +- .../Hid/HidTouchScreen.cs | 2 +- {Ryujinx => Ryujinx.Core}/Hid/HidUnknown.cs | 2 +- {Ryujinx => Ryujinx.Core}/Hid/JoyCon.cs | 0 .../Loaders/Compression/Lz4.cs | 2 +- {Ryujinx => Ryujinx.Core}/Loaders/ElfDyn.cs | 2 +- .../Loaders/ElfDynTag.cs | 2 +- {Ryujinx => Ryujinx.Core}/Loaders/ElfRel.cs | 2 +- .../Loaders/ElfRelType.cs | 2 +- {Ryujinx => Ryujinx.Core}/Loaders/ElfSym.cs | 2 +- .../Loaders/ElfSymBinding.cs | 2 +- .../Loaders/ElfSymType.cs | 2 +- .../Loaders/ElfSymVisibility.cs | 2 +- .../Loaders/Executable.cs | 6 +-- .../Loaders/Executables/IExecutable.cs | 4 +- .../Loaders/Executables/Nro.cs | 2 +- .../Loaders/Executables/Nso.cs | 4 +- {Ryujinx => Ryujinx.Core}/Logging.cs | 2 +- {Ryujinx => Ryujinx.Core}/OsHle/CondVar.cs | 6 +-- {Ryujinx => Ryujinx.Core}/OsHle/Display.cs | 2 +- .../GuestBrokeExecutionException.cs | 2 +- .../UndefinedInstructionException.cs | 2 +- {Ryujinx => Ryujinx.Core}/OsHle/FileDesc.cs | 2 +- .../OsHle/Handles/HDomain.cs | 4 +- Ryujinx.Core/OsHle/Handles/HEvent.cs | 7 +++ .../OsHle/Handles/HNvMap.cs | 2 +- .../OsHle/Handles/HSession.cs | 2 +- .../OsHle/Handles/HSessionObj.cs | 2 +- .../OsHle/Handles/HSharedMem.cs | 2 +- .../OsHle/Handles/HThread.cs | 4 +- .../OsHle/Handles/HTransferMem.cs | 2 +- .../OsHle/Handles/KProcessScheduler.cs | 4 +- {Ryujinx => Ryujinx.Core}/OsHle/Horizon.cs | 12 ++--- .../OsHle/Ipc/IpcBuffDesc.cs | 2 +- .../OsHle/Ipc/IpcDomCmd.cs | 2 +- .../OsHle/Ipc/IpcHandleDesc.cs | 2 +- .../OsHle/Ipc/IpcHandler.cs | 8 +-- .../OsHle/Ipc/IpcMessage.cs | 2 +- .../OsHle/Ipc/IpcMessageType.cs | 2 +- .../OsHle/Ipc/IpcPtrBuffDesc.cs | 2 +- .../OsHle/Ipc/IpcRecvListBuffDesc.cs | 2 +- .../OsHle/Ipc/ServiceProcessRequest.cs | 2 +- {Ryujinx => Ryujinx.Core}/OsHle/MemoryInfo.cs | 2 +- {Ryujinx => Ryujinx.Core}/OsHle/MemoryType.cs | 2 +- {Ryujinx => Ryujinx.Core}/OsHle/Mutex.cs | 6 +-- .../Objects/Acc/IManagerForApplication.cs | 4 +- .../OsHle/Objects/Acc/IProfile.cs | 4 +- .../OsHle/Objects/Am/IApplicationFunctions.cs | 6 +-- .../OsHle/Objects/Am/IApplicationProxy.cs | 6 +-- .../OsHle/Objects/Am/IAudioController.cs | 4 +- .../OsHle/Objects/Am/ICommonStateGetter.cs | 4 +- .../OsHle/Objects/Am/IDebugFunctions.cs | 4 +- .../OsHle/Objects/Am/IDisplayController.cs | 4 +- .../OsHle/Objects/Am/ILibraryAppletCreator.cs | 4 +- .../Objects/Am/IParentalControlService.cs | 4 +- .../OsHle/Objects/Am/ISelfController.cs | 4 +- .../OsHle/Objects/Am/IStorage.cs | 6 +-- .../OsHle/Objects/Am/IStorageAccessor.cs | 4 +- .../OsHle/Objects/Am/IWindowController.cs | 4 +- .../OsHle/Objects/Apm/ISession.cs | 4 +- .../OsHle/Objects/Aud/IAudioOut.cs | 6 +-- .../OsHle/Objects/Aud/IAudioRenderer.cs | 6 +-- .../OsHle/Objects/Friend/IFriendService.cs | 4 +- .../OsHle/Objects/FspSrv/IDirectory.cs | 4 +- .../OsHle/Objects/FspSrv/IFile.cs | 4 +- .../OsHle/Objects/FspSrv/IFileSystem.cs | 6 +-- .../OsHle/Objects/FspSrv/IStorage.cs | 4 +- .../OsHle/Objects/Hid/IAppletResource.cs | 6 +-- .../OsHle/Objects/IIpcInterface.cs | 4 +- .../OsHle/Objects/ObjHelper.cs | 6 +-- .../OsHle/Objects/Parcel.cs | 2 +- .../OsHle/Objects/Time/ISteadyClock.cs | 4 +- .../OsHle/Objects/Time/ISystemClock.cs | 4 +- .../OsHle/Objects/Time/ITimeZoneService.cs | 4 +- .../OsHle/Objects/Time/SystemClockType.cs | 2 +- .../Objects/Vi/IApplicationDisplayService.cs | 10 ++-- .../OsHle/Objects/Vi/IHOSBinderDriver.cs | 10 ++-- .../Objects/Vi/IManagerDisplayService.cs | 4 +- .../OsHle/Objects/Vi/ISystemDisplayService.cs | 4 +- {Ryujinx => Ryujinx.Core}/OsHle/Process.cs | 14 ++--- {Ryujinx => Ryujinx.Core}/OsHle/ServiceCtx.cs | 6 +-- .../OsHle/Services/ServiceAcc.cs | 6 +-- .../OsHle/Services/ServiceApm.cs | 6 +-- .../OsHle/Services/ServiceAppletOE.cs | 6 +-- .../OsHle/Services/ServiceAud.cs | 6 +-- .../OsHle/Services/ServiceFriend.cs | 6 +-- .../OsHle/Services/ServiceFspSrv.cs | 6 +-- .../OsHle/Services/ServiceHid.cs | 8 +-- .../OsHle/Services/ServiceLm.cs | 2 +- .../OsHle/Services/ServiceNvDrv.cs | 22 ++++---- .../OsHle/Services/ServicePctl.cs | 6 +-- .../OsHle/Services/ServicePl.cs | 4 +- .../OsHle/Services/ServiceSet.cs | 2 +- .../OsHle/Services/ServiceSm.cs | 6 +-- .../OsHle/Services/ServiceTime.cs | 6 +-- .../OsHle/Services/ServiceVi.cs | 6 +-- .../OsHle/Svc/SvcHandler.cs | 2 +- .../OsHle/Svc/SvcMemory.cs | 4 +- .../OsHle/Svc/SvcResult.cs | 2 +- .../OsHle/Svc/SvcSystem.cs | 8 +-- .../OsHle/Svc/SvcThread.cs | 4 +- .../OsHle/Svc/SvcThreadSync.cs | 4 +- .../OsHle/Utilities/IdPool.cs | 2 +- .../OsHle/Utilities/IdPoolWithObj.cs | 2 +- .../OsHle/Utilities/MemReader.cs | 2 +- .../OsHle/Utilities/MemWriter.cs | 2 +- Ryujinx.Core/Ryujinx.Core.csproj | 20 +++++++ {Ryujinx => Ryujinx.Core}/Switch.cs | 32 +++++++++-- {Ryujinx => Ryujinx.Core}/VirtualFs.cs | 2 +- .../Gal/GalPrimitiveType.cs | 2 +- .../Gal/GalVertexAttrib.cs | 2 +- .../Gal/GalVertexAttribSize.cs | 2 +- .../Gal/GalVertexAttribType.cs | 2 +- .../Gal/IGalRenderer.cs | 2 +- .../Gal/OpenGL/OpenGLRenderer.cs | 2 +- {Ryujinx => Ryujinx.Graphics}/Gpu/BCn.cs | 2 +- Ryujinx.Graphics/Gpu/NsGpu.cs | 53 +++++++++++++++++++ .../Gpu/NsGpuEngine.cs | 2 +- .../Gpu/NsGpuMemoryMgr.cs | 2 +- .../Gpu/NsGpuPBEntry.cs | 4 +- .../Gpu/NsGpuPGraph.cs | 4 +- .../Gpu/NsGpuRegister.cs | 4 +- .../Gpu/NsGpuTexture.cs | 2 +- .../Gpu/NsGpuTextureFormat.cs | 2 +- .../Gpu/SwizzleAddr.cs | 2 +- Ryujinx.Graphics/Ryujinx.Graphics.csproj | 15 ++++++ Ryujinx.sln | 24 +++++++-- Ryujinx/Gpu/NsGpu.cs | 22 -------- Ryujinx/OsHle/Handles/HEvent.cs | 7 --- Ryujinx/Ryujinx.csproj | 5 ++ Ryujinx/Ui/GLScreen.cs | 5 +- Ryujinx/Ui/Program.cs | 13 ++--- 257 files changed, 415 insertions(+), 285 deletions(-) rename {Ryujinx/Cpu => ChocolArm64}/ABitUtils.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/AOpCodeTable.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/AOptimizations.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/AThread.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/ATranslatedSub.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/ATranslator.cs (100%) create mode 100644 ChocolArm64/ChocolArm64.csproj rename {Ryujinx/Cpu => ChocolArm64}/Decoder/ABlock.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/ACond.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/ADataOp.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/ADecoder.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/ADecoderHelper.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AIntType.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCode.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeAdr.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeAlu.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeAluImm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeAluRs.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeAluRx.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeBImm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeBImmAl.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeBImmCmp.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeBImmCond.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeBImmTest.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeBReg.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeBfm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeCcmp.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeCcmpImm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeCcmpReg.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeCsel.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeException.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeMem.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeMemEx.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeMemImm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeMemLit.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeMemPair.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeMemReg.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeMov.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeMul.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimd.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdCvt.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdFcond.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdFmov.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdImm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdIns.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdMemImm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdMemLit.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdMemMs.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdMemPair.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdMemReg.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdMemSs.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdReg.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdRegElem.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdShImm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSimdTbl.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AOpCodeSystem.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/AShiftType.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/IAOpCode.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/IAOpCodeAlu.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/IAOpCodeAluImm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/IAOpCodeAluRs.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/IAOpCodeAluRx.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/IAOpCodeCond.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/IAOpCodeLit.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Decoder/IAOpCodeSimd.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Exceptions/VmmAccessViolationException.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Exceptions/VmmOutOfMemoryException.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Exceptions/VmmPageFaultException.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInst.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitAlu.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitAluHelper.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitBfm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitCcmp.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitCsel.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitException.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitFlow.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitMemory.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitMemoryEx.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitMemoryHelper.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitMove.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitMul.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSimdArithmetic.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSimdCmp.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSimdCvt.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSimdHelper.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSimdLogical.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSimdMemory.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSimdMove.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSimdShift.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitSystem.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/AInstEmitter.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Instruction/ASoftFallback.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Memory/AMemory.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Memory/AMemoryAlloc.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Memory/AMemoryHelper.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Memory/AMemoryMapInfo.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Memory/AMemoryMgr.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Memory/AMemoryPerm.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/State/AInstExceptEventArgs.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/State/AInstUndEventArgs.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/State/APState.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/State/ARegister.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/State/ARegisterSize.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/State/ARegisterType.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/State/AThreadState.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/State/AVec.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILBlock.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILEmitter.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILEmitterCtx.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILLabel.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILOpCode.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILOpCodeBranch.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILOpCodeCall.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILOpCodeConst.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILOpCodeLoad.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILOpCodeLog.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AILOpCodeStore.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/AIoType.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/ALocalAlloc.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/IAILEmit.cs (100%) rename {Ryujinx/Cpu => ChocolArm64}/Translation/ILGeneratorEx.cs (100%) rename {Ryujinx => Ryujinx.Core}/Config.cs (99%) rename {Ryujinx => Ryujinx.Core}/Hid.cs (99%) rename {Ryujinx => Ryujinx.Core}/Hid/HidController.cs (99%) rename {Ryujinx => Ryujinx.Core}/Hid/HidKeyboard.cs (97%) rename {Ryujinx => Ryujinx.Core}/Hid/HidMouse.cs (97%) rename {Ryujinx => Ryujinx.Core}/Hid/HidTouchScreen.cs (98%) rename {Ryujinx => Ryujinx.Core}/Hid/HidUnknown.cs (98%) rename {Ryujinx => Ryujinx.Core}/Hid/JoyCon.cs (100%) rename {Ryujinx => Ryujinx.Core}/Loaders/Compression/Lz4.cs (97%) rename {Ryujinx => Ryujinx.Core}/Loaders/ElfDyn.cs (89%) rename {Ryujinx => Ryujinx.Core}/Loaders/ElfDynTag.cs (98%) rename {Ryujinx => Ryujinx.Core}/Loaders/ElfRel.cs (93%) rename {Ryujinx => Ryujinx.Core}/Loaders/ElfRelType.cs (99%) rename {Ryujinx => Ryujinx.Core}/Loaders/ElfSym.cs (97%) rename {Ryujinx => Ryujinx.Core}/Loaders/ElfSymBinding.cs (77%) rename {Ryujinx => Ryujinx.Core}/Loaders/ElfSymType.cs (87%) rename {Ryujinx => Ryujinx.Core}/Loaders/ElfSymVisibility.cs (82%) rename {Ryujinx => Ryujinx.Core}/Loaders/Executable.cs (98%) rename {Ryujinx => Ryujinx.Core}/Loaders/Executables/IExecutable.cs (82%) rename {Ryujinx => Ryujinx.Core}/Loaders/Executables/Nro.cs (97%) rename {Ryujinx => Ryujinx.Core}/Loaders/Executables/Nso.cs (97%) rename {Ryujinx => Ryujinx.Core}/Logging.cs (99%) rename {Ryujinx => Ryujinx.Core}/OsHle/CondVar.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Display.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Exceptions/GuestBrokeExecutionException.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Exceptions/UndefinedInstructionException.cs (90%) rename {Ryujinx => Ryujinx.Core}/OsHle/FileDesc.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Handles/HDomain.cs (94%) create mode 100644 Ryujinx.Core/OsHle/Handles/HEvent.cs rename {Ryujinx => Ryujinx.Core}/OsHle/Handles/HNvMap.cs (91%) rename {Ryujinx => Ryujinx.Core}/OsHle/Handles/HSession.cs (93%) rename {Ryujinx => Ryujinx.Core}/OsHle/Handles/HSessionObj.cs (94%) rename {Ryujinx => Ryujinx.Core}/OsHle/Handles/HSharedMem.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Handles/HThread.cs (88%) rename {Ryujinx => Ryujinx.Core}/OsHle/Handles/HTransferMem.cs (93%) rename {Ryujinx => Ryujinx.Core}/OsHle/Handles/KProcessScheduler.cs (99%) rename {Ryujinx => Ryujinx.Core}/OsHle/Horizon.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/IpcBuffDesc.cs (95%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/IpcDomCmd.cs (70%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/IpcHandleDesc.cs (98%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/IpcHandler.cs (98%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/IpcMessage.cs (99%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/IpcMessageType.cs (79%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/IpcPtrBuffDesc.cs (95%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/IpcRecvListBuffDesc.cs (92%) rename {Ryujinx => Ryujinx.Core}/OsHle/Ipc/ServiceProcessRequest.cs (65%) rename {Ryujinx => Ryujinx.Core}/OsHle/MemoryInfo.cs (96%) rename {Ryujinx => Ryujinx.Core}/OsHle/MemoryType.cs (96%) rename {Ryujinx => Ryujinx.Core}/OsHle/Mutex.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Acc/IManagerForApplication.cs (91%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Acc/IProfile.cs (92%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IApplicationFunctions.cs (94%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IApplicationProxy.cs (94%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IAudioController.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/ICommonStateGetter.cs (96%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IDebugFunctions.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IDisplayController.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/ILibraryAppletCreator.cs (86%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IParentalControlService.cs (86%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/ISelfController.cs (95%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IStorage.cs (84%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IStorageAccessor.cs (95%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Am/IWindowController.cs (91%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Apm/ISession.cs (90%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Aud/IAudioOut.cs (98%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Aud/IAudioRenderer.cs (95%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Friend/IFriendService.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/FspSrv/IDirectory.cs (98%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/FspSrv/IFile.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/FspSrv/IFileSystem.cs (98%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/FspSrv/IStorage.cs (94%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Hid/IAppletResource.cs (87%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/IIpcInterface.cs (69%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/ObjHelper.cs (84%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Parcel.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Time/ISteadyClock.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Time/ISystemClock.cs (93%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Time/ITimeZoneService.cs (85%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Time/SystemClockType.cs (66%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Vi/IApplicationDisplayService.cs (96%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Vi/IHOSBinderDriver.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Vi/IManagerDisplayService.cs (91%) rename {Ryujinx => Ryujinx.Core}/OsHle/Objects/Vi/ISystemDisplayService.cs (88%) rename {Ryujinx => Ryujinx.Core}/OsHle/Process.cs (96%) rename {Ryujinx => Ryujinx.Core}/OsHle/ServiceCtx.cs (92%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceAcc.cs (83%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceApm.cs (61%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceAppletOE.cs (64%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceAud.cs (94%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceFriend.cs (62%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceFspSrv.cs (89%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceHid.cs (89%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceLm.cs (83%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceNvDrv.cs (96%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServicePctl.cs (63%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServicePl.cs (91%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceSet.cs (95%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceSm.cs (91%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceTime.cs (88%) rename {Ryujinx => Ryujinx.Core}/OsHle/Services/ServiceVi.cs (69%) rename {Ryujinx => Ryujinx.Core}/OsHle/Svc/SvcHandler.cs (98%) rename {Ryujinx => Ryujinx.Core}/OsHle/Svc/SvcMemory.cs (98%) rename {Ryujinx => Ryujinx.Core}/OsHle/Svc/SvcResult.cs (84%) rename {Ryujinx => Ryujinx.Core}/OsHle/Svc/SvcSystem.cs (98%) rename {Ryujinx => Ryujinx.Core}/OsHle/Svc/SvcThread.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Svc/SvcThreadSync.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Utilities/IdPool.cs (96%) rename {Ryujinx => Ryujinx.Core}/OsHle/Utilities/IdPoolWithObj.cs (97%) rename {Ryujinx => Ryujinx.Core}/OsHle/Utilities/MemReader.cs (95%) rename {Ryujinx => Ryujinx.Core}/OsHle/Utilities/MemWriter.cs (94%) create mode 100644 Ryujinx.Core/Ryujinx.Core.csproj rename {Ryujinx => Ryujinx.Core}/Switch.cs (54%) rename {Ryujinx => Ryujinx.Core}/VirtualFs.cs (98%) rename {Ryujinx => Ryujinx.Graphics}/Gal/GalPrimitiveType.cs (95%) rename {Ryujinx => Ryujinx.Graphics}/Gal/GalVertexAttrib.cs (96%) rename {Ryujinx => Ryujinx.Graphics}/Gal/GalVertexAttribSize.cs (93%) rename {Ryujinx => Ryujinx.Graphics}/Gal/GalVertexAttribType.cs (86%) rename {Ryujinx => Ryujinx.Graphics}/Gal/IGalRenderer.cs (93%) rename {Ryujinx => Ryujinx.Graphics}/Gal/OpenGL/OpenGLRenderer.cs (99%) rename {Ryujinx => Ryujinx.Graphics}/Gpu/BCn.cs (99%) create mode 100644 Ryujinx.Graphics/Gpu/NsGpu.cs rename {Ryujinx => Ryujinx.Graphics}/Gpu/NsGpuEngine.cs (87%) rename {Ryujinx => Ryujinx.Graphics}/Gpu/NsGpuMemoryMgr.cs (99%) rename {Ryujinx => Ryujinx.Graphics}/Gpu/NsGpuPBEntry.cs (97%) rename {Ryujinx => Ryujinx.Graphics}/Gpu/NsGpuPGraph.cs (99%) rename {Ryujinx => Ryujinx.Graphics}/Gpu/NsGpuRegister.cs (98%) rename {Ryujinx => Ryujinx.Graphics}/Gpu/NsGpuTexture.cs (79%) rename {Ryujinx => Ryujinx.Graphics}/Gpu/NsGpuTextureFormat.cs (76%) rename {Ryujinx => Ryujinx.Graphics}/Gpu/SwizzleAddr.cs (99%) create mode 100644 Ryujinx.Graphics/Ryujinx.Graphics.csproj delete mode 100644 Ryujinx/Gpu/NsGpu.cs delete mode 100644 Ryujinx/OsHle/Handles/HEvent.cs diff --git a/Ryujinx/Cpu/ABitUtils.cs b/ChocolArm64/ABitUtils.cs similarity index 100% rename from Ryujinx/Cpu/ABitUtils.cs rename to ChocolArm64/ABitUtils.cs diff --git a/Ryujinx/Cpu/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs similarity index 100% rename from Ryujinx/Cpu/AOpCodeTable.cs rename to ChocolArm64/AOpCodeTable.cs diff --git a/Ryujinx/Cpu/AOptimizations.cs b/ChocolArm64/AOptimizations.cs similarity index 100% rename from Ryujinx/Cpu/AOptimizations.cs rename to ChocolArm64/AOptimizations.cs diff --git a/Ryujinx/Cpu/AThread.cs b/ChocolArm64/AThread.cs similarity index 100% rename from Ryujinx/Cpu/AThread.cs rename to ChocolArm64/AThread.cs diff --git a/Ryujinx/Cpu/ATranslatedSub.cs b/ChocolArm64/ATranslatedSub.cs similarity index 100% rename from Ryujinx/Cpu/ATranslatedSub.cs rename to ChocolArm64/ATranslatedSub.cs diff --git a/Ryujinx/Cpu/ATranslator.cs b/ChocolArm64/ATranslator.cs similarity index 100% rename from Ryujinx/Cpu/ATranslator.cs rename to ChocolArm64/ATranslator.cs diff --git a/ChocolArm64/ChocolArm64.csproj b/ChocolArm64/ChocolArm64.csproj new file mode 100644 index 000000000..47d66cf15 --- /dev/null +++ b/ChocolArm64/ChocolArm64.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.0 + + + + true + + + + true + + + diff --git a/Ryujinx/Cpu/Decoder/ABlock.cs b/ChocolArm64/Decoder/ABlock.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/ABlock.cs rename to ChocolArm64/Decoder/ABlock.cs diff --git a/Ryujinx/Cpu/Decoder/ACond.cs b/ChocolArm64/Decoder/ACond.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/ACond.cs rename to ChocolArm64/Decoder/ACond.cs diff --git a/Ryujinx/Cpu/Decoder/ADataOp.cs b/ChocolArm64/Decoder/ADataOp.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/ADataOp.cs rename to ChocolArm64/Decoder/ADataOp.cs diff --git a/Ryujinx/Cpu/Decoder/ADecoder.cs b/ChocolArm64/Decoder/ADecoder.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/ADecoder.cs rename to ChocolArm64/Decoder/ADecoder.cs diff --git a/Ryujinx/Cpu/Decoder/ADecoderHelper.cs b/ChocolArm64/Decoder/ADecoderHelper.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/ADecoderHelper.cs rename to ChocolArm64/Decoder/ADecoderHelper.cs diff --git a/Ryujinx/Cpu/Decoder/AIntType.cs b/ChocolArm64/Decoder/AIntType.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AIntType.cs rename to ChocolArm64/Decoder/AIntType.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCode.cs b/ChocolArm64/Decoder/AOpCode.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCode.cs rename to ChocolArm64/Decoder/AOpCode.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeAdr.cs b/ChocolArm64/Decoder/AOpCodeAdr.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeAdr.cs rename to ChocolArm64/Decoder/AOpCodeAdr.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeAlu.cs b/ChocolArm64/Decoder/AOpCodeAlu.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeAlu.cs rename to ChocolArm64/Decoder/AOpCodeAlu.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeAluImm.cs b/ChocolArm64/Decoder/AOpCodeAluImm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeAluImm.cs rename to ChocolArm64/Decoder/AOpCodeAluImm.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeAluRs.cs b/ChocolArm64/Decoder/AOpCodeAluRs.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeAluRs.cs rename to ChocolArm64/Decoder/AOpCodeAluRs.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeAluRx.cs b/ChocolArm64/Decoder/AOpCodeAluRx.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeAluRx.cs rename to ChocolArm64/Decoder/AOpCodeAluRx.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImm.cs b/ChocolArm64/Decoder/AOpCodeBImm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeBImm.cs rename to ChocolArm64/Decoder/AOpCodeBImm.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImmAl.cs b/ChocolArm64/Decoder/AOpCodeBImmAl.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeBImmAl.cs rename to ChocolArm64/Decoder/AOpCodeBImmAl.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImmCmp.cs b/ChocolArm64/Decoder/AOpCodeBImmCmp.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeBImmCmp.cs rename to ChocolArm64/Decoder/AOpCodeBImmCmp.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImmCond.cs b/ChocolArm64/Decoder/AOpCodeBImmCond.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeBImmCond.cs rename to ChocolArm64/Decoder/AOpCodeBImmCond.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBImmTest.cs b/ChocolArm64/Decoder/AOpCodeBImmTest.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeBImmTest.cs rename to ChocolArm64/Decoder/AOpCodeBImmTest.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBReg.cs b/ChocolArm64/Decoder/AOpCodeBReg.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeBReg.cs rename to ChocolArm64/Decoder/AOpCodeBReg.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeBfm.cs b/ChocolArm64/Decoder/AOpCodeBfm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeBfm.cs rename to ChocolArm64/Decoder/AOpCodeBfm.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeCcmp.cs b/ChocolArm64/Decoder/AOpCodeCcmp.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeCcmp.cs rename to ChocolArm64/Decoder/AOpCodeCcmp.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeCcmpImm.cs b/ChocolArm64/Decoder/AOpCodeCcmpImm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeCcmpImm.cs rename to ChocolArm64/Decoder/AOpCodeCcmpImm.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeCcmpReg.cs b/ChocolArm64/Decoder/AOpCodeCcmpReg.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeCcmpReg.cs rename to ChocolArm64/Decoder/AOpCodeCcmpReg.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeCsel.cs b/ChocolArm64/Decoder/AOpCodeCsel.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeCsel.cs rename to ChocolArm64/Decoder/AOpCodeCsel.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeException.cs b/ChocolArm64/Decoder/AOpCodeException.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeException.cs rename to ChocolArm64/Decoder/AOpCodeException.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMem.cs b/ChocolArm64/Decoder/AOpCodeMem.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeMem.cs rename to ChocolArm64/Decoder/AOpCodeMem.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMemEx.cs b/ChocolArm64/Decoder/AOpCodeMemEx.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeMemEx.cs rename to ChocolArm64/Decoder/AOpCodeMemEx.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMemImm.cs b/ChocolArm64/Decoder/AOpCodeMemImm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeMemImm.cs rename to ChocolArm64/Decoder/AOpCodeMemImm.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMemLit.cs b/ChocolArm64/Decoder/AOpCodeMemLit.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeMemLit.cs rename to ChocolArm64/Decoder/AOpCodeMemLit.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMemPair.cs b/ChocolArm64/Decoder/AOpCodeMemPair.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeMemPair.cs rename to ChocolArm64/Decoder/AOpCodeMemPair.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMemReg.cs b/ChocolArm64/Decoder/AOpCodeMemReg.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeMemReg.cs rename to ChocolArm64/Decoder/AOpCodeMemReg.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMov.cs b/ChocolArm64/Decoder/AOpCodeMov.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeMov.cs rename to ChocolArm64/Decoder/AOpCodeMov.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeMul.cs b/ChocolArm64/Decoder/AOpCodeMul.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeMul.cs rename to ChocolArm64/Decoder/AOpCodeMul.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimd.cs b/ChocolArm64/Decoder/AOpCodeSimd.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimd.cs rename to ChocolArm64/Decoder/AOpCodeSimd.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdCvt.cs b/ChocolArm64/Decoder/AOpCodeSimdCvt.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdCvt.cs rename to ChocolArm64/Decoder/AOpCodeSimdCvt.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdFcond.cs b/ChocolArm64/Decoder/AOpCodeSimdFcond.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdFcond.cs rename to ChocolArm64/Decoder/AOpCodeSimdFcond.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdFmov.cs b/ChocolArm64/Decoder/AOpCodeSimdFmov.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdFmov.cs rename to ChocolArm64/Decoder/AOpCodeSimdFmov.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdImm.cs b/ChocolArm64/Decoder/AOpCodeSimdImm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdImm.cs rename to ChocolArm64/Decoder/AOpCodeSimdImm.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdIns.cs b/ChocolArm64/Decoder/AOpCodeSimdIns.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdIns.cs rename to ChocolArm64/Decoder/AOpCodeSimdIns.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemImm.cs b/ChocolArm64/Decoder/AOpCodeSimdMemImm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdMemImm.cs rename to ChocolArm64/Decoder/AOpCodeSimdMemImm.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemLit.cs b/ChocolArm64/Decoder/AOpCodeSimdMemLit.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdMemLit.cs rename to ChocolArm64/Decoder/AOpCodeSimdMemLit.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs b/ChocolArm64/Decoder/AOpCodeSimdMemMs.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdMemMs.cs rename to ChocolArm64/Decoder/AOpCodeSimdMemMs.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemPair.cs b/ChocolArm64/Decoder/AOpCodeSimdMemPair.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdMemPair.cs rename to ChocolArm64/Decoder/AOpCodeSimdMemPair.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemReg.cs b/ChocolArm64/Decoder/AOpCodeSimdMemReg.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdMemReg.cs rename to ChocolArm64/Decoder/AOpCodeSimdMemReg.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs b/ChocolArm64/Decoder/AOpCodeSimdMemSs.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs rename to ChocolArm64/Decoder/AOpCodeSimdMemSs.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdReg.cs b/ChocolArm64/Decoder/AOpCodeSimdReg.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdReg.cs rename to ChocolArm64/Decoder/AOpCodeSimdReg.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdRegElem.cs b/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdRegElem.cs rename to ChocolArm64/Decoder/AOpCodeSimdRegElem.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdShImm.cs b/ChocolArm64/Decoder/AOpCodeSimdShImm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdShImm.cs rename to ChocolArm64/Decoder/AOpCodeSimdShImm.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSimdTbl.cs b/ChocolArm64/Decoder/AOpCodeSimdTbl.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSimdTbl.cs rename to ChocolArm64/Decoder/AOpCodeSimdTbl.cs diff --git a/Ryujinx/Cpu/Decoder/AOpCodeSystem.cs b/ChocolArm64/Decoder/AOpCodeSystem.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AOpCodeSystem.cs rename to ChocolArm64/Decoder/AOpCodeSystem.cs diff --git a/Ryujinx/Cpu/Decoder/AShiftType.cs b/ChocolArm64/Decoder/AShiftType.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/AShiftType.cs rename to ChocolArm64/Decoder/AShiftType.cs diff --git a/Ryujinx/Cpu/Decoder/IAOpCode.cs b/ChocolArm64/Decoder/IAOpCode.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/IAOpCode.cs rename to ChocolArm64/Decoder/IAOpCode.cs diff --git a/Ryujinx/Cpu/Decoder/IAOpCodeAlu.cs b/ChocolArm64/Decoder/IAOpCodeAlu.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/IAOpCodeAlu.cs rename to ChocolArm64/Decoder/IAOpCodeAlu.cs diff --git a/Ryujinx/Cpu/Decoder/IAOpCodeAluImm.cs b/ChocolArm64/Decoder/IAOpCodeAluImm.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/IAOpCodeAluImm.cs rename to ChocolArm64/Decoder/IAOpCodeAluImm.cs diff --git a/Ryujinx/Cpu/Decoder/IAOpCodeAluRs.cs b/ChocolArm64/Decoder/IAOpCodeAluRs.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/IAOpCodeAluRs.cs rename to ChocolArm64/Decoder/IAOpCodeAluRs.cs diff --git a/Ryujinx/Cpu/Decoder/IAOpCodeAluRx.cs b/ChocolArm64/Decoder/IAOpCodeAluRx.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/IAOpCodeAluRx.cs rename to ChocolArm64/Decoder/IAOpCodeAluRx.cs diff --git a/Ryujinx/Cpu/Decoder/IAOpCodeCond.cs b/ChocolArm64/Decoder/IAOpCodeCond.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/IAOpCodeCond.cs rename to ChocolArm64/Decoder/IAOpCodeCond.cs diff --git a/Ryujinx/Cpu/Decoder/IAOpCodeLit.cs b/ChocolArm64/Decoder/IAOpCodeLit.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/IAOpCodeLit.cs rename to ChocolArm64/Decoder/IAOpCodeLit.cs diff --git a/Ryujinx/Cpu/Decoder/IAOpCodeSimd.cs b/ChocolArm64/Decoder/IAOpCodeSimd.cs similarity index 100% rename from Ryujinx/Cpu/Decoder/IAOpCodeSimd.cs rename to ChocolArm64/Decoder/IAOpCodeSimd.cs diff --git a/Ryujinx/Cpu/Exceptions/VmmAccessViolationException.cs b/ChocolArm64/Exceptions/VmmAccessViolationException.cs similarity index 100% rename from Ryujinx/Cpu/Exceptions/VmmAccessViolationException.cs rename to ChocolArm64/Exceptions/VmmAccessViolationException.cs diff --git a/Ryujinx/Cpu/Exceptions/VmmOutOfMemoryException.cs b/ChocolArm64/Exceptions/VmmOutOfMemoryException.cs similarity index 100% rename from Ryujinx/Cpu/Exceptions/VmmOutOfMemoryException.cs rename to ChocolArm64/Exceptions/VmmOutOfMemoryException.cs diff --git a/Ryujinx/Cpu/Exceptions/VmmPageFaultException.cs b/ChocolArm64/Exceptions/VmmPageFaultException.cs similarity index 100% rename from Ryujinx/Cpu/Exceptions/VmmPageFaultException.cs rename to ChocolArm64/Exceptions/VmmPageFaultException.cs diff --git a/Ryujinx/Cpu/Instruction/AInst.cs b/ChocolArm64/Instruction/AInst.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInst.cs rename to ChocolArm64/Instruction/AInst.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs b/ChocolArm64/Instruction/AInstEmitAlu.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitAlu.cs rename to ChocolArm64/Instruction/AInstEmitAlu.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs b/ChocolArm64/Instruction/AInstEmitAluHelper.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitAluHelper.cs rename to ChocolArm64/Instruction/AInstEmitAluHelper.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitBfm.cs b/ChocolArm64/Instruction/AInstEmitBfm.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitBfm.cs rename to ChocolArm64/Instruction/AInstEmitBfm.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitCcmp.cs b/ChocolArm64/Instruction/AInstEmitCcmp.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitCcmp.cs rename to ChocolArm64/Instruction/AInstEmitCcmp.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitCsel.cs b/ChocolArm64/Instruction/AInstEmitCsel.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitCsel.cs rename to ChocolArm64/Instruction/AInstEmitCsel.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitException.cs b/ChocolArm64/Instruction/AInstEmitException.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitException.cs rename to ChocolArm64/Instruction/AInstEmitException.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitFlow.cs b/ChocolArm64/Instruction/AInstEmitFlow.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitFlow.cs rename to ChocolArm64/Instruction/AInstEmitFlow.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitMemory.cs b/ChocolArm64/Instruction/AInstEmitMemory.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitMemory.cs rename to ChocolArm64/Instruction/AInstEmitMemory.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitMemoryEx.cs b/ChocolArm64/Instruction/AInstEmitMemoryEx.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitMemoryEx.cs rename to ChocolArm64/Instruction/AInstEmitMemoryEx.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitMemoryHelper.cs b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitMemoryHelper.cs rename to ChocolArm64/Instruction/AInstEmitMemoryHelper.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitMove.cs b/ChocolArm64/Instruction/AInstEmitMove.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitMove.cs rename to ChocolArm64/Instruction/AInstEmitMove.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitMul.cs b/ChocolArm64/Instruction/AInstEmitMul.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitMul.cs rename to ChocolArm64/Instruction/AInstEmitMul.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSimdArithmetic.cs rename to ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSimdCmp.cs rename to ChocolArm64/Instruction/AInstEmitSimdCmp.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSimdCvt.cs rename to ChocolArm64/Instruction/AInstEmitSimdCvt.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSimdHelper.cs rename to ChocolArm64/Instruction/AInstEmitSimdHelper.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdLogical.cs b/ChocolArm64/Instruction/AInstEmitSimdLogical.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSimdLogical.cs rename to ChocolArm64/Instruction/AInstEmitSimdLogical.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdMemory.cs b/ChocolArm64/Instruction/AInstEmitSimdMemory.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSimdMemory.cs rename to ChocolArm64/Instruction/AInstEmitSimdMemory.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs b/ChocolArm64/Instruction/AInstEmitSimdMove.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs rename to ChocolArm64/Instruction/AInstEmitSimdMove.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSimdShift.cs rename to ChocolArm64/Instruction/AInstEmitSimdShift.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSystem.cs b/ChocolArm64/Instruction/AInstEmitSystem.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitSystem.cs rename to ChocolArm64/Instruction/AInstEmitSystem.cs diff --git a/Ryujinx/Cpu/Instruction/AInstEmitter.cs b/ChocolArm64/Instruction/AInstEmitter.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/AInstEmitter.cs rename to ChocolArm64/Instruction/AInstEmitter.cs diff --git a/Ryujinx/Cpu/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs similarity index 100% rename from Ryujinx/Cpu/Instruction/ASoftFallback.cs rename to ChocolArm64/Instruction/ASoftFallback.cs diff --git a/Ryujinx/Cpu/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs similarity index 100% rename from Ryujinx/Cpu/Memory/AMemory.cs rename to ChocolArm64/Memory/AMemory.cs diff --git a/Ryujinx/Cpu/Memory/AMemoryAlloc.cs b/ChocolArm64/Memory/AMemoryAlloc.cs similarity index 100% rename from Ryujinx/Cpu/Memory/AMemoryAlloc.cs rename to ChocolArm64/Memory/AMemoryAlloc.cs diff --git a/Ryujinx/Cpu/Memory/AMemoryHelper.cs b/ChocolArm64/Memory/AMemoryHelper.cs similarity index 100% rename from Ryujinx/Cpu/Memory/AMemoryHelper.cs rename to ChocolArm64/Memory/AMemoryHelper.cs diff --git a/Ryujinx/Cpu/Memory/AMemoryMapInfo.cs b/ChocolArm64/Memory/AMemoryMapInfo.cs similarity index 100% rename from Ryujinx/Cpu/Memory/AMemoryMapInfo.cs rename to ChocolArm64/Memory/AMemoryMapInfo.cs diff --git a/Ryujinx/Cpu/Memory/AMemoryMgr.cs b/ChocolArm64/Memory/AMemoryMgr.cs similarity index 100% rename from Ryujinx/Cpu/Memory/AMemoryMgr.cs rename to ChocolArm64/Memory/AMemoryMgr.cs diff --git a/Ryujinx/Cpu/Memory/AMemoryPerm.cs b/ChocolArm64/Memory/AMemoryPerm.cs similarity index 100% rename from Ryujinx/Cpu/Memory/AMemoryPerm.cs rename to ChocolArm64/Memory/AMemoryPerm.cs diff --git a/Ryujinx/Cpu/State/AInstExceptEventArgs.cs b/ChocolArm64/State/AInstExceptEventArgs.cs similarity index 100% rename from Ryujinx/Cpu/State/AInstExceptEventArgs.cs rename to ChocolArm64/State/AInstExceptEventArgs.cs diff --git a/Ryujinx/Cpu/State/AInstUndEventArgs.cs b/ChocolArm64/State/AInstUndEventArgs.cs similarity index 100% rename from Ryujinx/Cpu/State/AInstUndEventArgs.cs rename to ChocolArm64/State/AInstUndEventArgs.cs diff --git a/Ryujinx/Cpu/State/APState.cs b/ChocolArm64/State/APState.cs similarity index 100% rename from Ryujinx/Cpu/State/APState.cs rename to ChocolArm64/State/APState.cs diff --git a/Ryujinx/Cpu/State/ARegister.cs b/ChocolArm64/State/ARegister.cs similarity index 100% rename from Ryujinx/Cpu/State/ARegister.cs rename to ChocolArm64/State/ARegister.cs diff --git a/Ryujinx/Cpu/State/ARegisterSize.cs b/ChocolArm64/State/ARegisterSize.cs similarity index 100% rename from Ryujinx/Cpu/State/ARegisterSize.cs rename to ChocolArm64/State/ARegisterSize.cs diff --git a/Ryujinx/Cpu/State/ARegisterType.cs b/ChocolArm64/State/ARegisterType.cs similarity index 100% rename from Ryujinx/Cpu/State/ARegisterType.cs rename to ChocolArm64/State/ARegisterType.cs diff --git a/Ryujinx/Cpu/State/AThreadState.cs b/ChocolArm64/State/AThreadState.cs similarity index 100% rename from Ryujinx/Cpu/State/AThreadState.cs rename to ChocolArm64/State/AThreadState.cs diff --git a/Ryujinx/Cpu/State/AVec.cs b/ChocolArm64/State/AVec.cs similarity index 100% rename from Ryujinx/Cpu/State/AVec.cs rename to ChocolArm64/State/AVec.cs diff --git a/Ryujinx/Cpu/Translation/AILBlock.cs b/ChocolArm64/Translation/AILBlock.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILBlock.cs rename to ChocolArm64/Translation/AILBlock.cs diff --git a/Ryujinx/Cpu/Translation/AILEmitter.cs b/ChocolArm64/Translation/AILEmitter.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILEmitter.cs rename to ChocolArm64/Translation/AILEmitter.cs diff --git a/Ryujinx/Cpu/Translation/AILEmitterCtx.cs b/ChocolArm64/Translation/AILEmitterCtx.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILEmitterCtx.cs rename to ChocolArm64/Translation/AILEmitterCtx.cs diff --git a/Ryujinx/Cpu/Translation/AILLabel.cs b/ChocolArm64/Translation/AILLabel.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILLabel.cs rename to ChocolArm64/Translation/AILLabel.cs diff --git a/Ryujinx/Cpu/Translation/AILOpCode.cs b/ChocolArm64/Translation/AILOpCode.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILOpCode.cs rename to ChocolArm64/Translation/AILOpCode.cs diff --git a/Ryujinx/Cpu/Translation/AILOpCodeBranch.cs b/ChocolArm64/Translation/AILOpCodeBranch.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILOpCodeBranch.cs rename to ChocolArm64/Translation/AILOpCodeBranch.cs diff --git a/Ryujinx/Cpu/Translation/AILOpCodeCall.cs b/ChocolArm64/Translation/AILOpCodeCall.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILOpCodeCall.cs rename to ChocolArm64/Translation/AILOpCodeCall.cs diff --git a/Ryujinx/Cpu/Translation/AILOpCodeConst.cs b/ChocolArm64/Translation/AILOpCodeConst.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILOpCodeConst.cs rename to ChocolArm64/Translation/AILOpCodeConst.cs diff --git a/Ryujinx/Cpu/Translation/AILOpCodeLoad.cs b/ChocolArm64/Translation/AILOpCodeLoad.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILOpCodeLoad.cs rename to ChocolArm64/Translation/AILOpCodeLoad.cs diff --git a/Ryujinx/Cpu/Translation/AILOpCodeLog.cs b/ChocolArm64/Translation/AILOpCodeLog.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILOpCodeLog.cs rename to ChocolArm64/Translation/AILOpCodeLog.cs diff --git a/Ryujinx/Cpu/Translation/AILOpCodeStore.cs b/ChocolArm64/Translation/AILOpCodeStore.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AILOpCodeStore.cs rename to ChocolArm64/Translation/AILOpCodeStore.cs diff --git a/Ryujinx/Cpu/Translation/AIoType.cs b/ChocolArm64/Translation/AIoType.cs similarity index 100% rename from Ryujinx/Cpu/Translation/AIoType.cs rename to ChocolArm64/Translation/AIoType.cs diff --git a/Ryujinx/Cpu/Translation/ALocalAlloc.cs b/ChocolArm64/Translation/ALocalAlloc.cs similarity index 100% rename from Ryujinx/Cpu/Translation/ALocalAlloc.cs rename to ChocolArm64/Translation/ALocalAlloc.cs diff --git a/Ryujinx/Cpu/Translation/IAILEmit.cs b/ChocolArm64/Translation/IAILEmit.cs similarity index 100% rename from Ryujinx/Cpu/Translation/IAILEmit.cs rename to ChocolArm64/Translation/IAILEmit.cs diff --git a/Ryujinx/Cpu/Translation/ILGeneratorEx.cs b/ChocolArm64/Translation/ILGeneratorEx.cs similarity index 100% rename from Ryujinx/Cpu/Translation/ILGeneratorEx.cs rename to ChocolArm64/Translation/ILGeneratorEx.cs diff --git a/Ryujinx/Config.cs b/Ryujinx.Core/Config.cs similarity index 99% rename from Ryujinx/Config.cs rename to Ryujinx.Core/Config.cs index b53614211..b97e80b89 100644 --- a/Ryujinx/Config.cs +++ b/Ryujinx.Core/Config.cs @@ -4,7 +4,7 @@ using System.IO; using System.Linq; using System.Reflection; -namespace Ryujinx +namespace Ryujinx.Core { public static class Config { diff --git a/Ryujinx/Hid.cs b/Ryujinx.Core/Hid.cs similarity index 99% rename from Ryujinx/Hid.cs rename to Ryujinx.Core/Hid.cs index c344ec587..44d3e0fb7 100644 --- a/Ryujinx/Hid.cs +++ b/Ryujinx.Core/Hid.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle; +using Ryujinx.Core.OsHle; using System; using System.Runtime.InteropServices; -namespace Ryujinx +namespace Ryujinx.Core { public class Hid { diff --git a/Ryujinx/Hid/HidController.cs b/Ryujinx.Core/Hid/HidController.cs similarity index 99% rename from Ryujinx/Hid/HidController.cs rename to Ryujinx.Core/Hid/HidController.cs index 7dd198412..641bc5569 100644 --- a/Ryujinx/Hid/HidController.cs +++ b/Ryujinx.Core/Hid/HidController.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace Ryujinx +namespace Ryujinx.Core { [Flags] public enum HidControllerKeys diff --git a/Ryujinx/Hid/HidKeyboard.cs b/Ryujinx.Core/Hid/HidKeyboard.cs similarity index 97% rename from Ryujinx/Hid/HidKeyboard.cs rename to Ryujinx.Core/Hid/HidKeyboard.cs index 2ee51bfa1..f9987f68b 100644 --- a/Ryujinx/Hid/HidKeyboard.cs +++ b/Ryujinx.Core/Hid/HidKeyboard.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace Ryujinx +namespace Ryujinx.Core { [StructLayout(LayoutKind.Sequential, Size = 0x20)] public struct HidKeyboardHeader diff --git a/Ryujinx/Hid/HidMouse.cs b/Ryujinx.Core/Hid/HidMouse.cs similarity index 97% rename from Ryujinx/Hid/HidMouse.cs rename to Ryujinx.Core/Hid/HidMouse.cs index db01e649c..9a019dd5f 100644 --- a/Ryujinx/Hid/HidMouse.cs +++ b/Ryujinx.Core/Hid/HidMouse.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace Ryujinx +namespace Ryujinx.Core { [StructLayout(LayoutKind.Sequential, Size = 0x20)] public struct HidMouseHeader diff --git a/Ryujinx/Hid/HidTouchScreen.cs b/Ryujinx.Core/Hid/HidTouchScreen.cs similarity index 98% rename from Ryujinx/Hid/HidTouchScreen.cs rename to Ryujinx.Core/Hid/HidTouchScreen.cs index 7fb022893..b755cb95c 100644 --- a/Ryujinx/Hid/HidTouchScreen.cs +++ b/Ryujinx.Core/Hid/HidTouchScreen.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace Ryujinx +namespace Ryujinx.Core { [StructLayout(LayoutKind.Sequential, Size = 0x28)] public struct HidTouchScreenHeader diff --git a/Ryujinx/Hid/HidUnknown.cs b/Ryujinx.Core/Hid/HidUnknown.cs similarity index 98% rename from Ryujinx/Hid/HidUnknown.cs rename to Ryujinx.Core/Hid/HidUnknown.cs index ef2172d5b..c3fe68a83 100644 --- a/Ryujinx/Hid/HidUnknown.cs +++ b/Ryujinx.Core/Hid/HidUnknown.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace Ryujinx +namespace Ryujinx.Core { [StructLayout(LayoutKind.Sequential, Size = 0x400)] public struct HidSharedMemHeader diff --git a/Ryujinx/Hid/JoyCon.cs b/Ryujinx.Core/Hid/JoyCon.cs similarity index 100% rename from Ryujinx/Hid/JoyCon.cs rename to Ryujinx.Core/Hid/JoyCon.cs diff --git a/Ryujinx/Loaders/Compression/Lz4.cs b/Ryujinx.Core/Loaders/Compression/Lz4.cs similarity index 97% rename from Ryujinx/Loaders/Compression/Lz4.cs rename to Ryujinx.Core/Loaders/Compression/Lz4.cs index aace200cc..eb1602a09 100644 --- a/Ryujinx/Loaders/Compression/Lz4.cs +++ b/Ryujinx.Core/Loaders/Compression/Lz4.cs @@ -1,6 +1,6 @@ using System; -namespace Ryujinx.Loaders.Compression +namespace Ryujinx.Core.Loaders.Compression { static class Lz4 { diff --git a/Ryujinx/Loaders/ElfDyn.cs b/Ryujinx.Core/Loaders/ElfDyn.cs similarity index 89% rename from Ryujinx/Loaders/ElfDyn.cs rename to Ryujinx.Core/Loaders/ElfDyn.cs index 595d6cfb5..2ed50b3e6 100644 --- a/Ryujinx/Loaders/ElfDyn.cs +++ b/Ryujinx.Core/Loaders/ElfDyn.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { struct ElfDyn { diff --git a/Ryujinx/Loaders/ElfDynTag.cs b/Ryujinx.Core/Loaders/ElfDynTag.cs similarity index 98% rename from Ryujinx/Loaders/ElfDynTag.cs rename to Ryujinx.Core/Loaders/ElfDynTag.cs index fb6cab3fb..1616c2238 100644 --- a/Ryujinx/Loaders/ElfDynTag.cs +++ b/Ryujinx.Core/Loaders/ElfDynTag.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { enum ElfDynTag { diff --git a/Ryujinx/Loaders/ElfRel.cs b/Ryujinx.Core/Loaders/ElfRel.cs similarity index 93% rename from Ryujinx/Loaders/ElfRel.cs rename to Ryujinx.Core/Loaders/ElfRel.cs index 8b691d99c..8db274524 100644 --- a/Ryujinx/Loaders/ElfRel.cs +++ b/Ryujinx.Core/Loaders/ElfRel.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { struct ElfRel { diff --git a/Ryujinx/Loaders/ElfRelType.cs b/Ryujinx.Core/Loaders/ElfRelType.cs similarity index 99% rename from Ryujinx/Loaders/ElfRelType.cs rename to Ryujinx.Core/Loaders/ElfRelType.cs index cc638b19d..a05331388 100644 --- a/Ryujinx/Loaders/ElfRelType.cs +++ b/Ryujinx.Core/Loaders/ElfRelType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { enum ElfRelType { diff --git a/Ryujinx/Loaders/ElfSym.cs b/Ryujinx.Core/Loaders/ElfSym.cs similarity index 97% rename from Ryujinx/Loaders/ElfSym.cs rename to Ryujinx.Core/Loaders/ElfSym.cs index c4ed810ce..35a45500a 100644 --- a/Ryujinx/Loaders/ElfSym.cs +++ b/Ryujinx.Core/Loaders/ElfSym.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { struct ElfSym { diff --git a/Ryujinx/Loaders/ElfSymBinding.cs b/Ryujinx.Core/Loaders/ElfSymBinding.cs similarity index 77% rename from Ryujinx/Loaders/ElfSymBinding.cs rename to Ryujinx.Core/Loaders/ElfSymBinding.cs index 8bbc6d4e0..c87894962 100644 --- a/Ryujinx/Loaders/ElfSymBinding.cs +++ b/Ryujinx.Core/Loaders/ElfSymBinding.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { enum ElfSymBinding { diff --git a/Ryujinx/Loaders/ElfSymType.cs b/Ryujinx.Core/Loaders/ElfSymType.cs similarity index 87% rename from Ryujinx/Loaders/ElfSymType.cs rename to Ryujinx.Core/Loaders/ElfSymType.cs index e504411e1..786395e62 100644 --- a/Ryujinx/Loaders/ElfSymType.cs +++ b/Ryujinx.Core/Loaders/ElfSymType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { enum ElfSymType { diff --git a/Ryujinx/Loaders/ElfSymVisibility.cs b/Ryujinx.Core/Loaders/ElfSymVisibility.cs similarity index 82% rename from Ryujinx/Loaders/ElfSymVisibility.cs rename to Ryujinx.Core/Loaders/ElfSymVisibility.cs index a308ef795..e72eb5b83 100644 --- a/Ryujinx/Loaders/ElfSymVisibility.cs +++ b/Ryujinx.Core/Loaders/ElfSymVisibility.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { enum ElfSymVisibility { diff --git a/Ryujinx/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs similarity index 98% rename from Ryujinx/Loaders/Executable.cs rename to Ryujinx.Core/Loaders/Executable.cs index 650436589..6a6073ef2 100644 --- a/Ryujinx/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -1,9 +1,9 @@ using ChocolArm64.Memory; -using Ryujinx.Loaders.Executables; -using Ryujinx.OsHle; +using Ryujinx.Core.Loaders.Executables; +using Ryujinx.Core.OsHle; using System.Collections.Generic; -namespace Ryujinx.Loaders +namespace Ryujinx.Core.Loaders { class Executable { diff --git a/Ryujinx/Loaders/Executables/IExecutable.cs b/Ryujinx.Core/Loaders/Executables/IExecutable.cs similarity index 82% rename from Ryujinx/Loaders/Executables/IExecutable.cs rename to Ryujinx.Core/Loaders/Executables/IExecutable.cs index 3e42a834a..73787b1d2 100644 --- a/Ryujinx/Loaders/Executables/IExecutable.cs +++ b/Ryujinx.Core/Loaders/Executables/IExecutable.cs @@ -1,8 +1,8 @@ using System.Collections.ObjectModel; -namespace Ryujinx.Loaders.Executables +namespace Ryujinx.Core.Loaders.Executables { - interface IExecutable + public interface IExecutable { ReadOnlyCollection Text { get; } ReadOnlyCollection RO { get; } diff --git a/Ryujinx/Loaders/Executables/Nro.cs b/Ryujinx.Core/Loaders/Executables/Nro.cs similarity index 97% rename from Ryujinx/Loaders/Executables/Nro.cs rename to Ryujinx.Core/Loaders/Executables/Nro.cs index 2217f3310..3cbc4c5d4 100644 --- a/Ryujinx/Loaders/Executables/Nro.cs +++ b/Ryujinx.Core/Loaders/Executables/Nro.cs @@ -2,7 +2,7 @@ using System; using System.Collections.ObjectModel; using System.IO; -namespace Ryujinx.Loaders.Executables +namespace Ryujinx.Core.Loaders.Executables { class Nro : IExecutable { diff --git a/Ryujinx/Loaders/Executables/Nso.cs b/Ryujinx.Core/Loaders/Executables/Nso.cs similarity index 97% rename from Ryujinx/Loaders/Executables/Nso.cs rename to Ryujinx.Core/Loaders/Executables/Nso.cs index ead1baf15..7b8bf253a 100644 --- a/Ryujinx/Loaders/Executables/Nso.cs +++ b/Ryujinx.Core/Loaders/Executables/Nso.cs @@ -1,9 +1,9 @@ -using Ryujinx.Loaders.Compression; +using Ryujinx.Core.Loaders.Compression; using System; using System.Collections.ObjectModel; using System.IO; -namespace Ryujinx.Loaders.Executables +namespace Ryujinx.Core.Loaders.Executables { class Nso : IExecutable { diff --git a/Ryujinx/Logging.cs b/Ryujinx.Core/Logging.cs similarity index 99% rename from Ryujinx/Logging.cs rename to Ryujinx.Core/Logging.cs index 2ae858b4e..e14e5587a 100644 --- a/Ryujinx/Logging.cs +++ b/Ryujinx.Core/Logging.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.IO; -namespace Ryujinx +namespace Ryujinx.Core { public static class Logging { diff --git a/Ryujinx/OsHle/CondVar.cs b/Ryujinx.Core/OsHle/CondVar.cs similarity index 97% rename from Ryujinx/OsHle/CondVar.cs rename to Ryujinx.Core/OsHle/CondVar.cs index 91ea37bdb..7b3e18521 100644 --- a/Ryujinx/OsHle/CondVar.cs +++ b/Ryujinx.Core/OsHle/CondVar.cs @@ -1,10 +1,10 @@ -using Ryujinx.OsHle.Handles; +using Ryujinx.Core.OsHle.Handles; using System.Collections.Generic; using System.Threading; -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { - class CondVar + public class CondVar { private Process Process; diff --git a/Ryujinx/OsHle/Display.cs b/Ryujinx.Core/OsHle/Display.cs similarity index 85% rename from Ryujinx/OsHle/Display.cs rename to Ryujinx.Core/OsHle/Display.cs index f62430fa8..590841fc5 100644 --- a/Ryujinx/OsHle/Display.cs +++ b/Ryujinx.Core/OsHle/Display.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { class Display { diff --git a/Ryujinx/OsHle/Exceptions/GuestBrokeExecutionException.cs b/Ryujinx.Core/OsHle/Exceptions/GuestBrokeExecutionException.cs similarity index 85% rename from Ryujinx/OsHle/Exceptions/GuestBrokeExecutionException.cs rename to Ryujinx.Core/OsHle/Exceptions/GuestBrokeExecutionException.cs index 1369c57b2..db4929c5b 100644 --- a/Ryujinx/OsHle/Exceptions/GuestBrokeExecutionException.cs +++ b/Ryujinx.Core/OsHle/Exceptions/GuestBrokeExecutionException.cs @@ -1,6 +1,6 @@ using System; -namespace Ryujinx.OsHle.Exceptions +namespace Ryujinx.Core.OsHle.Exceptions { public class GuestBrokeExecutionException : Exception { diff --git a/Ryujinx/OsHle/Exceptions/UndefinedInstructionException.cs b/Ryujinx.Core/OsHle/Exceptions/UndefinedInstructionException.cs similarity index 90% rename from Ryujinx/OsHle/Exceptions/UndefinedInstructionException.cs rename to Ryujinx.Core/OsHle/Exceptions/UndefinedInstructionException.cs index 86033a82a..20cf83862 100644 --- a/Ryujinx/OsHle/Exceptions/UndefinedInstructionException.cs +++ b/Ryujinx.Core/OsHle/Exceptions/UndefinedInstructionException.cs @@ -1,6 +1,6 @@ using System; -namespace Ryujinx.OsHle.Exceptions +namespace Ryujinx.Core.OsHle.Exceptions { public class UndefinedInstructionException : Exception { diff --git a/Ryujinx/OsHle/FileDesc.cs b/Ryujinx.Core/OsHle/FileDesc.cs similarity index 85% rename from Ryujinx/OsHle/FileDesc.cs rename to Ryujinx.Core/OsHle/FileDesc.cs index 2a21f5007..4be83bb07 100644 --- a/Ryujinx/OsHle/FileDesc.cs +++ b/Ryujinx.Core/OsHle/FileDesc.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { class FileDesc { diff --git a/Ryujinx/OsHle/Handles/HDomain.cs b/Ryujinx.Core/OsHle/Handles/HDomain.cs similarity index 94% rename from Ryujinx/OsHle/Handles/HDomain.cs rename to Ryujinx.Core/OsHle/Handles/HDomain.cs index e781602a1..ca287a5fd 100644 --- a/Ryujinx/OsHle/Handles/HDomain.cs +++ b/Ryujinx.Core/OsHle/Handles/HDomain.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Utilities; +using Ryujinx.Core.OsHle.Utilities; using System; using System.Collections.Generic; -namespace Ryujinx.OsHle.Handles +namespace Ryujinx.Core.OsHle.Handles { class HDomain : HSession { diff --git a/Ryujinx.Core/OsHle/Handles/HEvent.cs b/Ryujinx.Core/OsHle/Handles/HEvent.cs new file mode 100644 index 000000000..4e881ca24 --- /dev/null +++ b/Ryujinx.Core/OsHle/Handles/HEvent.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.Core.OsHle.Handles +{ + class HEvent + { + + } +} \ No newline at end of file diff --git a/Ryujinx/OsHle/Handles/HNvMap.cs b/Ryujinx.Core/OsHle/Handles/HNvMap.cs similarity index 91% rename from Ryujinx/OsHle/Handles/HNvMap.cs rename to Ryujinx.Core/OsHle/Handles/HNvMap.cs index 3e15eda38..09173730b 100644 --- a/Ryujinx/OsHle/Handles/HNvMap.cs +++ b/Ryujinx.Core/OsHle/Handles/HNvMap.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle.Handles +namespace Ryujinx.Core.OsHle.Handles { class HNvMap { diff --git a/Ryujinx/OsHle/Handles/HSession.cs b/Ryujinx.Core/OsHle/Handles/HSession.cs similarity index 93% rename from Ryujinx/OsHle/Handles/HSession.cs rename to Ryujinx.Core/OsHle/Handles/HSession.cs index 6b9016591..8aa1c06bc 100644 --- a/Ryujinx/OsHle/Handles/HSession.cs +++ b/Ryujinx.Core/OsHle/Handles/HSession.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle.Handles +namespace Ryujinx.Core.OsHle.Handles { class HSession { diff --git a/Ryujinx/OsHle/Handles/HSessionObj.cs b/Ryujinx.Core/OsHle/Handles/HSessionObj.cs similarity index 94% rename from Ryujinx/OsHle/Handles/HSessionObj.cs rename to Ryujinx.Core/OsHle/Handles/HSessionObj.cs index a871a11f4..ed0530f74 100644 --- a/Ryujinx/OsHle/Handles/HSessionObj.cs +++ b/Ryujinx.Core/OsHle/Handles/HSessionObj.cs @@ -1,6 +1,6 @@ using System; -namespace Ryujinx.OsHle.Handles +namespace Ryujinx.Core.OsHle.Handles { class HSessionObj : HSession, IDisposable { diff --git a/Ryujinx/OsHle/Handles/HSharedMem.cs b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs similarity index 97% rename from Ryujinx/OsHle/Handles/HSharedMem.cs rename to Ryujinx.Core/OsHle/Handles/HSharedMem.cs index 4f943ebcd..3d56ff920 100644 --- a/Ryujinx/OsHle/Handles/HSharedMem.cs +++ b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Ryujinx.OsHle.Handles +namespace Ryujinx.Core.OsHle.Handles { class HSharedMem { diff --git a/Ryujinx/OsHle/Handles/HThread.cs b/Ryujinx.Core/OsHle/Handles/HThread.cs similarity index 88% rename from Ryujinx/OsHle/Handles/HThread.cs rename to Ryujinx.Core/OsHle/Handles/HThread.cs index fef2faf2c..8bb276fa8 100644 --- a/Ryujinx/OsHle/Handles/HThread.cs +++ b/Ryujinx.Core/OsHle/Handles/HThread.cs @@ -1,8 +1,8 @@ using ChocolArm64; -namespace Ryujinx.OsHle.Handles +namespace Ryujinx.Core.OsHle.Handles { - class HThread + public class HThread { public AThread Thread { get; private set; } diff --git a/Ryujinx/OsHle/Handles/HTransferMem.cs b/Ryujinx.Core/OsHle/Handles/HTransferMem.cs similarity index 93% rename from Ryujinx/OsHle/Handles/HTransferMem.cs rename to Ryujinx.Core/OsHle/Handles/HTransferMem.cs index b24e14129..701fc451c 100644 --- a/Ryujinx/OsHle/Handles/HTransferMem.cs +++ b/Ryujinx.Core/OsHle/Handles/HTransferMem.cs @@ -1,6 +1,6 @@ using ChocolArm64.Memory; -namespace Ryujinx.OsHle.Handles +namespace Ryujinx.Core.OsHle.Handles { class HTransferMem { diff --git a/Ryujinx/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs similarity index 99% rename from Ryujinx/OsHle/Handles/KProcessScheduler.cs rename to Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs index 9044987fd..2045f8a17 100644 --- a/Ryujinx/OsHle/Handles/KProcessScheduler.cs +++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs @@ -3,9 +3,9 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; -namespace Ryujinx.OsHle.Handles +namespace Ryujinx.Core.OsHle.Handles { - class KProcessScheduler : IDisposable + public class KProcessScheduler : IDisposable { private class SchedulerThread : IDisposable { diff --git a/Ryujinx/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs similarity index 97% rename from Ryujinx/OsHle/Horizon.cs rename to Ryujinx.Core/OsHle/Horizon.cs index b9af69c2f..e2d38d522 100644 --- a/Ryujinx/OsHle/Horizon.cs +++ b/Ryujinx.Core/OsHle/Horizon.cs @@ -1,14 +1,14 @@ using ChocolArm64.Memory; -using Ryujinx.Loaders.Executables; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Utilities; +using Ryujinx.Core.Loaders.Executables; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Utilities; +using System; using System.Collections.Concurrent; using System.IO; -using System; -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { - class Horizon + public class Horizon { internal const int HidSize = 0x40000; internal const int FontSize = 0x50; diff --git a/Ryujinx/OsHle/Ipc/IpcBuffDesc.cs b/Ryujinx.Core/OsHle/Ipc/IpcBuffDesc.cs similarity index 95% rename from Ryujinx/OsHle/Ipc/IpcBuffDesc.cs rename to Ryujinx.Core/OsHle/Ipc/IpcBuffDesc.cs index 41b1efe03..01bb15392 100644 --- a/Ryujinx/OsHle/Ipc/IpcBuffDesc.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcBuffDesc.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { struct IpcBuffDesc { diff --git a/Ryujinx/OsHle/Ipc/IpcDomCmd.cs b/Ryujinx.Core/OsHle/Ipc/IpcDomCmd.cs similarity index 70% rename from Ryujinx/OsHle/Ipc/IpcDomCmd.cs rename to Ryujinx.Core/OsHle/Ipc/IpcDomCmd.cs index 035671859..1ef0c4082 100644 --- a/Ryujinx/OsHle/Ipc/IpcDomCmd.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcDomCmd.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { enum IpcDomCmd { diff --git a/Ryujinx/OsHle/Ipc/IpcHandleDesc.cs b/Ryujinx.Core/OsHle/Ipc/IpcHandleDesc.cs similarity index 98% rename from Ryujinx/OsHle/Ipc/IpcHandleDesc.cs rename to Ryujinx.Core/OsHle/Ipc/IpcHandleDesc.cs index fa5d7e1de..572c0e649 100644 --- a/Ryujinx/OsHle/Ipc/IpcHandleDesc.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcHandleDesc.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { class IpcHandleDesc { diff --git a/Ryujinx/OsHle/Ipc/IpcHandler.cs b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs similarity index 98% rename from Ryujinx/OsHle/Ipc/IpcHandler.cs rename to Ryujinx.Core/OsHle/Ipc/IpcHandler.cs index f12789145..deab88969 100644 --- a/Ryujinx/OsHle/Ipc/IpcHandler.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs @@ -1,12 +1,12 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Objects; -using Ryujinx.OsHle.Services; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Objects; +using Ryujinx.Core.OsHle.Services; using System; using System.Collections.Generic; using System.IO; -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { static class IpcHandler { diff --git a/Ryujinx/OsHle/Ipc/IpcMessage.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs similarity index 99% rename from Ryujinx/OsHle/Ipc/IpcMessage.cs rename to Ryujinx.Core/OsHle/Ipc/IpcMessage.cs index 407fd65f9..3b38c4516 100644 --- a/Ryujinx/OsHle/Ipc/IpcMessage.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.IO; -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { class IpcMessage { diff --git a/Ryujinx/OsHle/Ipc/IpcMessageType.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessageType.cs similarity index 79% rename from Ryujinx/OsHle/Ipc/IpcMessageType.cs rename to Ryujinx.Core/OsHle/Ipc/IpcMessageType.cs index b0e283de7..8027508de 100644 --- a/Ryujinx/OsHle/Ipc/IpcMessageType.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcMessageType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { enum IpcMessageType { diff --git a/Ryujinx/OsHle/Ipc/IpcPtrBuffDesc.cs b/Ryujinx.Core/OsHle/Ipc/IpcPtrBuffDesc.cs similarity index 95% rename from Ryujinx/OsHle/Ipc/IpcPtrBuffDesc.cs rename to Ryujinx.Core/OsHle/Ipc/IpcPtrBuffDesc.cs index 414d71f45..d39f78db8 100644 --- a/Ryujinx/OsHle/Ipc/IpcPtrBuffDesc.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcPtrBuffDesc.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { struct IpcPtrBuffDesc { diff --git a/Ryujinx/OsHle/Ipc/IpcRecvListBuffDesc.cs b/Ryujinx.Core/OsHle/Ipc/IpcRecvListBuffDesc.cs similarity index 92% rename from Ryujinx/OsHle/Ipc/IpcRecvListBuffDesc.cs rename to Ryujinx.Core/OsHle/Ipc/IpcRecvListBuffDesc.cs index 8180b8dd3..c647208f6 100644 --- a/Ryujinx/OsHle/Ipc/IpcRecvListBuffDesc.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcRecvListBuffDesc.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { struct IpcRecvListBuffDesc { diff --git a/Ryujinx/OsHle/Ipc/ServiceProcessRequest.cs b/Ryujinx.Core/OsHle/Ipc/ServiceProcessRequest.cs similarity index 65% rename from Ryujinx/OsHle/Ipc/ServiceProcessRequest.cs rename to Ryujinx.Core/OsHle/Ipc/ServiceProcessRequest.cs index 838a6aea8..ea7580744 100644 --- a/Ryujinx/OsHle/Ipc/ServiceProcessRequest.cs +++ b/Ryujinx.Core/OsHle/Ipc/ServiceProcessRequest.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle.Ipc +namespace Ryujinx.Core.OsHle.Ipc { delegate long ServiceProcessRequest(ServiceCtx Context); } \ No newline at end of file diff --git a/Ryujinx/OsHle/MemoryInfo.cs b/Ryujinx.Core/OsHle/MemoryInfo.cs similarity index 96% rename from Ryujinx/OsHle/MemoryInfo.cs rename to Ryujinx.Core/OsHle/MemoryInfo.cs index 395ccf73e..76a4bef3b 100644 --- a/Ryujinx/OsHle/MemoryInfo.cs +++ b/Ryujinx.Core/OsHle/MemoryInfo.cs @@ -1,6 +1,6 @@ using ChocolArm64.Memory; -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { struct MemoryInfo { diff --git a/Ryujinx/OsHle/MemoryType.cs b/Ryujinx.Core/OsHle/MemoryType.cs similarity index 96% rename from Ryujinx/OsHle/MemoryType.cs rename to Ryujinx.Core/OsHle/MemoryType.cs index b1ac330ae..d3b43dd55 100644 --- a/Ryujinx/OsHle/MemoryType.cs +++ b/Ryujinx.Core/OsHle/MemoryType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { enum MemoryType { diff --git a/Ryujinx/OsHle/Mutex.cs b/Ryujinx.Core/OsHle/Mutex.cs similarity index 97% rename from Ryujinx/OsHle/Mutex.cs rename to Ryujinx.Core/OsHle/Mutex.cs index 43862d7b2..c95ed7716 100644 --- a/Ryujinx/OsHle/Mutex.cs +++ b/Ryujinx.Core/OsHle/Mutex.cs @@ -1,10 +1,10 @@ -using Ryujinx.OsHle.Handles; +using Ryujinx.Core.OsHle.Handles; using System.Collections.Concurrent; using System.Threading; -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { - class Mutex + public class Mutex { private const int MutexHasListenersMask = 0x40000000; diff --git a/Ryujinx/OsHle/Objects/Acc/IManagerForApplication.cs b/Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs similarity index 91% rename from Ryujinx/OsHle/Objects/Acc/IManagerForApplication.cs rename to Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs index 404ee7da6..afbfab240 100644 --- a/Ryujinx/OsHle/Objects/Acc/IManagerForApplication.cs +++ b/Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Acc +namespace Ryujinx.Core.OsHle.Objects.Acc { class IManagerForApplication : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Acc/IProfile.cs b/Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs similarity index 92% rename from Ryujinx/OsHle/Objects/Acc/IProfile.cs rename to Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs index c84c7ae28..94d171833 100644 --- a/Ryujinx/OsHle/Objects/Acc/IProfile.cs +++ b/Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Acc +namespace Ryujinx.Core.OsHle.Objects.Acc { class IProfile : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IApplicationFunctions.cs b/Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs similarity index 94% rename from Ryujinx/OsHle/Objects/Am/IApplicationFunctions.cs rename to Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs index 138d9084f..939ad2486 100644 --- a/Ryujinx/OsHle/Objects/Am/IApplicationFunctions.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs @@ -1,10 +1,10 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; using System.IO; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IApplicationFunctions : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IApplicationProxy.cs b/Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs similarity index 94% rename from Ryujinx/OsHle/Objects/Am/IApplicationProxy.cs rename to Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs index 3d692d6bc..4a164daf1 100644 --- a/Ryujinx/OsHle/Objects/Am/IApplicationProxy.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs @@ -1,9 +1,9 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IApplicationProxy : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IAudioController.cs b/Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs similarity index 85% rename from Ryujinx/OsHle/Objects/Am/IAudioController.cs rename to Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs index 0ca49f892..c37042fdb 100644 --- a/Ryujinx/OsHle/Objects/Am/IAudioController.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IAudioController : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/ICommonStateGetter.cs b/Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs similarity index 96% rename from Ryujinx/OsHle/Objects/Am/ICommonStateGetter.cs rename to Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs index 5a3af8e11..83d61fa64 100644 --- a/Ryujinx/OsHle/Objects/Am/ICommonStateGetter.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class ICommonStateGetter : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IDebugFunctions.cs b/Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs similarity index 85% rename from Ryujinx/OsHle/Objects/Am/IDebugFunctions.cs rename to Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs index dc57e8e6e..d04d8363f 100644 --- a/Ryujinx/OsHle/Objects/Am/IDebugFunctions.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IDebugFunctions : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IDisplayController.cs b/Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs similarity index 85% rename from Ryujinx/OsHle/Objects/Am/IDisplayController.cs rename to Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs index 886120866..9eafa70dc 100644 --- a/Ryujinx/OsHle/Objects/Am/IDisplayController.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IDisplayController : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/ILibraryAppletCreator.cs b/Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs similarity index 86% rename from Ryujinx/OsHle/Objects/Am/ILibraryAppletCreator.cs rename to Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs index 91fae3dd0..10e0f4f4a 100644 --- a/Ryujinx/OsHle/Objects/Am/ILibraryAppletCreator.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class ILibraryAppletCreator : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IParentalControlService.cs b/Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs similarity index 86% rename from Ryujinx/OsHle/Objects/Am/IParentalControlService.cs rename to Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs index c462ff07f..1feacfa64 100644 --- a/Ryujinx/OsHle/Objects/Am/IParentalControlService.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IParentalControlService : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/ISelfController.cs b/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs similarity index 95% rename from Ryujinx/OsHle/Objects/Am/ISelfController.cs rename to Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs index c46396c55..691bb202f 100644 --- a/Ryujinx/OsHle/Objects/Am/ISelfController.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class ISelfController : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IStorage.cs b/Ryujinx.Core/OsHle/Objects/Am/IStorage.cs similarity index 84% rename from Ryujinx/OsHle/Objects/Am/IStorage.cs rename to Ryujinx.Core/OsHle/Objects/Am/IStorage.cs index d5a7ee610..b30059ba2 100644 --- a/Ryujinx/OsHle/Objects/Am/IStorage.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IStorage.cs @@ -1,9 +1,9 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IStorage : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IStorageAccessor.cs b/Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs similarity index 95% rename from Ryujinx/OsHle/Objects/Am/IStorageAccessor.cs rename to Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs index bcf0fc01c..df260cc3e 100644 --- a/Ryujinx/OsHle/Objects/Am/IStorageAccessor.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs @@ -1,9 +1,9 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IStorageAccessor : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Am/IWindowController.cs b/Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs similarity index 91% rename from Ryujinx/OsHle/Objects/Am/IWindowController.cs rename to Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs index 1796644e3..aa6e961e0 100644 --- a/Ryujinx/OsHle/Objects/Am/IWindowController.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.Objects.Am { class IWindowController : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Apm/ISession.cs b/Ryujinx.Core/OsHle/Objects/Apm/ISession.cs similarity index 90% rename from Ryujinx/OsHle/Objects/Apm/ISession.cs rename to Ryujinx.Core/OsHle/Objects/Apm/ISession.cs index f3965b484..3ab330055 100644 --- a/Ryujinx/OsHle/Objects/Apm/ISession.cs +++ b/Ryujinx.Core/OsHle/Objects/Apm/ISession.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Apm +namespace Ryujinx.Core.OsHle.Objects.Apm { class ISession : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs similarity index 98% rename from Ryujinx/OsHle/Objects/Aud/IAudioOut.cs rename to Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs index 9e55e30e8..061c63763 100644 --- a/Ryujinx/OsHle/Objects/Aud/IAudioOut.cs +++ b/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs @@ -1,13 +1,13 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; using OpenTK.Audio; using OpenTK.Audio.OpenAL; using System; using System.Collections.Generic; using System.IO; -namespace Ryujinx.OsHle.Objects.Aud +namespace Ryujinx.Core.OsHle.Objects.Aud { class IAudioOut : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs similarity index 95% rename from Ryujinx/OsHle/Objects/Aud/IAudioRenderer.cs rename to Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs index a953d82a0..053564773 100644 --- a/Ryujinx/OsHle/Objects/Aud/IAudioRenderer.cs +++ b/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Aud +namespace Ryujinx.Core.OsHle.Objects.Aud { class IAudioRenderer : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Friend/IFriendService.cs b/Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs similarity index 85% rename from Ryujinx/OsHle/Objects/Friend/IFriendService.cs rename to Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs index 41084f8da..e98e27cad 100644 --- a/Ryujinx/OsHle/Objects/Friend/IFriendService.cs +++ b/Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Friend +namespace Ryujinx.Core.OsHle.Objects.Friend { class IFriendService : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/FspSrv/IDirectory.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs similarity index 98% rename from Ryujinx/OsHle/Objects/FspSrv/IDirectory.cs rename to Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs index 828674511..88fce28eb 100644 --- a/Ryujinx/OsHle/Objects/FspSrv/IDirectory.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs @@ -1,5 +1,5 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; using System.IO; @@ -7,7 +7,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; -namespace Ryujinx.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.Objects.FspSrv { [StructLayout(LayoutKind.Sequential, Size = 0x310)] struct DirectoryEntry diff --git a/Ryujinx/OsHle/Objects/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs similarity index 97% rename from Ryujinx/OsHle/Objects/FspSrv/IFile.cs rename to Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs index 2f3899909..95fbc650f 100644 --- a/Ryujinx/OsHle/Objects/FspSrv/IFile.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs @@ -1,10 +1,10 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; using System.IO; -namespace Ryujinx.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.Objects.FspSrv { class IFile : IIpcInterface, IDisposable { diff --git a/Ryujinx/OsHle/Objects/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs similarity index 98% rename from Ryujinx/OsHle/Objects/FspSrv/IFileSystem.cs rename to Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs index c3edf2712..68b158452 100644 --- a/Ryujinx/OsHle/Objects/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs @@ -1,11 +1,11 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; using System.IO; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.Objects.FspSrv { class IFileSystem : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/FspSrv/IStorage.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs similarity index 94% rename from Ryujinx/OsHle/Objects/FspSrv/IStorage.cs rename to Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs index 40fb87cac..4eca37e8e 100644 --- a/Ryujinx/OsHle/Objects/FspSrv/IStorage.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs @@ -1,9 +1,9 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; using System.IO; -namespace Ryujinx.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.Objects.FspSrv { class IStorage : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs similarity index 87% rename from Ryujinx/OsHle/Objects/Hid/IAppletResource.cs rename to Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs index ac7ccf564..d6e8947bb 100644 --- a/Ryujinx/OsHle/Objects/Hid/IAppletResource.cs +++ b/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Hid +namespace Ryujinx.Core.OsHle.Objects.Hid { class IAppletResource : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/IIpcInterface.cs b/Ryujinx.Core/OsHle/Objects/IIpcInterface.cs similarity index 69% rename from Ryujinx/OsHle/Objects/IIpcInterface.cs rename to Ryujinx.Core/OsHle/Objects/IIpcInterface.cs index af0594cc1..c57a09748 100644 --- a/Ryujinx/OsHle/Objects/IIpcInterface.cs +++ b/Ryujinx.Core/OsHle/Objects/IIpcInterface.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects +namespace Ryujinx.Core.OsHle.Objects { interface IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/ObjHelper.cs b/Ryujinx.Core/OsHle/Objects/ObjHelper.cs similarity index 84% rename from Ryujinx/OsHle/Objects/ObjHelper.cs rename to Ryujinx.Core/OsHle/Objects/ObjHelper.cs index bab222032..a151a2879 100644 --- a/Ryujinx/OsHle/Objects/ObjHelper.cs +++ b/Ryujinx.Core/OsHle/Objects/ObjHelper.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; -namespace Ryujinx.OsHle.Objects +namespace Ryujinx.Core.OsHle.Objects { static class ObjHelper { diff --git a/Ryujinx/OsHle/Objects/Parcel.cs b/Ryujinx.Core/OsHle/Objects/Parcel.cs similarity index 97% rename from Ryujinx/OsHle/Objects/Parcel.cs rename to Ryujinx.Core/OsHle/Objects/Parcel.cs index 0d322bab8..cd7179e1e 100644 --- a/Ryujinx/OsHle/Objects/Parcel.cs +++ b/Ryujinx.Core/OsHle/Objects/Parcel.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Ryujinx.OsHle.Objects.Android +namespace Ryujinx.Core.OsHle.Objects.Android { static class Parcel { diff --git a/Ryujinx/OsHle/Objects/Time/ISteadyClock.cs b/Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs similarity index 85% rename from Ryujinx/OsHle/Objects/Time/ISteadyClock.cs rename to Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs index a5139bab0..1116b8492 100644 --- a/Ryujinx/OsHle/Objects/Time/ISteadyClock.cs +++ b/Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Time +namespace Ryujinx.Core.OsHle.Objects.Time { class ISteadyClock : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Time/ISystemClock.cs b/Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs similarity index 93% rename from Ryujinx/OsHle/Objects/Time/ISystemClock.cs rename to Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs index 1d9bae3bb..3aa706915 100644 --- a/Ryujinx/OsHle/Objects/Time/ISystemClock.cs +++ b/Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Time +namespace Ryujinx.Core.OsHle.Objects.Time { class ISystemClock : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs similarity index 85% rename from Ryujinx/OsHle/Objects/Time/ITimeZoneService.cs rename to Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs index 29e7ec927..c083628bb 100644 --- a/Ryujinx/OsHle/Objects/Time/ITimeZoneService.cs +++ b/Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Time +namespace Ryujinx.Core.OsHle.Objects.Time { class ITimeZoneService : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Time/SystemClockType.cs b/Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs similarity index 66% rename from Ryujinx/OsHle/Objects/Time/SystemClockType.cs rename to Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs index ad9675aab..f447ca1cf 100644 --- a/Ryujinx/OsHle/Objects/Time/SystemClockType.cs +++ b/Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle.Objects.Time +namespace Ryujinx.Core.OsHle.Objects.Time { enum SystemClockType { diff --git a/Ryujinx/OsHle/Objects/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs similarity index 96% rename from Ryujinx/OsHle/Objects/Vi/IApplicationDisplayService.cs rename to Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs index 4fa359280..b3ec0e90c 100644 --- a/Ryujinx/OsHle/Objects/Vi/IApplicationDisplayService.cs +++ b/Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs @@ -1,13 +1,13 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; using System.IO; -using static Ryujinx.OsHle.Objects.Android.Parcel; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.Android.Parcel; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Objects.Vi +namespace Ryujinx.Core.OsHle.Objects.Vi { class IApplicationDisplayService : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs similarity index 97% rename from Ryujinx/OsHle/Objects/Vi/IHOSBinderDriver.cs rename to Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs index 157d600fb..cfd271e85 100644 --- a/Ryujinx/OsHle/Objects/Vi/IHOSBinderDriver.cs +++ b/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs @@ -1,15 +1,15 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; -using Ryujinx.OsHle.Utilities; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using Ryujinx.Core.OsHle.Utilities; using System; using System.Collections.Generic; using System.IO; using System.Text; -using static Ryujinx.OsHle.Objects.Android.Parcel; +using static Ryujinx.Core.OsHle.Objects.Android.Parcel; -namespace Ryujinx.OsHle.Objects.Vi +namespace Ryujinx.Core.OsHle.Objects.Vi { class IHOSBinderDriver : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Vi/IManagerDisplayService.cs b/Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs similarity index 91% rename from Ryujinx/OsHle/Objects/Vi/IManagerDisplayService.cs rename to Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs index c2bbf43b2..f1b3cdd0a 100644 --- a/Ryujinx/OsHle/Objects/Vi/IManagerDisplayService.cs +++ b/Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Vi +namespace Ryujinx.Core.OsHle.Objects.Vi { class IManagerDisplayService : IIpcInterface { diff --git a/Ryujinx/OsHle/Objects/Vi/ISystemDisplayService.cs b/Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs similarity index 88% rename from Ryujinx/OsHle/Objects/Vi/ISystemDisplayService.cs rename to Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs index 39d197864..4c83c25f1 100644 --- a/Ryujinx/OsHle/Objects/Vi/ISystemDisplayService.cs +++ b/Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.OsHle.Objects.Vi +namespace Ryujinx.Core.OsHle.Objects.Vi { class ISystemDisplayService : IIpcInterface { diff --git a/Ryujinx/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs similarity index 96% rename from Ryujinx/OsHle/Process.cs rename to Ryujinx.Core/OsHle/Process.cs index 4d07b94bd..842678859 100644 --- a/Ryujinx/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -1,19 +1,19 @@ using ChocolArm64; using ChocolArm64.Memory; using ChocolArm64.State; -using Ryujinx.Loaders; -using Ryujinx.Loaders.Executables; -using Ryujinx.OsHle.Exceptions; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Svc; +using Ryujinx.Core.Loaders; +using Ryujinx.Core.Loaders.Executables; +using Ryujinx.Core.OsHle.Exceptions; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Svc; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { - class Process : IDisposable + public class Process : IDisposable { private const int MaxStackSize = 8 * 1024 * 1024; diff --git a/Ryujinx/OsHle/ServiceCtx.cs b/Ryujinx.Core/OsHle/ServiceCtx.cs similarity index 92% rename from Ryujinx/OsHle/ServiceCtx.cs rename to Ryujinx.Core/OsHle/ServiceCtx.cs index 501d8d0f0..31ecce3de 100644 --- a/Ryujinx/OsHle/ServiceCtx.cs +++ b/Ryujinx.Core/OsHle/ServiceCtx.cs @@ -1,9 +1,9 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; using System.IO; -namespace Ryujinx.OsHle +namespace Ryujinx.Core.OsHle { class ServiceCtx { diff --git a/Ryujinx/OsHle/Services/ServiceAcc.cs b/Ryujinx.Core/OsHle/Services/ServiceAcc.cs similarity index 83% rename from Ryujinx/OsHle/Services/ServiceAcc.cs rename to Ryujinx.Core/OsHle/Services/ServiceAcc.cs index 632fb41c2..f25113e59 100644 --- a/Ryujinx/OsHle/Services/ServiceAcc.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceAcc.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Objects.Acc; +using Ryujinx.Core.OsHle.Objects.Acc; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceApm.cs b/Ryujinx.Core/OsHle/Services/ServiceApm.cs similarity index 61% rename from Ryujinx/OsHle/Services/ServiceApm.cs rename to Ryujinx.Core/OsHle/Services/ServiceApm.cs index 81e68680a..e1bc0d348 100644 --- a/Ryujinx/OsHle/Services/ServiceApm.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceApm.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Objects.Apm; +using Ryujinx.Core.OsHle.Objects.Apm; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs similarity index 64% rename from Ryujinx/OsHle/Services/ServiceAppletOE.cs rename to Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs index 9f2391df7..bbb2484b4 100644 --- a/Ryujinx/OsHle/Services/ServiceAppletOE.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Objects.Am; +using Ryujinx.Core.OsHle.Objects.Am; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceAud.cs b/Ryujinx.Core/OsHle/Services/ServiceAud.cs similarity index 94% rename from Ryujinx/OsHle/Services/ServiceAud.cs rename to Ryujinx.Core/OsHle/Services/ServiceAud.cs index 6d1367cf1..a8ba7dc01 100644 --- a/Ryujinx/OsHle/Services/ServiceAud.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceAud.cs @@ -1,10 +1,10 @@ using ChocolArm64.Memory; -using Ryujinx.OsHle.Objects.Aud; +using Ryujinx.Core.OsHle.Objects.Aud; using System.Text; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceFriend.cs b/Ryujinx.Core/OsHle/Services/ServiceFriend.cs similarity index 62% rename from Ryujinx/OsHle/Services/ServiceFriend.cs rename to Ryujinx.Core/OsHle/Services/ServiceFriend.cs index 10c23aaea..d1229bd46 100644 --- a/Ryujinx/OsHle/Services/ServiceFriend.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceFriend.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Objects.Friend; +using Ryujinx.Core.OsHle.Objects.Friend; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs similarity index 89% rename from Ryujinx/OsHle/Services/ServiceFspSrv.cs rename to Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs index 17aa3bda7..3fe41cf06 100644 --- a/Ryujinx/OsHle/Services/ServiceFspSrv.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Objects.FspSrv; +using Ryujinx.Core.OsHle.Objects.FspSrv; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/ServiceHid.cs similarity index 89% rename from Ryujinx/OsHle/Services/ServiceHid.cs rename to Ryujinx.Core/OsHle/Services/ServiceHid.cs index 176c7842c..4b2e82ffb 100644 --- a/Ryujinx/OsHle/Services/ServiceHid.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceHid.cs @@ -1,9 +1,9 @@ -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Objects.Hid; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Objects.Hid; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceLm.cs b/Ryujinx.Core/OsHle/Services/ServiceLm.cs similarity index 83% rename from Ryujinx/OsHle/Services/ServiceLm.cs rename to Ryujinx.Core/OsHle/Services/ServiceLm.cs index dc6acad95..1fdde5521 100644 --- a/Ryujinx/OsHle/Services/ServiceLm.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceLm.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs similarity index 96% rename from Ryujinx/OsHle/Services/ServiceNvDrv.cs rename to Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs index 405eace2b..6c5fdaedd 100644 --- a/Ryujinx/OsHle/Services/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs @@ -1,12 +1,12 @@ using ChocolArm64.Memory; -using Ryujinx.Gpu; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; -using Ryujinx.OsHle.Utilities; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using Ryujinx.Core.OsHle.Utilities; +using Ryujinx.Graphics.Gpu; using System; using System.Collections.Generic; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { @@ -142,11 +142,11 @@ namespace Ryujinx.OsHle.Services if ((Flags & 1) != 0) { - Align = Context.Ns.Gpu.MemoryMgr.Reserve(Align, (long)Pages * PageSize, 1); + Align = Context.Ns.Gpu.ReserveMemory(Align, (long)Pages * PageSize, 1); } else { - Align = Context.Ns.Gpu.MemoryMgr.Reserve((long)Pages * PageSize, Align); + Align = Context.Ns.Gpu.ReserveMemory((long)Pages * PageSize, Align); } Context.Memory.WriteInt64(Position + 0x10, Align); @@ -174,11 +174,11 @@ namespace Ryujinx.OsHle.Services { if ((Flags & 1) != 0) { - Offset = Context.Ns.Gpu.MemoryMgr.Map(NvMap.Address, Offset, NvMap.Size); + Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, Offset, NvMap.Size); } else { - Offset = Context.Ns.Gpu.MemoryMgr.Map(NvMap.Address, NvMap.Size); + Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, NvMap.Size); } } @@ -417,7 +417,7 @@ namespace Ryujinx.OsHle.Services int Size = (int)(GpFifoHdr >> 40) & 0x7ffffc; - long CpuAddr = Context.Ns.Gpu.MemoryMgr.GetCpuAddr(GpuAddr); + long CpuAddr = Context.Ns.Gpu.GetCpuAddr(GpuAddr); if (CpuAddr != -1) { @@ -425,7 +425,7 @@ namespace Ryujinx.OsHle.Services NsGpuPBEntry[] PushBuffer = NsGpuPBEntry.DecodePushBuffer(Data); - Context.Ns.Gpu.PGraph.ProcessPushBuffer(PushBuffer, Context.Memory); + Context.Ns.Gpu.ProcessPushBuffer(PushBuffer, Context.Memory); } } diff --git a/Ryujinx/OsHle/Services/ServicePctl.cs b/Ryujinx.Core/OsHle/Services/ServicePctl.cs similarity index 63% rename from Ryujinx/OsHle/Services/ServicePctl.cs rename to Ryujinx.Core/OsHle/Services/ServicePctl.cs index a0a5aaf3f..9c4406bb6 100644 --- a/Ryujinx/OsHle/Services/ServicePctl.cs +++ b/Ryujinx.Core/OsHle/Services/ServicePctl.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Objects.Am; +using Ryujinx.Core.OsHle.Objects.Am; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServicePl.cs b/Ryujinx.Core/OsHle/Services/ServicePl.cs similarity index 91% rename from Ryujinx/OsHle/Services/ServicePl.cs rename to Ryujinx.Core/OsHle/Services/ServicePl.cs index 6981637f9..21e6741cd 100644 --- a/Ryujinx/OsHle/Services/ServicePl.cs +++ b/Ryujinx.Core/OsHle/Services/ServicePl.cs @@ -1,6 +1,6 @@ -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Ipc; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceSet.cs b/Ryujinx.Core/OsHle/Services/ServiceSet.cs similarity index 95% rename from Ryujinx/OsHle/Services/ServiceSet.cs rename to Ryujinx.Core/OsHle/Services/ServiceSet.cs index f98e8f0de..83ea5b2ce 100644 --- a/Ryujinx/OsHle/Services/ServiceSet.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceSet.cs @@ -1,6 +1,6 @@ using ChocolArm64.Memory; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceSm.cs b/Ryujinx.Core/OsHle/Services/ServiceSm.cs similarity index 91% rename from Ryujinx/OsHle/Services/ServiceSm.cs rename to Ryujinx.Core/OsHle/Services/ServiceSm.cs index 8af3ed5e4..58abed241 100644 --- a/Ryujinx/OsHle/Services/ServiceSm.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceSm.cs @@ -1,7 +1,7 @@ -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceTime.cs b/Ryujinx.Core/OsHle/Services/ServiceTime.cs similarity index 88% rename from Ryujinx/OsHle/Services/ServiceTime.cs rename to Ryujinx.Core/OsHle/Services/ServiceTime.cs index 8a32aabc1..a5fddcba6 100644 --- a/Ryujinx/OsHle/Services/ServiceTime.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceTime.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Objects.Time; +using Ryujinx.Core.OsHle.Objects.Time; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Services/ServiceVi.cs b/Ryujinx.Core/OsHle/Services/ServiceVi.cs similarity index 69% rename from Ryujinx/OsHle/Services/ServiceVi.cs rename to Ryujinx.Core/OsHle/Services/ServiceVi.cs index 096bc18f0..75cdc31b2 100644 --- a/Ryujinx/OsHle/Services/ServiceVi.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceVi.cs @@ -1,8 +1,8 @@ -using Ryujinx.OsHle.Objects.Vi; +using Ryujinx.Core.OsHle.Objects.Vi; -using static Ryujinx.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.Objects.ObjHelper; -namespace Ryujinx.OsHle.Services +namespace Ryujinx.Core.OsHle.Services { static partial class Service { diff --git a/Ryujinx/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs similarity index 98% rename from Ryujinx/OsHle/Svc/SvcHandler.cs rename to Ryujinx.Core/OsHle/Svc/SvcHandler.cs index 3ab89d445..60af1e11d 100644 --- a/Ryujinx/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs @@ -3,7 +3,7 @@ using ChocolArm64.State; using System; using System.Collections.Generic; -namespace Ryujinx.OsHle.Svc +namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler { diff --git a/Ryujinx/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs similarity index 98% rename from Ryujinx/OsHle/Svc/SvcMemory.cs rename to Ryujinx.Core/OsHle/Svc/SvcMemory.cs index fa91397c4..7528f4e03 100644 --- a/Ryujinx/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -1,8 +1,8 @@ using ChocolArm64.Memory; using ChocolArm64.State; -using Ryujinx.OsHle.Handles; +using Ryujinx.Core.OsHle.Handles; -namespace Ryujinx.OsHle.Svc +namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler { diff --git a/Ryujinx/OsHle/Svc/SvcResult.cs b/Ryujinx.Core/OsHle/Svc/SvcResult.cs similarity index 84% rename from Ryujinx/OsHle/Svc/SvcResult.cs rename to Ryujinx.Core/OsHle/Svc/SvcResult.cs index 4f0c4f1fd..a5be9a945 100644 --- a/Ryujinx/OsHle/Svc/SvcResult.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcResult.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.OsHle.Svc +namespace Ryujinx.Core.OsHle.Svc { enum SvcResult { diff --git a/Ryujinx/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs similarity index 98% rename from Ryujinx/OsHle/Svc/SvcSystem.cs rename to Ryujinx.Core/OsHle/Svc/SvcSystem.cs index 0570ccb09..7f593c8f2 100644 --- a/Ryujinx/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -1,12 +1,12 @@ using ChocolArm64.Memory; using ChocolArm64.State; -using Ryujinx.OsHle.Exceptions; -using Ryujinx.OsHle.Handles; -using Ryujinx.OsHle.Ipc; +using Ryujinx.Core.OsHle.Exceptions; +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; using System; using System.Threading; -namespace Ryujinx.OsHle.Svc +namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler { diff --git a/Ryujinx/OsHle/Svc/SvcThread.cs b/Ryujinx.Core/OsHle/Svc/SvcThread.cs similarity index 97% rename from Ryujinx/OsHle/Svc/SvcThread.cs rename to Ryujinx.Core/OsHle/Svc/SvcThread.cs index cc2bbb1eb..a635edb15 100644 --- a/Ryujinx/OsHle/Svc/SvcThread.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThread.cs @@ -1,7 +1,7 @@ using ChocolArm64.State; -using Ryujinx.OsHle.Handles; +using Ryujinx.Core.OsHle.Handles; -namespace Ryujinx.OsHle.Svc +namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler { diff --git a/Ryujinx/OsHle/Svc/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs similarity index 97% rename from Ryujinx/OsHle/Svc/SvcThreadSync.cs rename to Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs index f342f51d5..dec13f75e 100644 --- a/Ryujinx/OsHle/Svc/SvcThreadSync.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs @@ -1,7 +1,7 @@ using ChocolArm64.State; -using Ryujinx.OsHle.Handles; +using Ryujinx.Core.OsHle.Handles; -namespace Ryujinx.OsHle.Svc +namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler { diff --git a/Ryujinx/OsHle/Utilities/IdPool.cs b/Ryujinx.Core/OsHle/Utilities/IdPool.cs similarity index 96% rename from Ryujinx/OsHle/Utilities/IdPool.cs rename to Ryujinx.Core/OsHle/Utilities/IdPool.cs index 836d6310e..a7e181fa2 100644 --- a/Ryujinx/OsHle/Utilities/IdPool.cs +++ b/Ryujinx.Core/OsHle/Utilities/IdPool.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Ryujinx.OsHle.Utilities +namespace Ryujinx.Core.OsHle.Utilities { class IdPool { diff --git a/Ryujinx/OsHle/Utilities/IdPoolWithObj.cs b/Ryujinx.Core/OsHle/Utilities/IdPoolWithObj.cs similarity index 97% rename from Ryujinx/OsHle/Utilities/IdPoolWithObj.cs rename to Ryujinx.Core/OsHle/Utilities/IdPoolWithObj.cs index 621466a82..f0a339df3 100644 --- a/Ryujinx/OsHle/Utilities/IdPoolWithObj.cs +++ b/Ryujinx.Core/OsHle/Utilities/IdPoolWithObj.cs @@ -3,7 +3,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; -namespace Ryujinx.OsHle.Utilities +namespace Ryujinx.Core.OsHle.Utilities { class IdPoolWithObj : IEnumerable> { diff --git a/Ryujinx/OsHle/Utilities/MemReader.cs b/Ryujinx.Core/OsHle/Utilities/MemReader.cs similarity index 95% rename from Ryujinx/OsHle/Utilities/MemReader.cs rename to Ryujinx.Core/OsHle/Utilities/MemReader.cs index 9868293a0..fe92f68fd 100644 --- a/Ryujinx/OsHle/Utilities/MemReader.cs +++ b/Ryujinx.Core/OsHle/Utilities/MemReader.cs @@ -1,6 +1,6 @@ using ChocolArm64.Memory; -namespace Ryujinx.OsHle.Utilities +namespace Ryujinx.Core.OsHle.Utilities { class MemReader { diff --git a/Ryujinx/OsHle/Utilities/MemWriter.cs b/Ryujinx.Core/OsHle/Utilities/MemWriter.cs similarity index 94% rename from Ryujinx/OsHle/Utilities/MemWriter.cs rename to Ryujinx.Core/OsHle/Utilities/MemWriter.cs index 041b0a970..21b6a3b65 100644 --- a/Ryujinx/OsHle/Utilities/MemWriter.cs +++ b/Ryujinx.Core/OsHle/Utilities/MemWriter.cs @@ -1,6 +1,6 @@ using ChocolArm64.Memory; -namespace Ryujinx.OsHle.Utilities +namespace Ryujinx.Core.OsHle.Utilities { class MemWriter { diff --git a/Ryujinx.Core/Ryujinx.Core.csproj b/Ryujinx.Core/Ryujinx.Core.csproj new file mode 100644 index 000000000..7d5ad7185 --- /dev/null +++ b/Ryujinx.Core/Ryujinx.Core.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp2.0 + + + + true + + + + true + + + + + + + + diff --git a/Ryujinx/Switch.cs b/Ryujinx.Core/Switch.cs similarity index 54% rename from Ryujinx/Switch.cs rename to Ryujinx.Core/Switch.cs index 4022061bc..2b6a90457 100644 --- a/Ryujinx/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -1,11 +1,11 @@ using ChocolArm64.Memory; -using Gal; -using Ryujinx.Gpu; -using Ryujinx.OsHle; +using Ryujinx.Core.OsHle; +using Ryujinx.Graphics.Gal; +using Ryujinx.Graphics.Gpu; using System; using System.Runtime.InteropServices; -namespace Ryujinx +namespace Ryujinx.Core { public class Switch : IDisposable { @@ -28,6 +28,30 @@ namespace Ryujinx Hid = new Hid(this); } + public void FinalizeAllProcesses() + { + Os.FinalizeAllProcesses(); + } + + public void LoadCart(string ExeFsDir, string RomFsFile = null) + { + Os.LoadCart(ExeFsDir, RomFsFile); + } + + public void LoadProgram(string FileName) + { + Os.LoadProgram(FileName); + } + + public void SendControllerButtons(HidControllerID ControllerId, + HidControllerLayouts Layout, + HidControllerKeys Buttons, + JoystickPosition LeftJoystick, + JoystickPosition RightJoystick) + { + Hid.SendControllerButtons(ControllerId, Layout, Buttons, LeftJoystick, RightJoystick); + } + internal virtual void OnFinish(EventArgs e) { Finish?.Invoke(this, e); diff --git a/Ryujinx/VirtualFs.cs b/Ryujinx.Core/VirtualFs.cs similarity index 98% rename from Ryujinx/VirtualFs.cs rename to Ryujinx.Core/VirtualFs.cs index 98298053f..23c7285c6 100644 --- a/Ryujinx/VirtualFs.cs +++ b/Ryujinx.Core/VirtualFs.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Ryujinx +namespace Ryujinx.Core { class VirtualFs : IDisposable { diff --git a/Ryujinx/Gal/GalPrimitiveType.cs b/Ryujinx.Graphics/Gal/GalPrimitiveType.cs similarity index 95% rename from Ryujinx/Gal/GalPrimitiveType.cs rename to Ryujinx.Graphics/Gal/GalPrimitiveType.cs index 7b6d99a0b..ce084149d 100644 --- a/Ryujinx/Gal/GalPrimitiveType.cs +++ b/Ryujinx.Graphics/Gal/GalPrimitiveType.cs @@ -1,4 +1,4 @@ -namespace Gal +namespace Ryujinx.Graphics.Gal { public enum GalPrimitiveType { diff --git a/Ryujinx/Gal/GalVertexAttrib.cs b/Ryujinx.Graphics/Gal/GalVertexAttrib.cs similarity index 96% rename from Ryujinx/Gal/GalVertexAttrib.cs rename to Ryujinx.Graphics/Gal/GalVertexAttrib.cs index bbc326337..dc38c5934 100644 --- a/Ryujinx/Gal/GalVertexAttrib.cs +++ b/Ryujinx.Graphics/Gal/GalVertexAttrib.cs @@ -1,4 +1,4 @@ -namespace Gal +namespace Ryujinx.Graphics.Gal { public struct GalVertexAttrib { diff --git a/Ryujinx/Gal/GalVertexAttribSize.cs b/Ryujinx.Graphics/Gal/GalVertexAttribSize.cs similarity index 93% rename from Ryujinx/Gal/GalVertexAttribSize.cs rename to Ryujinx.Graphics/Gal/GalVertexAttribSize.cs index 11f0470c2..d3ce60ace 100644 --- a/Ryujinx/Gal/GalVertexAttribSize.cs +++ b/Ryujinx.Graphics/Gal/GalVertexAttribSize.cs @@ -1,4 +1,4 @@ -namespace Gal +namespace Ryujinx.Graphics.Gal { public enum GalVertexAttribSize { diff --git a/Ryujinx/Gal/GalVertexAttribType.cs b/Ryujinx.Graphics/Gal/GalVertexAttribType.cs similarity index 86% rename from Ryujinx/Gal/GalVertexAttribType.cs rename to Ryujinx.Graphics/Gal/GalVertexAttribType.cs index c0ed59fb2..358836fda 100644 --- a/Ryujinx/Gal/GalVertexAttribType.cs +++ b/Ryujinx.Graphics/Gal/GalVertexAttribType.cs @@ -1,4 +1,4 @@ -namespace Gal +namespace Ryujinx.Graphics.Gal { public enum GalVertexAttribType { diff --git a/Ryujinx/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs similarity index 93% rename from Ryujinx/Gal/IGalRenderer.cs rename to Ryujinx.Graphics/Gal/IGalRenderer.cs index 306d0d511..1870aca5b 100644 --- a/Ryujinx/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -1,6 +1,6 @@ using System; -namespace Gal +namespace Ryujinx.Graphics.Gal { public interface IGalRenderer { diff --git a/Ryujinx/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs similarity index 99% rename from Ryujinx/Gal/OpenGL/OpenGLRenderer.cs rename to Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index 72ad6f706..7429569b6 100644 --- a/Ryujinx/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -2,7 +2,7 @@ using OpenTK.Graphics.OpenGL; using System; using System.Collections.Generic; -namespace Gal.OpenGL +namespace Ryujinx.Graphics.Gal.OpenGL { public class OpenGLRenderer : IGalRenderer { diff --git a/Ryujinx/Gpu/BCn.cs b/Ryujinx.Graphics/Gpu/BCn.cs similarity index 99% rename from Ryujinx/Gpu/BCn.cs rename to Ryujinx.Graphics/Gpu/BCn.cs index bf782d167..b1caf4675 100644 --- a/Ryujinx/Gpu/BCn.cs +++ b/Ryujinx.Graphics/Gpu/BCn.cs @@ -1,7 +1,7 @@ using System; using System.Drawing; -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { static class BCn { diff --git a/Ryujinx.Graphics/Gpu/NsGpu.cs b/Ryujinx.Graphics/Gpu/NsGpu.cs new file mode 100644 index 000000000..133d0af25 --- /dev/null +++ b/Ryujinx.Graphics/Gpu/NsGpu.cs @@ -0,0 +1,53 @@ +using ChocolArm64.Memory; +using Ryujinx.Graphics.Gal; + +namespace Ryujinx.Graphics.Gpu +{ + public class NsGpu + { + public IGalRenderer Renderer { get; private set; } + + internal NsGpuMemoryMgr MemoryMgr { get; private set; } + + internal NsGpuPGraph PGraph { get; private set; } + + public NsGpu(IGalRenderer Renderer) + { + this.Renderer = Renderer; + + MemoryMgr = new NsGpuMemoryMgr(); + + PGraph = new NsGpuPGraph(this); + } + + public long GetCpuAddr(long Position) + { + return MemoryMgr.GetCpuAddr(Position); + } + + public long MapMemory(long CpuAddr, long Size) + { + return MemoryMgr.Map(CpuAddr, Size); + } + + public long MapMemory(long CpuAddr, long GpuAddr, long Size) + { + return MemoryMgr.Map(CpuAddr, GpuAddr, Size); + } + + public void ProcessPushBuffer(NsGpuPBEntry[] PushBuffer, AMemory Memory) + { + PGraph.ProcessPushBuffer(PushBuffer, Memory); + } + + public long ReserveMemory(long Size, long Align) + { + return MemoryMgr.Reserve(Size, Align); + } + + public long ReserveMemory(long GpuAddr, long Size, long Align) + { + return MemoryMgr.Reserve(GpuAddr, Size, Align); + } + } +} \ No newline at end of file diff --git a/Ryujinx/Gpu/NsGpuEngine.cs b/Ryujinx.Graphics/Gpu/NsGpuEngine.cs similarity index 87% rename from Ryujinx/Gpu/NsGpuEngine.cs rename to Ryujinx.Graphics/Gpu/NsGpuEngine.cs index bf1045696..118e2b72a 100644 --- a/Ryujinx/Gpu/NsGpuEngine.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuEngine.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { enum NsGpuEngine { diff --git a/Ryujinx/Gpu/NsGpuMemoryMgr.cs b/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs similarity index 99% rename from Ryujinx/Gpu/NsGpuMemoryMgr.cs rename to Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs index 563a5c099..54fabc671 100644 --- a/Ryujinx/Gpu/NsGpuMemoryMgr.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { class NsGpuMemoryMgr { diff --git a/Ryujinx/Gpu/NsGpuPBEntry.cs b/Ryujinx.Graphics/Gpu/NsGpuPBEntry.cs similarity index 97% rename from Ryujinx/Gpu/NsGpuPBEntry.cs rename to Ryujinx.Graphics/Gpu/NsGpuPBEntry.cs index 226a7f61d..8063651aa 100644 --- a/Ryujinx/Gpu/NsGpuPBEntry.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuPBEntry.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { - struct NsGpuPBEntry + public struct NsGpuPBEntry { public NsGpuRegister Register { get; private set; } diff --git a/Ryujinx/Gpu/NsGpuPGraph.cs b/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs similarity index 99% rename from Ryujinx/Gpu/NsGpuPGraph.cs rename to Ryujinx.Graphics/Gpu/NsGpuPGraph.cs index e40b6283e..eb893f74c 100644 --- a/Ryujinx/Gpu/NsGpuPGraph.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuPGraph.cs @@ -1,8 +1,8 @@ using ChocolArm64.Memory; -using Gal; +using Ryujinx.Graphics.Gal; using System.Collections.Generic; -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { class NsGpuPGraph { diff --git a/Ryujinx/Gpu/NsGpuRegister.cs b/Ryujinx.Graphics/Gpu/NsGpuRegister.cs similarity index 98% rename from Ryujinx/Gpu/NsGpuRegister.cs rename to Ryujinx.Graphics/Gpu/NsGpuRegister.cs index 740ca9feb..319e2c01f 100644 --- a/Ryujinx/Gpu/NsGpuRegister.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuRegister.cs @@ -1,6 +1,6 @@ -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { - enum NsGpuRegister + public enum NsGpuRegister { BindChannel = 0, diff --git a/Ryujinx/Gpu/NsGpuTexture.cs b/Ryujinx.Graphics/Gpu/NsGpuTexture.cs similarity index 79% rename from Ryujinx/Gpu/NsGpuTexture.cs rename to Ryujinx.Graphics/Gpu/NsGpuTexture.cs index 26500c04a..aac422005 100644 --- a/Ryujinx/Gpu/NsGpuTexture.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuTexture.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { struct NsGpuTexture { diff --git a/Ryujinx/Gpu/NsGpuTextureFormat.cs b/Ryujinx.Graphics/Gpu/NsGpuTextureFormat.cs similarity index 76% rename from Ryujinx/Gpu/NsGpuTextureFormat.cs rename to Ryujinx.Graphics/Gpu/NsGpuTextureFormat.cs index 9bb122812..2993840be 100644 --- a/Ryujinx/Gpu/NsGpuTextureFormat.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuTextureFormat.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { enum NsGpuTextureFormat { diff --git a/Ryujinx/Gpu/SwizzleAddr.cs b/Ryujinx.Graphics/Gpu/SwizzleAddr.cs similarity index 99% rename from Ryujinx/Gpu/SwizzleAddr.cs rename to Ryujinx.Graphics/Gpu/SwizzleAddr.cs index 5ad35a538..08e61eb58 100644 --- a/Ryujinx/Gpu/SwizzleAddr.cs +++ b/Ryujinx.Graphics/Gpu/SwizzleAddr.cs @@ -1,6 +1,6 @@ using System; -namespace Ryujinx.Gpu +namespace Ryujinx.Graphics.Gpu { class SwizzleAddr { diff --git a/Ryujinx.Graphics/Ryujinx.Graphics.csproj b/Ryujinx.Graphics/Ryujinx.Graphics.csproj new file mode 100644 index 000000000..657beb827 --- /dev/null +++ b/Ryujinx.Graphics/Ryujinx.Graphics.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.0 + + + + + + + + + + + diff --git a/Ryujinx.sln b/Ryujinx.sln index 777539885..34a5f4887 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -1,11 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26730.8 +VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx", "Ryujinx\Ryujinx.csproj", "{074045D4-3ED2-4711-9169-E385F2BFB5A0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "Ryujinx\Ryujinx.csproj", "{074045D4-3ED2-4711-9169-E385F2BFB5A0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Tests", "Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests", "Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Core", "Ryujinx.Core\Ryujinx.Core.csproj", "{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChocolArm64", "ChocolArm64\ChocolArm64.csproj", "{2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics", "Ryujinx.Graphics\Ryujinx.Graphics.csproj", "{EAAE36AF-7781-4578-A7E0-F0EFD2025569}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +27,18 @@ Global {EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU {EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU {EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU + {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.Build.0 = Release|Any CPU + {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2345A1A7-8DEF-419B-9AFB-4DFD41D20D05}.Release|Any CPU.Build.0 = Release|Any CPU + {EAAE36AF-7781-4578-A7E0-F0EFD2025569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EAAE36AF-7781-4578-A7E0-F0EFD2025569}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EAAE36AF-7781-4578-A7E0-F0EFD2025569}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EAAE36AF-7781-4578-A7E0-F0EFD2025569}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Ryujinx/Gpu/NsGpu.cs b/Ryujinx/Gpu/NsGpu.cs deleted file mode 100644 index 6aa7332cd..000000000 --- a/Ryujinx/Gpu/NsGpu.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Gal; - -namespace Ryujinx.Gpu -{ - class NsGpu - { - public IGalRenderer Renderer { get; private set; } - - public NsGpuMemoryMgr MemoryMgr { get; private set; } - - public NsGpuPGraph PGraph { get; private set; } - - public NsGpu(IGalRenderer Renderer) - { - this.Renderer = Renderer; - - MemoryMgr = new NsGpuMemoryMgr(); - - PGraph = new NsGpuPGraph(this); - } - } -} \ No newline at end of file diff --git a/Ryujinx/OsHle/Handles/HEvent.cs b/Ryujinx/OsHle/Handles/HEvent.cs deleted file mode 100644 index d9d0ff4c2..000000000 --- a/Ryujinx/OsHle/Handles/HEvent.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.OsHle.Handles -{ - class HEvent - { - - } -} \ No newline at end of file diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj index 9b0e7396a..bc5dbe042 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -9,6 +9,11 @@ + + + + + PreserveNewest diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 8101648ea..9c05953bf 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -2,10 +2,11 @@ // to the Public Domain. // It is provided "as is" without express or implied warranty of any kind. -using Gal; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using Ryujinx.Core; +using Ryujinx.Graphics.Gal; using System; namespace Ryujinx @@ -346,7 +347,7 @@ void main(void) { }; //We just need one pair of JoyCon because it's emulate by the keyboard. - Ns.Hid.SendControllerButtons(HidControllerID.CONTROLLER_HANDHELD, HidControllerLayouts.Main, CurrentButton, LeftJoystick, RightJoystick); + Ns.SendControllerButtons(HidControllerID.CONTROLLER_HANDHELD, HidControllerLayouts.Main, CurrentButton, LeftJoystick, RightJoystick); } protected override void OnRenderFrame(FrameEventArgs e) diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs index 2f29411a9..7912147ee 100644 --- a/Ryujinx/Ui/Program.cs +++ b/Ryujinx/Ui/Program.cs @@ -1,5 +1,6 @@ -using Gal; -using Gal.OpenGL; +using Ryujinx.Core; +using Ryujinx.Graphics.Gal; +using Ryujinx.Graphics.Gal.OpenGL; using System; using System.IO; @@ -27,20 +28,20 @@ namespace Ryujinx { Logging.Info("Loading as cart with RomFS."); - Ns.Os.LoadCart(args[0], RomFsFiles[0]); + Ns.LoadCart(args[0], RomFsFiles[0]); } else { Logging.Info("Loading as cart WITHOUT RomFS."); - Ns.Os.LoadCart(args[0]); + Ns.LoadCart(args[0]); } } else if (File.Exists(args[0])) { Logging.Info("Loading as homebrew."); - Ns.Os.LoadProgram(args[0]); + Ns.LoadProgram(args[0]); } } else @@ -58,7 +59,7 @@ namespace Ryujinx Screen.Run(60.0); } - Ns.Os.FinalizeAllProcesses(); + Ns.FinalizeAllProcesses(); Ns.Dispose(); } From fed74be81d2647c0ea1ee22dbd7204c5930a47e6 Mon Sep 17 00:00:00 2001 From: Hexagon12 Date: Tue, 20 Feb 2018 22:10:03 +0200 Subject: [PATCH 08/67] Fix various typos in the Readme (#31) * Fix some typos * Fix even more typos --- README.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f39d2f029..975b23406 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Experimental Switch emulator written in C# -Don't expect much from this. Some homebrew apps works, and Tetris shows the intro logos (sometimes) but that's about it for now. +Don't expect much from this. Some homebrew apps work, and Puyo Puyo Tetris shows the intro logo (sometimes) but that's about it for now. Contributions are always welcome. **Building** @@ -10,7 +10,7 @@ Contributions are always welcome. To build this emulator, you need the .NET Core 2.0 (or higher) SDK. https://www.microsoft.com/net/download/ In release builds, memory checks are disabled to improve performances. -Or just drag'n'drop the *.NRO or the game folder on the executable if you have a pre-build version. +Or just drag'n'drop the *.NRO / *.NSO or the game folder on the executable if you have a pre-build version. **Features** @@ -41,11 +41,11 @@ https://openal.org/downloads/OpenAL11CoreSDK.zip **Help** -If you have some homebrews that currently doesn't work on it, you can contact us through discord with the compiled NRO/NSO (and source code if possible) and will work to make them work. +If you have some homebrew that currently don't work on the emulator, you can contact us through Discord with the compiled NRO/NSO (and source code if possible) and then we'll make changes to make the requested app / game work. **Contact** -For help, support, suggestion, or if you just want to get in touch with the team, join our Discord server! +For help, support, suggestions, or if you just want to get in touch with the team, join our Discord server! https://discord.gg/VkQYXAZ **Running** @@ -54,10 +54,7 @@ To run this emulator, you need the .NET Core 2.0 (or higher) SDK. Run `dotnet run -c Release -- path\to\homebrew.nro` inside the Ryujinx solution folder to run homebrew apps. Run `dotnet run -c Release -- path\to\game_exefs_and_romfs_folder` to run official games (they need to be decrypted and extracted first!). -Audio is partially supported (glitched) on Linux and macOS, for Windows you need to install the OpenAL Core SDK: -https://openal.org/downloads/OpenAL11CoreSDK.zip +**Latest build** -**Lastest build** - -Those builds are compiled automatically for each commit on the master branch. They may be unstable or not work at all. -To download the lastest automatic build for Windows (64-bits), [Click Here](https://ci.appveyor.com/api/projects/gdkchan/ryujinx/artifacts/ryujinx_lastest_unstable.zip). +These builds are compiled automatically for each commit on the master branch. They may be unstable or not work at all. +To download the latest automatic build for Windows (64-bits), [Click Here](https://ci.appveyor.com/api/projects/gdkchan/ryujinx/artifacts/ryujinx_lastest_unstable.zip). From 3696255457dce06111ce5a07544d30239366ebf6 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 20 Feb 2018 17:19:00 -0300 Subject: [PATCH 09/67] Add ChocolArm64 reference to Ryujinx.Tests --- Ryujinx.Tests/Ryujinx.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ryujinx.Tests/Ryujinx.Tests.csproj b/Ryujinx.Tests/Ryujinx.Tests.csproj index f8b430e62..ae4ea6c33 100644 --- a/Ryujinx.Tests/Ryujinx.Tests.csproj +++ b/Ryujinx.Tests/Ryujinx.Tests.csproj @@ -12,6 +12,6 @@ - + From b2f733da7839ff8ba7a70a529cb9eb3eea9f0af6 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 21 Feb 2018 18:56:52 -0300 Subject: [PATCH 10/67] FspSrv improvements, also fix ImageEnd for NROs without a MOD0 section --- Ryujinx.Core/Loaders/Executable.cs | 7 +- Ryujinx.Core/OsHle/Ipc/IpcHandler.cs | 14 +- Ryujinx.Core/OsHle/Objects/ErrorCode.cs | 12 + Ryujinx.Core/OsHle/Objects/ErrorModule.cs | 7 + Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs | 9 + .../OsHle/Objects/FspSrv/IDirectory.cs | 154 ++++----- Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs | 30 +- .../OsHle/Objects/FspSrv/IFileSystem.cs | 317 ++++++++++++------ .../Objects/Hid/IActiveVibrationDeviceList.cs | 18 + .../OsHle/Objects/Hid/IAppletResource.cs | 2 +- Ryujinx.Core/OsHle/Services/ServiceHid.cs | 21 ++ Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 2 +- Ryujinx.Core/VirtualFs.cs | 9 +- Ryujinx/Ui/GLScreen.cs | 2 +- 14 files changed, 408 insertions(+), 196 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Objects/ErrorCode.cs create mode 100644 Ryujinx.Core/OsHle/Objects/ErrorModule.cs create mode 100644 Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs create mode 100644 Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index 6a6073ef2..e26608389 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -26,7 +26,12 @@ namespace Ryujinx.Core.Loaders if (Exe.Mod0Offset == 0) { - MapBss(ImageBase + Exe.DataOffset + Exe.Data.Count, Exe.BssSize); + int BssOffset = Exe.DataOffset + Exe.Data.Count; + int BssSize = Exe.BssSize; + + MapBss(ImageBase + BssOffset, BssSize); + + ImageEnd = ImageBase + BssOffset + BssSize; return; } diff --git a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs index deab88969..612d15eb0 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs @@ -34,9 +34,12 @@ namespace Ryujinx.Core.OsHle.Ipc { ( "hid", 0), Service.HidCreateAppletResource }, { ( "hid", 11), Service.HidActivateTouchScreen }, { ( "hid", 100), Service.HidSetSupportedNpadStyleSet }, + { ( "hid", 101), Service.HidGetSupportedNpadStyleSet }, { ( "hid", 102), Service.HidSetSupportedNpadIdType }, { ( "hid", 103), Service.HidActivateNpad }, { ( "hid", 120), Service.HidSetNpadJoyHoldType }, + { ( "hid", 121), Service.HidGetNpadJoyHoldType }, + { ( "hid", 203), Service.HidCreateActiveVibrationDeviceList }, { ( "lm", 0), Service.LmInitialize }, { ( "nvdrv", 0), Service.NvDrvOpen }, { ( "nvdrv", 1), Service.NvDrvIoctl }, @@ -79,6 +82,7 @@ namespace Ryujinx.Core.OsHle.Ipc AMemory Memory, HSession Session, IpcMessage Request, + int ThreadId, long CmdPtr, int HndId) { @@ -111,13 +115,13 @@ namespace Ryujinx.Core.OsHle.Ipc { ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq); - DbgServiceName = $"{ServiceName} {ProcReq?.Method.Name ?? CmdId.ToString()}"; + DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}"; } else if (Obj != null) { ((IIpcInterface)Obj).Commands.TryGetValue(CmdId, out ProcReq); - DbgServiceName = $"{ServiceName} {Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}"; + DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}"; } } else if (Request.DomCmd == IpcDomCmd.DeleteObj) @@ -140,16 +144,18 @@ namespace Ryujinx.Core.OsHle.Ipc ((IIpcInterface)Obj).Commands.TryGetValue(CmdId, out ProcReq); - DbgServiceName = $"{ServiceName} {Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}"; + DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}"; } else { ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq); - DbgServiceName = $"{ServiceName} {ProcReq?.Method.Name ?? CmdId.ToString()}"; + DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}"; } } + DbgServiceName = $"Tid {ThreadId} {ServiceName} {DbgServiceName}"; + Logging.Debug($"IpcMessage: {DbgServiceName}"); if (ProcReq != null) diff --git a/Ryujinx.Core/OsHle/Objects/ErrorCode.cs b/Ryujinx.Core/OsHle/Objects/ErrorCode.cs new file mode 100644 index 000000000..20f97f848 --- /dev/null +++ b/Ryujinx.Core/OsHle/Objects/ErrorCode.cs @@ -0,0 +1,12 @@ +using System; + +namespace Ryujinx.Core.OsHle.Objects +{ + static class ErrorCode + { + public static long MakeError(ErrorModule Module, int Code) + { + return (int)Module | (Code << 9); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/ErrorModule.cs b/Ryujinx.Core/OsHle/Objects/ErrorModule.cs new file mode 100644 index 000000000..0221031b4 --- /dev/null +++ b/Ryujinx.Core/OsHle/Objects/ErrorModule.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.Core.OsHle.Objects +{ + enum ErrorModule + { + Fs = 2, + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs new file mode 100644 index 000000000..d9aa60ae7 --- /dev/null +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs @@ -0,0 +1,9 @@ +namespace Ryujinx.Core.OsHle.Objects.FspSrv +{ + static class FsErr + { + public const int PathDoesNotExist = 1; + public const int PathAlreadyExists = 2; + public const int PathAlreadyInUse = 7; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs index 88fce28eb..785b1ba38 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs @@ -3,131 +3,115 @@ using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Runtime.InteropServices; using System.Text; namespace Ryujinx.Core.OsHle.Objects.FspSrv { - [StructLayout(LayoutKind.Sequential, Size = 0x310)] - struct DirectoryEntry + class IDirectory : IIpcInterface, IDisposable { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x300)] - public byte[] Name; - public int Unknown; - public byte Type; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x3)] - public byte[] Padding; - public long Size; - } + private const int DirectoryEntrySize = 0x310; - enum DirectoryEntryType - { - Directory, - File - } - - class IDirectory : IIpcInterface - { - private List DirectoryEntries = new List(); private Dictionary m_Commands; public IReadOnlyDictionary Commands => m_Commands; - private string HostPath; + private List DirectoryEntries; - public IDirectory(string HostPath, int flags) + private int CurrentItemIndex; + + public event EventHandler Disposed; + + public string HostPath { get; private set; } + + public IDirectory(string HostPath, int Flags) { m_Commands = new Dictionary() { - { 0, Read }, - { 1, GetEntryCount } + { 0, Read }, + { 1, GetEntryCount } }; this.HostPath = HostPath; - if ((flags & 1) == 1) + DirectoryEntries = new List(); + + if ((Flags & 1) != 0) { - string[] Directories = Directory.GetDirectories(HostPath, "*", SearchOption.TopDirectoryOnly). - Where(x => (new FileInfo(x).Attributes & FileAttributes.Hidden) == 0).ToArray(); - - foreach (string Directory in Directories) - { - DirectoryEntry Info = new DirectoryEntry - { - Name = Encoding.UTF8.GetBytes(Directory), - Type = (byte)DirectoryEntryType.Directory, - Size = 0 - }; - - Array.Resize(ref Info.Name, 0x300); - DirectoryEntries.Add(Info); - } + DirectoryEntries.AddRange(Directory.GetDirectories(HostPath)); } - if ((flags & 2) == 2) + if ((Flags & 2) != 0) { - string[] Files = Directory.GetFiles(HostPath, "*", SearchOption.TopDirectoryOnly). - Where(x => (new FileInfo(x).Attributes & FileAttributes.Hidden) == 0).ToArray(); - - foreach (string FileName in Files) - { - DirectoryEntry Info = new DirectoryEntry - { - Name = Encoding.UTF8.GetBytes(Path.GetFileName(FileName)), - Type = (byte)DirectoryEntryType.File, - Size = new FileInfo(Path.Combine(HostPath, FileName)).Length - }; - - Array.Resize(ref Info.Name, 0x300); - DirectoryEntries.Add(Info); - } + DirectoryEntries.AddRange(Directory.GetFiles(HostPath)); } + + CurrentItemIndex = 0; } - private int LastItem = 0; public long Read(ServiceCtx Context) { long BufferPosition = Context.Request.ReceiveBuff[0].Position; - long BufferLen = Context.Request.ReceiveBuff[0].Size; - long MaxDirectories = BufferLen / Marshal.SizeOf(typeof(DirectoryEntry)); + long BufferLen = Context.Request.ReceiveBuff[0].Size; - if (MaxDirectories > DirectoryEntries.Count - LastItem) + int MaxReadCount = (int)(BufferLen / DirectoryEntrySize); + + int Count = Math.Min(DirectoryEntries.Count - CurrentItemIndex, MaxReadCount); + + for (int Index = 0; Index < Count; Index++) { - MaxDirectories = DirectoryEntries.Count - LastItem; + long Position = BufferPosition + Index * DirectoryEntrySize; + + WriteDirectoryEntry(Context, Position, DirectoryEntries[CurrentItemIndex++]); } - int CurrentIndex; - for (CurrentIndex = 0; CurrentIndex < MaxDirectories; CurrentIndex++) - { - int CurrentItem = LastItem + CurrentIndex; - - byte[] DirectoryEntry = new byte[Marshal.SizeOf(typeof(DirectoryEntry))]; - IntPtr Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DirectoryEntry))); - Marshal.StructureToPtr(DirectoryEntries[CurrentItem], Ptr, true); - Marshal.Copy(Ptr, DirectoryEntry, 0, Marshal.SizeOf(typeof(DirectoryEntry))); - Marshal.FreeHGlobal(Ptr); - - AMemoryHelper.WriteBytes(Context.Memory, BufferPosition + Marshal.SizeOf(typeof(DirectoryEntry)) * CurrentIndex, DirectoryEntry); - } - - if (LastItem < DirectoryEntries.Count) - { - LastItem += CurrentIndex; - Context.ResponseData.Write((long)CurrentIndex); // index = number of entries written this call. - } - else - { - Context.ResponseData.Write((long)0); - } + Context.ResponseData.Write((long)Count); return 0; } + private void WriteDirectoryEntry(ServiceCtx Context, long Position, string FullPath) + { + for (int Offset = 0; Offset < 0x300; Offset += 8) + { + Context.Memory.WriteInt64(Position + Offset, 0); + } + + byte[] NameBuffer = Encoding.UTF8.GetBytes(Path.GetFileName(FullPath)); + + AMemoryHelper.WriteBytes(Context.Memory, Position, NameBuffer); + + int Type = 0; + long Size = 0; + + if (File.Exists(FullPath)) + { + Type = 1; + Size = new FileInfo(FullPath).Length; + } + + Context.Memory.WriteInt32(Position + 0x300, 0); //Padding? + Context.Memory.WriteInt32(Position + 0x304, Type); + Context.Memory.WriteInt64(Position + 0x308, Size); + } + public long GetEntryCount(ServiceCtx Context) { Context.ResponseData.Write((long)DirectoryEntries.Count); + return 0; } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + Disposed?.Invoke(this, EventArgs.Empty); + } + } } } diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs index 95fbc650f..82706f609 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs @@ -14,18 +14,23 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv private Stream BaseStream; - public IFile(Stream BaseStream) + public event EventHandler Disposed; + + public string HostPath { get; private set; } + + public IFile(Stream BaseStream, string HostPath) { m_Commands = new Dictionary() { - { 0, Read }, - { 1, Write }, - // { 2, Flush }, + { 0, Read }, + { 1, Write }, + { 2, Flush }, { 3, SetSize }, { 4, GetSize } }; this.BaseStream = BaseStream; + this.HostPath = HostPath; } public long Read(ServiceCtx Context) @@ -39,6 +44,7 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv byte[] Data = new byte[Size]; BaseStream.Seek(Offset, SeekOrigin.Begin); + int ReadSize = BaseStream.Read(Data, 0, (int)Size); AMemoryHelper.WriteBytes(Context.Memory, Position, Data); @@ -64,16 +70,26 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv return 0; } - public long GetSize(ServiceCtx Context) + public long Flush(ServiceCtx Context) { - Context.ResponseData.Write(BaseStream.Length); + BaseStream.Flush(); + return 0; } public long SetSize(ServiceCtx Context) { long Size = Context.RequestData.ReadInt64(); + BaseStream.SetLength(Size); + + return 0; + } + + public long GetSize(ServiceCtx Context) + { + Context.ResponseData.Write(BaseStream.Length); + return 0; } @@ -87,6 +103,8 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv if (disposing && BaseStream != null) { BaseStream.Dispose(); + + Disposed?.Invoke(this, EventArgs.Empty); } } } diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs index 68b158452..e18c1dafd 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs @@ -1,8 +1,10 @@ using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Ipc; +using System; using System.Collections.Generic; using System.IO; +using static Ryujinx.Core.OsHle.Objects.ErrorCode; using static Ryujinx.Core.OsHle.Objects.ObjHelper; namespace Ryujinx.Core.OsHle.Objects.FspSrv @@ -13,153 +15,214 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv public IReadOnlyDictionary Commands => m_Commands; + private HashSet OpenPaths; + private string Path; public IFileSystem(string Path) { - //TODO: implement. m_Commands = new Dictionary() { - { 0, CreateFile }, - { 1, DeleteFile }, - { 2, CreateDirectory }, - { 3, DeleteDirectory }, + { 0, CreateFile }, + { 1, DeleteFile }, + { 2, CreateDirectory }, + { 3, DeleteDirectory }, { 4, DeleteDirectoryRecursively }, - { 5, RenameFile }, - { 6, RenameDirectory }, - { 7, GetEntryType }, - { 8, OpenFile }, - { 9, OpenDirectory }, - { 10, Commit }, - //{ 11, GetFreeSpaceSize }, - //{ 12, GetTotalSpaceSize }, - //{ 13, CleanDirectoryRecursively }, - //{ 14, GetFileTimeStampRaw } + { 5, RenameFile }, + { 6, RenameDirectory }, + { 7, GetEntryType }, + { 8, OpenFile }, + { 9, OpenDirectory }, + { 10, Commit }, + { 11, GetFreeSpaceSize }, + { 12, GetTotalSpaceSize }, + //{ 13, CleanDirectoryRecursively }, + //{ 14, GetFileTimeStampRaw } }; + OpenPaths = new HashSet(); + this.Path = Path; } public long CreateFile(ServiceCtx Context) { long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - ulong Mode = Context.RequestData.ReadUInt64(); - uint Size = Context.RequestData.ReadUInt32(); + + long Mode = Context.RequestData.ReadInt64(); + int Size = Context.RequestData.ReadInt32(); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName != null) + if (FileName == null) { - FileStream NewFile = File.Create(FileName); - NewFile.SetLength(Size); - NewFile.Close(); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - //TODO: Correct error code. - return -1; + if (File.Exists(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + using (FileStream NewFile = File.Create(FileName)) + { + NewFile.SetLength(Size); + } + + return 0; } public long DeleteFile(ServiceCtx Context) { long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName != null) + if (!File.Exists(FileName)) { - File.Delete(FileName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - //TODO: Correct error code. - return -1; + if (IsPathAlreadyInUse(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + File.Delete(FileName); + + return 0; } public long CreateDirectory(ServiceCtx Context) { long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName != null) + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string DirName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (DirName == null) { - Directory.CreateDirectory(FileName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - //TODO: Correct error code. - return -1; + if (Directory.Exists(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + Directory.CreateDirectory(DirName); + + return 0; } public long DeleteDirectory(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - - if (FileName != null) - { - Directory.Delete(FileName); - return 0; - } - - // TODO: Correct error code. - return -1; + return DeleteDirectory(Context, false); } public long DeleteDirectoryRecursively(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + return DeleteDirectory(Context, true); + } - if (FileName != null) + private long DeleteDirectory(ServiceCtx Context, bool Recursive) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string DirName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (!Directory.Exists(DirName)) { - Directory.Delete(FileName, true); // recursive = true - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - // TODO: Correct error code. - return -1; + if (IsPathAlreadyInUse(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + Directory.Delete(DirName, Recursive); + + return 0; } public long RenameFile(ServiceCtx Context) { long OldPosition = Context.Request.PtrBuff[0].Position; long NewPosition = Context.Request.PtrBuff[0].Position; + string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + string OldFileName = Context.Ns.VFs.GetFullPath(Path, OldName); string NewFileName = Context.Ns.VFs.GetFullPath(Path, NewName); - if (OldFileName != null && NewFileName != null) + if (!File.Exists(OldFileName)) { - File.Move(OldFileName, NewFileName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - // TODO: Correct error code. - return -1; + if (File.Exists(NewFileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(OldFileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + File.Move(OldFileName, NewFileName); + + return 0; } public long RenameDirectory(ServiceCtx Context) { long OldPosition = Context.Request.PtrBuff[0].Position; long NewPosition = Context.Request.PtrBuff[0].Position; + string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + string OldDirName = Context.Ns.VFs.GetFullPath(Path, OldName); string NewDirName = Context.Ns.VFs.GetFullPath(Path, NewName); - if (OldDirName != null && NewDirName != null) + if (!Directory.Exists(OldDirName)) { - Directory.Move(OldDirName, NewDirName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - // TODO: Correct error code. - return -1; + if (Directory.Exists(NewDirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(OldDirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + Directory.Move(OldDirName, NewDirName); + + return 0; } public long GetEntryType(ServiceCtx Context) @@ -170,15 +233,20 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName == null) + if (File.Exists(FileName)) { - //TODO: Correct error code. - return -1; + Context.ResponseData.Write(1); } + else if (Directory.Exists(FileName)) + { + Context.ResponseData.Write(0); + } + else + { + Context.ResponseData.Write(0); - bool IsFile = File.Exists(FileName); - - Context.ResponseData.Write(IsFile ? 1 : 0); + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } return 0; } @@ -193,22 +261,21 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName == null) + if (!File.Exists(FileName)) { - //TODO: Correct error code. - return -1; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - if (File.Exists(FileName)) + if (IsPathAlreadyInUse(FileName)) { - FileStream Stream = new FileStream(FileName, FileMode.OpenOrCreate); - MakeObject(Context, new IFile(Stream)); - - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); } - //TODO: Correct error code. - return -1; + FileStream Stream = new FileStream(FileName, FileMode.Open); + + MakeObject(Context, new IFile(Stream, FileName)); + + return 0; } public long OpenDirectory(ServiceCtx Context) @@ -221,27 +288,87 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv string DirName = Context.Ns.VFs.GetFullPath(Path, Name); - if(DirName != null) + if (!Directory.Exists(DirName)) { - if (Directory.Exists(DirName)) - { - MakeObject(Context, new IDirectory(DirName, FilterFlags)); - return 0; - } - else - { - // TODO: correct error code. - return -1; - } + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - // TODO: Correct error code. - return -1; + if (IsPathAlreadyInUse(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + IDirectory DirInterface = new IDirectory(DirName, FilterFlags); + + DirInterface.Disposed += RemoveDirectoryInUse; + + lock (OpenPaths) + { + OpenPaths.Add(DirName); + } + + MakeObject(Context, DirInterface); + + return 0; } public long Commit(ServiceCtx Context) { return 0; } + + public long GetFreeSpaceSize(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + Context.ResponseData.Write(Context.Ns.VFs.GetDrive().AvailableFreeSpace); + + return 0; + } + + public long GetTotalSpaceSize(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + Context.ResponseData.Write(Context.Ns.VFs.GetDrive().TotalSize); + + return 0; + } + + private bool IsPathAlreadyInUse(string Path) + { + lock (OpenPaths) + { + return OpenPaths.Contains(Path); + } + } + + private void RemoveFileInUse(object sender, EventArgs e) + { + IFile FileInterface = (IFile)sender; + + lock (OpenPaths) + { + FileInterface.Disposed -= RemoveDirectoryInUse; + + OpenPaths.Remove(FileInterface.HostPath); + } + } + + private void RemoveDirectoryInUse(object sender, EventArgs e) + { + IDirectory DirInterface = (IDirectory)sender; + + lock (OpenPaths) + { + DirInterface.Disposed -= RemoveDirectoryInUse; + + OpenPaths.Remove(DirInterface.HostPath); + } + } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs b/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs new file mode 100644 index 000000000..1f0c8592a --- /dev/null +++ b/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs @@ -0,0 +1,18 @@ +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.Objects.Hid +{ + class IActiveApplicationDeviceList : IIpcInterface + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IActiveApplicationDeviceList() + { + m_Commands = new Dictionary() { }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs index d6e8947bb..7d56d04ba 100644 --- a/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs +++ b/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs @@ -10,7 +10,7 @@ namespace Ryujinx.Core.OsHle.Objects.Hid public IReadOnlyDictionary Commands => m_Commands; - public HSharedMem Handle; + private HSharedMem Handle; public IAppletResource(HSharedMem Handle) { diff --git a/Ryujinx.Core/OsHle/Services/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/ServiceHid.cs index 4b2e82ffb..aed3e959c 100644 --- a/Ryujinx.Core/OsHle/Services/ServiceHid.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceHid.cs @@ -23,6 +23,13 @@ namespace Ryujinx.Core.OsHle.Services return 0; } + public static long HidGetSupportedNpadStyleSet(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + return 0; + } + public static long HidSetSupportedNpadStyleSet(ServiceCtx Context) { long Unknown0 = Context.RequestData.ReadInt64(); @@ -52,5 +59,19 @@ namespace Ryujinx.Core.OsHle.Services return 0; } + + public static long HidGetNpadJoyHoldType(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + + return 0; + } + + public static long HidCreateActiveVibrationDeviceList(ServiceCtx Context) + { + MakeObject(Context, new IActiveApplicationDeviceList()); + + return 0; + } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index 7f593c8f2..40369b995 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -106,7 +106,7 @@ namespace Ryujinx.Core.OsHle.Svc if (Session != null) { - IpcHandler.IpcCall(Ns, Memory, Session, Cmd, CmdPtr, Handle); + IpcHandler.IpcCall(Ns, Memory, Session, Cmd, ThreadState.ThreadId, CmdPtr, Handle); byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size); diff --git a/Ryujinx.Core/VirtualFs.cs b/Ryujinx.Core/VirtualFs.cs index 23c7285c6..0c9111165 100644 --- a/Ryujinx.Core/VirtualFs.cs +++ b/Ryujinx.Core/VirtualFs.cs @@ -37,7 +37,7 @@ namespace Ryujinx.Core public string GetGameSavesPath() => MakeDirAndGetFullPath(SavesPath); - private static string MakeDirAndGetFullPath(string Dir) + private string MakeDirAndGetFullPath(string Dir) { string FullPath = Path.Combine(GetBasePath(), Dir); @@ -49,7 +49,12 @@ namespace Ryujinx.Core return FullPath; } - public static string GetBasePath() + public DriveInfo GetDrive() + { + return new DriveInfo(Path.GetPathRoot(GetBasePath())); + } + + public string GetBasePath() { return Path.Combine(Directory.GetCurrentDirectory(), BasePath); } diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 9c05953bf..a100080e0 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -154,7 +154,7 @@ vec3 get_scale_ratio() { (window_size.y * native_size.x) / (native_size.y * window_size.x), (window_size.x * native_size.y) / (native_size.x * window_size.y) ); - return vec3(min(ratio, vec2(1, 1)), 1); + return vec3(min(ratio, vec2(1, 1)) * vec2(1, -1), 1); } void main(void) { From 224211367f52cf514f0608d69056e84a3ef37ff5 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Thu, 22 Feb 2018 01:51:17 +0100 Subject: [PATCH 11/67] Initiale hbmenu.nro support (#32) * Initiale hbmenu.nro support Implement missing SetScreenShotPermission object. Implement missing IsCurrentProcessBeingDebugged in SVC. Add a Extension variable to Executable. Add basic support of hbmenu.nro. * Homebrew.cs correction --- Ryujinx.Core/Loaders/Executable.cs | 3 + .../Loaders/Executables/IExecutable.cs | 8 ++ Ryujinx.Core/Loaders/Executables/Nro.cs | 4 + Ryujinx.Core/Loaders/Executables/Nso.cs | 4 + Ryujinx.Core/OsHle/Homebrew.cs | 34 ++++++++ .../OsHle/Objects/Am/ISelfController.cs | 8 ++ Ryujinx.Core/OsHle/Process.cs | 7 ++ Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 78 ++++++++++--------- 8 files changed, 110 insertions(+), 36 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Homebrew.cs diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index e26608389..25a621362 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -13,6 +13,7 @@ namespace Ryujinx.Core.Loaders public long ImageBase { get; private set; } public long ImageEnd { get; private set; } + public Extensions Extension { get; private set; } public Executable(IExecutable Exe, AMemory Memory, long ImageBase) { @@ -46,6 +47,8 @@ namespace Ryujinx.Core.Loaders long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset; long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset; + Extension = Exe.Extension; + MapBss(BssStartOffset, BssEndOffset - BssStartOffset); ImageEnd = BssEndOffset; diff --git a/Ryujinx.Core/Loaders/Executables/IExecutable.cs b/Ryujinx.Core/Loaders/Executables/IExecutable.cs index 73787b1d2..f6aa31aca 100644 --- a/Ryujinx.Core/Loaders/Executables/IExecutable.cs +++ b/Ryujinx.Core/Loaders/Executables/IExecutable.cs @@ -2,6 +2,12 @@ using System.Collections.ObjectModel; namespace Ryujinx.Core.Loaders.Executables { + public enum Extensions + { + NRO, + NSO + } + public interface IExecutable { ReadOnlyCollection Text { get; } @@ -13,5 +19,7 @@ namespace Ryujinx.Core.Loaders.Executables int ROOffset { get; } int DataOffset { get; } int BssSize { get; } + + Extensions Extension { get; } } } \ No newline at end of file diff --git a/Ryujinx.Core/Loaders/Executables/Nro.cs b/Ryujinx.Core/Loaders/Executables/Nro.cs index 3cbc4c5d4..7f492cc2b 100644 --- a/Ryujinx.Core/Loaders/Executables/Nro.cs +++ b/Ryujinx.Core/Loaders/Executables/Nro.cs @@ -20,6 +20,8 @@ namespace Ryujinx.Core.Loaders.Executables public int DataOffset { get; private set; } public int BssSize { get; private set; } + public Extensions Extension { get; private set; } + public Nro(Stream Input) { BinaryReader Reader = new BinaryReader(Input); @@ -47,6 +49,8 @@ namespace Ryujinx.Core.Loaders.Executables this.DataOffset = DataOffset; this.BssSize = BssSize; + this.Extension = Extensions.NRO; + byte[] Read(long Position, int Size) { Input.Seek(Position, SeekOrigin.Begin); diff --git a/Ryujinx.Core/Loaders/Executables/Nso.cs b/Ryujinx.Core/Loaders/Executables/Nso.cs index 7b8bf253a..63ae08aea 100644 --- a/Ryujinx.Core/Loaders/Executables/Nso.cs +++ b/Ryujinx.Core/Loaders/Executables/Nso.cs @@ -21,6 +21,8 @@ namespace Ryujinx.Core.Loaders.Executables public int DataOffset { get; private set; } public int BssSize { get; private set; } + public Extensions Extension { get; private set; } + [Flags] private enum NsoFlags { @@ -79,6 +81,8 @@ namespace Ryujinx.Core.Loaders.Executables this.DataOffset = DataMemOffset; this.BssSize = BssSize; + this.Extension = Extensions.NSO; + //Text segment Input.Seek(TextOffset, SeekOrigin.Begin); diff --git a/Ryujinx.Core/OsHle/Homebrew.cs b/Ryujinx.Core/OsHle/Homebrew.cs new file mode 100644 index 000000000..b69b31c99 --- /dev/null +++ b/Ryujinx.Core/OsHle/Homebrew.cs @@ -0,0 +1,34 @@ +using ChocolArm64.Memory; + +namespace Ryujinx.Core.OsHle +{ + public class Homebrew + { + //http://switchbrew.org/index.php?title=Homebrew_ABI + public Homebrew(AMemory Memory, long Position, long MainThreadHandle) + { + //(NbrKeys * LoaderConfigEntrySize) + 2 buffers for Key2 + long Size = (4 * 0x18) + 0x1000; + Memory.Manager.MapPhys(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW); + + //MainThreadHandle + WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle); + //NextLoadPath + WriteConfigEntry(Memory, ref Position, 2, 0, Position + Size, Position + Size + 0x200); + //AppletType + WriteConfigEntry(Memory, ref Position, 7); + //EndOfList + WriteConfigEntry(Memory, ref Position, 0); + } + + private void WriteConfigEntry(AMemory Memory, ref long Position, int Key, int Flags = 0, long Value0 = 0L, long Value1 = 0L) + { + Memory.WriteInt32(Position + 0x00, Key); + Memory.WriteInt32(Position + 0x04, Flags); + Memory.WriteInt64(Position + 0x08, Value0); + Memory.WriteInt64(Position + 0x10, Value1); + + Position += 0x18; + } + } +} diff --git a/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs b/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs index 691bb202f..712874e87 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs +++ b/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs @@ -13,6 +13,7 @@ namespace Ryujinx.Core.OsHle.Objects.Am { m_Commands = new Dictionary() { + { 10, SetScreenShotPermission }, { 11, SetOperationModeChangedNotification }, { 12, SetPerformanceModeChangedNotification }, { 13, SetFocusHandlingMode }, @@ -20,6 +21,13 @@ namespace Ryujinx.Core.OsHle.Objects.Am }; } + public long SetScreenShotPermission(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + public long SetOperationModeChangedNotification(ServiceCtx Context) { bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index 842678859..022dc0f9a 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -186,6 +186,13 @@ namespace Ryujinx.Core.OsHle Thread.ThreadState.X1 = (ulong)Handle; Thread.ThreadState.X31 = (ulong)StackTop; + if (Executables[0].Extension == Extensions.NRO) + { + Homebrew Homebrew_ABI = new Homebrew(Memory, Executables[0].ImageEnd, (long)Handle); + Thread.ThreadState.X0 = (ulong)Executables[0].ImageEnd; + Thread.ThreadState.X1 = 0xFFFFFFFFFFFFFFFF; + } + Thread.WorkFinished += ThreadFinished; ThreadsByTpidr.TryAdd(Thread.ThreadState.Tpidr, ThreadHnd); diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index 40369b995..f33d2ac8e 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -161,17 +161,18 @@ namespace Ryujinx.Core.OsHle.Svc switch (InfoType) { - case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break; - case 3: ThreadState.X1 = GetMapRegionSize(); break; - case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break; - case 5: ThreadState.X1 = GetHeapRegionSize(); break; - case 6: ThreadState.X1 = GetTotalMem(); break; - case 7: ThreadState.X1 = GetUsedMem(); break; - case 11: ThreadState.X1 = GetRnd64(); break; - case 12: ThreadState.X1 = GetAddrSpaceBaseAddr(); break; - case 13: ThreadState.X1 = GetAddrSpaceSize(); break; - case 14: ThreadState.X1 = GetMapRegionBaseAddr(); break; - case 15: ThreadState.X1 = GetMapRegionSize(); break; + case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break; + case 3: ThreadState.X1 = GetMapRegionSize(); break; + case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break; + case 5: ThreadState.X1 = GetHeapRegionSize(); break; + case 6: ThreadState.X1 = GetTotalMem(); break; + case 7: ThreadState.X1 = GetUsedMem(); break; + case 8: ThreadState.X1 = IsCurrentProcessBeingDebugged(); break; + case 11: ThreadState.X1 = GetRnd64(); break; + case 12: ThreadState.X1 = GetAddrSpaceBaseAddr(); break; + case 13: ThreadState.X1 = GetAddrSpaceSize(); break; + case 14: ThreadState.X1 = GetMapRegionBaseAddr(); break; + case 15: ThreadState.X1 = GetMapRegionSize(); break; default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}"); } @@ -179,31 +180,6 @@ namespace Ryujinx.Core.OsHle.Svc ThreadState.X0 = (int)SvcResult.Success; } - private ulong GetTotalMem() - { - return (ulong)Memory.Manager.GetTotalMemorySize(); - } - - private ulong GetUsedMem() - { - return (ulong)Memory.Manager.GetUsedMemorySize(); - } - - private ulong GetRnd64() - { - return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32); - } - - private ulong GetAddrSpaceBaseAddr() - { - return 0x08000000; - } - - private ulong GetAddrSpaceSize() - { - return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr(); - } - private ulong GetMapRegionBaseAddr() { return 0x80000000; @@ -223,5 +199,35 @@ namespace Ryujinx.Core.OsHle.Svc { return 0x40000000; } + + private ulong GetTotalMem() + { + return (ulong)Memory.Manager.GetTotalMemorySize(); + } + + private ulong GetUsedMem() + { + return (ulong)Memory.Manager.GetUsedMemorySize(); + } + + private ulong IsCurrentProcessBeingDebugged() + { + return (ulong)0; + } + + private ulong GetRnd64() + { + return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32); + } + + private ulong GetAddrSpaceBaseAddr() + { + return 0x08000000; + } + + private ulong GetAddrSpaceSize() + { + return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr(); + } } } \ No newline at end of file From 1b33e2f1d4b190017b4aed26cfb2f6878f0b2e4c Mon Sep 17 00:00:00 2001 From: emmauss Date: Thu, 22 Feb 2018 15:28:27 +0200 Subject: [PATCH 12/67] implement single tap touchscreen (#34) --- Ryujinx.Core/Hid.cs | 60 +++++++++++++++++---- Ryujinx.Core/Hid/HidTouchScreen.cs | 5 +- Ryujinx.Core/Switch.cs | 5 ++ Ryujinx/Ui/GLScreen.cs | 86 +++++++++++++++++++----------- 4 files changed, 113 insertions(+), 43 deletions(-) diff --git a/Ryujinx.Core/Hid.cs b/Ryujinx.Core/Hid.cs index 44d3e0fb7..bd83e92d4 100644 --- a/Ryujinx.Core/Hid.cs +++ b/Ryujinx.Core/Hid.cs @@ -33,7 +33,7 @@ namespace Ryujinx.Core } */ - private const int Hid_Num_Entries = 16; + private const int Hid_Num_Entries = 17; private Switch Ns; private long SharedMemOffset; @@ -63,9 +63,8 @@ namespace Ryujinx.Core TouchScreen.Header.LatestEntry = 0; TouchScreen.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1; TouchScreen.Header.Timestamp = (ulong)Environment.TickCount; - - //TODO: Write this structure when the input is implemented - //Marshal.StructureToPtr(TouchScreen, HidPtr, false); + + Marshal.StructureToPtr(TouchScreen, HidPtr, false); InnerOffset += (uint)Marshal.SizeOf(typeof(HidTouchScreen)); HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); @@ -170,16 +169,57 @@ namespace Ryujinx.Core InnerOffset += (uint)Marshal.SizeOf(typeof(HidControllerLayoutHeader)) + (uint)((uint)(ControllerLayoutHeader.LatestEntry) * Marshal.SizeOf(typeof(HidControllerInputEntry))); HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - HidControllerInputEntry ControllerInputEntry = new HidControllerInputEntry(); - ControllerInputEntry.Timestamp = (ulong)Environment.TickCount; - ControllerInputEntry.Timestamp_2 = (ulong)Environment.TickCount; - ControllerInputEntry.Buttons = (ulong)Buttons; - ControllerInputEntry.Joysticks = new JoystickPosition[(int)HidControllerJoystick.Joystick_Num_Sticks]; + HidControllerInputEntry ControllerInputEntry = new HidControllerInputEntry + { + Timestamp = (ulong)Environment.TickCount, + Timestamp_2 = (ulong)Environment.TickCount, + Buttons = (ulong)Buttons, + Joysticks = new JoystickPosition[(int)HidControllerJoystick.Joystick_Num_Sticks] + }; ControllerInputEntry.Joysticks[(int)HidControllerJoystick.Joystick_Left] = LeftJoystick; ControllerInputEntry.Joysticks[(int)HidControllerJoystick.Joystick_Right] = RightJoystick; ControllerInputEntry.ConnectionState = (ulong)(HidControllerConnectionState.Controller_State_Connected | HidControllerConnectionState.Controller_State_Wired); Marshal.StructureToPtr(ControllerInputEntry, HidPtr, false); } + + public void SendTouchPoint(HidTouchScreenEntryTouch TouchPoint) + { + uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader)); + + IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); + + HidTouchScreenHeader OldTouchScreenHeader = (HidTouchScreenHeader)Marshal.PtrToStructure(HidPtr,typeof(HidTouchScreenHeader)); + + HidTouchScreenHeader TouchScreenHeader = new HidTouchScreenHeader() + { + TimestampTicks = (ulong)Environment.TickCount, + NumEntries = (ulong)Hid_Num_Entries, + MaxEntryIndex = (ulong)Hid_Num_Entries - 1, + Timestamp = (ulong)Environment.TickCount, + LatestEntry = OldTouchScreenHeader.LatestEntry < Hid_Num_Entries-1 ? OldTouchScreenHeader.LatestEntry + 1 : 0 + }; + + Marshal.StructureToPtr(TouchScreenHeader, HidPtr, false); + + InnerOffset += (uint)Marshal.SizeOf(typeof(HidTouchScreenHeader)) + + (uint)((uint)(OldTouchScreenHeader.LatestEntry) * Marshal.SizeOf(typeof(HidTouchScreenEntry))); + HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); + + HidTouchScreenEntry hidTouchScreenEntry = new HidTouchScreenEntry() + { + Header = new HidTouchScreenEntryHeader() + { + Timestamp = (ulong)Environment.TickCount, + NumTouches = 1 + }, + Touches = new HidTouchScreenEntryTouch[16] + }; + + //Only supports single touch + hidTouchScreenEntry.Touches[0] = TouchPoint; + + Marshal.StructureToPtr(hidTouchScreenEntry, HidPtr, false); + } } -} +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidTouchScreen.cs b/Ryujinx.Core/Hid/HidTouchScreen.cs index b755cb95c..755ebadca 100644 --- a/Ryujinx.Core/Hid/HidTouchScreen.cs +++ b/Ryujinx.Core/Hid/HidTouchScreen.cs @@ -38,7 +38,7 @@ namespace Ryujinx.Core { public HidTouchScreenEntryHeader Header; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] - public HidTouchScreenEntryTouch[] Touches; + public HidTouchScreenEntryTouch[] Touches; public ulong Unknown; } @@ -51,4 +51,5 @@ namespace Ryujinx.Core [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x3C0)] public byte[] Padding; } -} + +} \ No newline at end of file diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index 2b6a90457..8fd7979e4 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -51,6 +51,11 @@ namespace Ryujinx.Core { Hid.SendControllerButtons(ControllerId, Layout, Buttons, LeftJoystick, RightJoystick); } + + public void SendTouchScreenEntry(HidTouchScreenEntryTouch TouchPoint) + { + Hid.SendTouchPoint(TouchPoint); + } internal virtual void OnFinish(EventArgs e) { diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index a100080e0..325e38cdf 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -15,21 +15,21 @@ namespace Ryujinx { class ScreenTexture : IDisposable { - private Switch Ns; + private Switch Ns; private IGalRenderer Renderer; - + private int Width; private int Height; - private int TexHandle; + private int TexHandle; private int[] Pixels; public ScreenTexture(Switch Ns, IGalRenderer Renderer, int Width, int Height) { - this.Ns = Ns; + this.Ns = Ns; this.Renderer = Renderer; - this.Width = Width; - this.Height = Height; + this.Width = Width; + this.Height = Height; Pixels = new int[Width * Height]; @@ -96,7 +96,7 @@ namespace Ryujinx { int Pos; - Pos = (Y & 0x7f) >> 4; + Pos = (Y & 0x7f) >> 4; Pos += (X >> 4) << 3; Pos += (Y >> 7) * ((Width >> 4) << 3); Pos *= 1024; @@ -115,7 +115,7 @@ namespace Ryujinx public void Dispose() { Dispose(true); - + GC.SuppressFinalize(this); } @@ -183,7 +183,7 @@ void main(void) { PrgShaderHandle; private int WindowSizeUniformLocation; - + private int VaoHandle; private int VboHandle; @@ -199,7 +199,7 @@ void main(void) { DisplayDevice.Default, 3, 3, GraphicsContextFlags.ForwardCompatible) { - this.Ns = Ns; + this.Ns = Ns; this.Renderer = Renderer; ScreenTex = new ScreenTexture(Ns, Renderer, 1280, 720); @@ -296,43 +296,44 @@ void main(void) { JoystickPosition LeftJoystick; JoystickPosition RightJoystick; + if (Keyboard[OpenTK.Input.Key.Escape]) this.Exit(); //RightJoystick int LeftJoystickDX = 0; int LeftJoystickDY = 0; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickUp]) LeftJoystickDY = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickDown]) LeftJoystickDY = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickLeft]) LeftJoystickDX = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickRight]) LeftJoystickDX = short.MaxValue; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickUp]) LeftJoystickDY = short.MaxValue; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickDown]) LeftJoystickDY = -short.MaxValue; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickLeft]) LeftJoystickDX = -short.MaxValue; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickRight]) LeftJoystickDX = short.MaxValue; if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickButton]) CurrentButton |= HidControllerKeys.KEY_LSTICK; //LeftButtons - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadUp]) CurrentButton |= HidControllerKeys.KEY_DUP; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadDown]) CurrentButton |= HidControllerKeys.KEY_DDOWN; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadLeft]) CurrentButton |= HidControllerKeys.KEY_DLEFT; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadRight]) CurrentButton |= HidControllerKeys.KEY_DRIGHT; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadUp]) CurrentButton |= HidControllerKeys.KEY_DUP; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadDown]) CurrentButton |= HidControllerKeys.KEY_DDOWN; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadLeft]) CurrentButton |= HidControllerKeys.KEY_DLEFT; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadRight]) CurrentButton |= HidControllerKeys.KEY_DRIGHT; if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonMinus]) CurrentButton |= HidControllerKeys.KEY_MINUS; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonL]) CurrentButton |= HidControllerKeys.KEY_L; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonZL]) CurrentButton |= HidControllerKeys.KEY_ZL; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonL]) CurrentButton |= HidControllerKeys.KEY_L; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonZL]) CurrentButton |= HidControllerKeys.KEY_ZL; //RightJoystick int RightJoystickDX = 0; int RightJoystickDY = 0; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickUp]) RightJoystickDY = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickDown]) RightJoystickDY = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickLeft]) RightJoystickDX = -short.MaxValue; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickUp]) RightJoystickDY = short.MaxValue; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickDown]) RightJoystickDY = -short.MaxValue; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickLeft]) RightJoystickDX = -short.MaxValue; if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickRight]) RightJoystickDX = short.MaxValue; if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickButton]) CurrentButton |= HidControllerKeys.KEY_RSTICK; //RightButtons - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonA]) CurrentButton |= HidControllerKeys.KEY_A; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonB]) CurrentButton |= HidControllerKeys.KEY_B; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonX]) CurrentButton |= HidControllerKeys.KEY_X; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonY]) CurrentButton |= HidControllerKeys.KEY_Y; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonA]) CurrentButton |= HidControllerKeys.KEY_A; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonB]) CurrentButton |= HidControllerKeys.KEY_B; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonX]) CurrentButton |= HidControllerKeys.KEY_X; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonY]) CurrentButton |= HidControllerKeys.KEY_Y; if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonPlus]) CurrentButton |= HidControllerKeys.KEY_PLUS; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonR]) CurrentButton |= HidControllerKeys.KEY_R; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonZR]) CurrentButton |= HidControllerKeys.KEY_ZR; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonR]) CurrentButton |= HidControllerKeys.KEY_R; + if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonZR]) CurrentButton |= HidControllerKeys.KEY_ZR; LeftJoystick = new JoystickPosition { @@ -346,6 +347,29 @@ void main(void) { DY = RightJoystickDY }; + //Get screen touch position from left mouse click + //Opentk always captures mouse events, even if out of focus, so check if window is focused. + if (Mouse != null && Focused) + if (Mouse.GetState().LeftButton == OpenTK.Input.ButtonState.Pressed) + { + HidTouchScreenEntryTouch CurrentPoint = new HidTouchScreenEntryTouch + { + Timestamp = (uint)Environment.TickCount, + X = (uint)Mouse.X, + Y = (uint)Mouse.Y, + + //Placeholder values till more data is acquired + DiameterX = 10, + DiameterY = 10, + Angle = 90, + + //Only support single touch + TouchIndex = 0, + }; + if (Mouse.X > -1 && Mouse.Y > -1) + Ns.SendTouchScreenEntry(CurrentPoint); + } + //We just need one pair of JoyCon because it's emulate by the keyboard. Ns.SendControllerButtons(HidControllerID.CONTROLLER_HANDHELD, HidControllerLayouts.Main, CurrentButton, LeftJoystick, RightJoystick); } @@ -361,10 +385,10 @@ void main(void) { RenderFb(); GL.UseProgram(PrgShaderHandle); - + Renderer.RunActions(); Renderer.BindTexture(0); - Renderer.Render(); + Renderer.Render(); SwapBuffers(); } From 2cba1d49f6fcf3d22969579eb2d0d7f02b4c9efa Mon Sep 17 00:00:00 2001 From: gdkchan Date: Thu, 22 Feb 2018 16:26:11 -0300 Subject: [PATCH 13/67] Add FRINTP instruction, fix opcode ctor call method creation with multithreading --- ChocolArm64/AOpCodeTable.cs | 73 ++++++++++--------- ChocolArm64/Decoder/ADecoder.cs | 54 ++++++++------ .../Instruction/AInstEmitSimdArithmetic.cs | 8 ++ 3 files changed, 75 insertions(+), 60 deletions(-) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index ff2796b81..d4d6dd7c3 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -144,54 +144,55 @@ namespace ChocolArm64 Set("01011110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_S, typeof(AOpCodeSimdIns)); Set("0x001110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_V, typeof(AOpCodeSimdIns)); Set("0x101110001xxxxx000111xxxxxxxxxx", AInstEmit.Eor_V, typeof(AOpCodeSimdReg)); - Set("00011110xx100000110000xxxxxxxxxx", AInstEmit.Fabs_S, typeof(AOpCodeSimd)); - Set("00011110xx1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg)); + Set("000111100x100000110000xxxxxxxxxx", AInstEmit.Fabs_S, typeof(AOpCodeSimd)); + Set("000111100x1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg)); Set("0>0011100<1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg)); - Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond)); - Set("00011110xx1xxxxxxxxx01xxxxx1xxxx", AInstEmit.Fccmpe_S, typeof(AOpCodeSimdFcond)); - Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg)); - Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg)); - Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond)); - Set("00011110xx10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd)); - Set("x0011110xx100100000000xxxxxxxxxx", AInstEmit.Fcvtas_Gp, typeof(AOpCodeSimdCvt)); - Set("x0011110xx100101000000xxxxxxxxxx", AInstEmit.Fcvtau_Gp, typeof(AOpCodeSimdCvt)); - Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt)); - Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt)); - Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt)); - Set("x0011110xx011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Gp_Fix, typeof(AOpCodeSimdCvt)); + Set("000111100x1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond)); + Set("000111100x1xxxxxxxxx01xxxxx1xxxx", AInstEmit.Fccmpe_S, typeof(AOpCodeSimdFcond)); + Set("000111100x1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg)); + Set("000111100x1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg)); + Set("000111100x1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond)); + Set("000111100x10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd)); + Set("x00111100x100100000000xxxxxxxxxx", AInstEmit.Fcvtas_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x100101000000xxxxxxxxxx", AInstEmit.Fcvtau_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Gp_Fix, typeof(AOpCodeSimdCvt)); Set("0>0011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd)); Set("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimdShImm)); - Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_Gp, typeof(AOpCodeSimdCvt)); - Set("x0011110xx011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Gp_Fix, typeof(AOpCodeSimdCvt)); + Set("x00111100x111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Gp_Fix, typeof(AOpCodeSimdCvt)); Set("0>1011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd)); Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimdShImm)); - Set("00011110xx1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg)); + Set("000111100x1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg)); Set("0>1011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Fdiv_V, typeof(AOpCodeSimdReg)); - Set("00011111xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg)); - Set("00011110xx1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg)); - Set("00011110xx1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg)); - Set("00011110xx1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg)); - Set("00011110xx1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg)); + Set("000111110x0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg)); + Set("000111100x1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg)); + Set("000111100x1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg)); + Set("000111100x1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg)); + Set("000111100x1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg)); Set("0>0011100<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg)); Set("0x0011111<1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); Set("0x0011111<0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg)); Set("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns)); Set("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns)); diff --git a/ChocolArm64/Decoder/ADecoder.cs b/ChocolArm64/Decoder/ADecoder.cs index 06a535c1b..a3f44e470 100644 --- a/ChocolArm64/Decoder/ADecoder.cs +++ b/ChocolArm64/Decoder/ADecoder.cs @@ -1,6 +1,7 @@ using ChocolArm64.Instruction; using ChocolArm64.Memory; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection.Emit; @@ -8,6 +9,15 @@ namespace ChocolArm64.Decoder { static class ADecoder { + private delegate object OpActivator(AInst Inst, long Position, int OpCode); + + private static ConcurrentDictionary OpActivators; + + static ADecoder() + { + OpActivators = new ConcurrentDictionary(); + } + public static (ABlock[] Graph, ABlock Root) DecodeSubroutine(ATranslator Translator, long Start) { Dictionary Visited = new Dictionary(); @@ -165,43 +175,39 @@ namespace ChocolArm64.Decoder if (Inst.Type != null) { - DecodedOpCode = CreateOpCode(Inst.Type, Inst, Position, OpCode); + DecodedOpCode = MakeOpCode(Inst.Type, Inst, Position, OpCode); } return DecodedOpCode; } - private delegate object OpActivator(AInst Inst, long Position, int OpCode); - - private static Dictionary Activators = new Dictionary(); - - private static AOpCode CreateOpCode(Type Type, AInst Inst, long Position, int OpCode) + private static AOpCode MakeOpCode(Type Type, AInst Inst, long Position, int OpCode) { if (Type == null) { throw new ArgumentNullException(nameof(Type)); } - if (!Activators.TryGetValue(Type, out OpActivator CreateInstance)) - { - Type[] ArgTypes = new Type[] { typeof(AInst), typeof(long), typeof(int) }; - - DynamicMethod Mthd = new DynamicMethod($"{Type.Name}_Create", Type, ArgTypes); - - ILGenerator Generator = Mthd.GetILGenerator(); - - Generator.Emit(OpCodes.Ldarg_0); - Generator.Emit(OpCodes.Ldarg_1); - Generator.Emit(OpCodes.Ldarg_2); - Generator.Emit(OpCodes.Newobj, Type.GetConstructor(ArgTypes)); - Generator.Emit(OpCodes.Ret); - - CreateInstance = (OpActivator)Mthd.CreateDelegate(typeof(OpActivator)); - - Activators.Add(Type, CreateInstance); - } + OpActivator CreateInstance = OpActivators.GetOrAdd(Type, CacheOpActivator); return (AOpCode)CreateInstance(Inst, Position, OpCode); } + + private static OpActivator CacheOpActivator(Type Type) + { + Type[] ArgTypes = new Type[] { typeof(AInst), typeof(long), typeof(int) }; + + DynamicMethod Mthd = new DynamicMethod($"Make{Type.Name}", Type, ArgTypes); + + ILGenerator Generator = Mthd.GetILGenerator(); + + Generator.Emit(OpCodes.Ldarg_0); + Generator.Emit(OpCodes.Ldarg_1); + Generator.Emit(OpCodes.Ldarg_2); + Generator.Emit(OpCodes.Newobj, Type.GetConstructor(ArgTypes)); + Generator.Emit(OpCodes.Ret); + + return (OpActivator)Mthd.CreateDelegate(typeof(OpActivator)); + } } } \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index 21ec11a7e..6665f219e 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -257,6 +257,14 @@ namespace ChocolArm64.Instruction }); } + public static void Frintp_S(AILEmitterCtx Context) + { + EmitScalarUnaryOpF(Context, () => + { + EmitUnaryMathCall(Context, nameof(Math.Ceiling)); + }); + } + public static void Fsqrt_S(AILEmitterCtx Context) { EmitScalarUnaryOpF(Context, () => From f09a0082bf86e5e03e8a86c4c72f1794bb664534 Mon Sep 17 00:00:00 2001 From: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> Date: Fri, 23 Feb 2018 13:29:20 +0100 Subject: [PATCH 14/67] Review of cpu tests and creation of a class for mixed cpu tests. (#35) * Update CpuTest.cs * Update CpuTestAlu.cs * Update CpuTestScalar.cs * Update CpuTestSimdMove.cs * Create CpuTestMisc.cs * Update CpuTest.cs * Update CpuTestScalar.cs * Update CpuTest.cs * Update CpuTestAlu.cs * Update CpuTestMisc.cs * Update CpuTestScalar.cs --- Ryujinx.Tests/Cpu/CpuTest.cs | 86 ++++++--- Ryujinx.Tests/Cpu/CpuTestAlu.cs | 35 ++-- Ryujinx.Tests/Cpu/CpuTestMisc.cs | 276 +++++++++++++++++++++++++++ Ryujinx.Tests/Cpu/CpuTestScalar.cs | 10 +- Ryujinx.Tests/Cpu/CpuTestSimdMove.cs | 3 +- 5 files changed, 354 insertions(+), 56 deletions(-) create mode 100644 Ryujinx.Tests/Cpu/CpuTestMisc.cs diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index 0f1e64134..949b95969 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -1,4 +1,4 @@ -using ChocolArm64; +using ChocolArm64; using ChocolArm64.Memory; using ChocolArm64.State; using NUnit.Framework; @@ -9,65 +9,93 @@ using System.Threading; namespace Ryujinx.Tests.Cpu { [TestFixture] - public partial class CpuTest + public class CpuTest { - IntPtr Ram; - AMemoryAlloc Allocator; - AMemory Memory; + protected long Position { get; private set; } + private long Size; + + private long EntryPoint; + + private IntPtr Ram; + private AMemoryAlloc Allocator; + private AMemory Memory; + private AThread Thread; [SetUp] public void Setup() { + Position = 0x0; + Size = 0x1000; + + EntryPoint = Position; + Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); Allocator = new AMemoryAlloc(); Memory = new AMemory(Ram, Allocator); - Memory.Manager.MapPhys(0x1000, 0x1000, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute); + Memory.Manager.MapPhys(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute); + Thread = new AThread(Memory, ThreadPriority.Normal, EntryPoint); } [TearDown] public void Teardown() { + Thread = null; + Memory = null; + Allocator = null; Marshal.FreeHGlobal(Ram); } - private void Execute(AThread Thread) + protected void Reset() { - AutoResetEvent Wait = new AutoResetEvent(false); - Thread.ThreadState.Break += (sender, e) => Thread.StopExecution(); - Thread.WorkFinished += (sender, e) => Wait.Set(); - - Wait.Reset(); - Thread.Execute(); - Wait.WaitOne(); + Teardown(); + Setup(); } - private AThreadState SingleOpcode(uint Opcode, - ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, - AVec V0 = new AVec(), AVec V1 = new AVec(), AVec V2 = new AVec()) + protected void Opcode(uint Opcode) { - Memory.WriteUInt32(0x1000, Opcode); - Memory.WriteUInt32(0x1004, 0xD4200000); // BRK #0 - Memory.WriteUInt32(0x1008, 0xD65F03C0); // RET + Thread.Memory.WriteUInt32(Position, Opcode); + Position += 4; + } - AThread Thread = new AThread(Memory, ThreadPriority.Normal, 0x1000); + protected void SetThreadState(ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, + AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec)) + { Thread.ThreadState.X0 = X0; Thread.ThreadState.X1 = X1; Thread.ThreadState.X2 = X2; Thread.ThreadState.V0 = V0; Thread.ThreadState.V1 = V1; Thread.ThreadState.V2 = V2; - Execute(Thread); + } + + protected void ExecuteOpcodes() + { + using (ManualResetEvent Wait = new ManualResetEvent(false)) + { + Thread.ThreadState.Break += (sender, e) => Thread.StopExecution(); + Thread.WorkFinished += (sender, e) => Wait.Set(); + + Thread.Execute(); + Wait.WaitOne(); + } + } + + protected AThreadState GetThreadState() + { return Thread.ThreadState; } - [Test] - public void SanityCheck() + protected AThreadState SingleOpcode(uint Opcode, + ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, + AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec)) { - uint Opcode = 0xD503201F; // NOP - Assert.AreEqual(SingleOpcode(Opcode, X0: 0).X0, 0); - Assert.AreEqual(SingleOpcode(Opcode, X0: 1).X0, 1); - Assert.AreEqual(SingleOpcode(Opcode, X0: 2).X0, 2); - Assert.AreEqual(SingleOpcode(Opcode, X0: 42).X0, 42); + this.Opcode(Opcode); + this.Opcode(0xD4200000); // BRK #0 + this.Opcode(0xD65F03C0); // RET + SetThreadState(X0, X1, X2, V0, V1, V2); + ExecuteOpcodes(); + + return GetThreadState(); } } } diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu.cs b/Ryujinx.Tests/Cpu/CpuTestAlu.cs index a05c0b199..fd5357251 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu.cs @@ -1,10 +1,9 @@ -using ChocolArm64.State; +using ChocolArm64.State; using NUnit.Framework; namespace Ryujinx.Tests.Cpu { - [TestFixture] - public partial class CpuTest + public class CpuTestAlu : CpuTest { [Test] public void Add() @@ -14,25 +13,17 @@ namespace Ryujinx.Tests.Cpu Assert.AreEqual(3, ThreadState.X0); } - [Test] - public void Ands() + [TestCase(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFul, true, false)] + [TestCase(0xFFFFFFFFu, 0x00000000u, 0x00000000ul, false, true)] + [TestCase(0x12345678u, 0x7324A993u, 0x12240010ul, false, false)] + public void Ands(uint A, uint B, ulong Result, bool Negative, bool Zero) { // ANDS W0, W1, W2 uint Opcode = 0x6A020020; - var tests = new[] - { - new { W1 = 0xFFFFFFFFul, W2 = 0xFFFFFFFFul, Result = 0xFFFFFFFFul, Negative = true, Zero = false }, - new { W1 = 0xFFFFFFFFul, W2 = 0x00000000ul, Result = 0x00000000ul, Negative = false, Zero = true }, - new { W1 = 0x12345678ul, W2 = 0x7324A993ul, Result = 0x12240010ul, Negative = false, Zero = false }, - }; - - foreach (var test in tests) - { - AThreadState ThreadState = SingleOpcode(Opcode, X1: test.W1, X2: test.W2); - Assert.AreEqual(test.Result, ThreadState.X0); - Assert.AreEqual(test.Negative, ThreadState.Negative); - Assert.AreEqual(test.Zero, ThreadState.Zero); - } + AThreadState ThreadState = SingleOpcode(Opcode, X1: A, X2: B); + Assert.AreEqual(Result, ThreadState.X0); + Assert.AreEqual(Negative, ThreadState.Negative); + Assert.AreEqual(Zero, ThreadState.Zero); } [Test] @@ -40,8 +31,14 @@ namespace Ryujinx.Tests.Cpu { // ORR W0, WZR, #0x01010101 Assert.AreEqual(0x01010101, SingleOpcode(0x3200C3E0).X0); + + Reset(); + // ORR W1, WZR, #0x00F000F0 Assert.AreEqual(0x00F000F0, SingleOpcode(0x320C8FE1).X1); + + Reset(); + // ORR W2, WZR, #1 Assert.AreEqual(0x00000001, SingleOpcode(0x320003E2).X2); } diff --git a/Ryujinx.Tests/Cpu/CpuTestMisc.cs b/Ryujinx.Tests/Cpu/CpuTestMisc.cs new file mode 100644 index 000000000..97947b9a9 --- /dev/null +++ b/Ryujinx.Tests/Cpu/CpuTestMisc.cs @@ -0,0 +1,276 @@ +using ChocolArm64.State; +using NUnit.Framework; + +namespace Ryujinx.Tests.Cpu +{ + public class CpuTestMisc : CpuTest + { + [TestCase(0ul)] + [TestCase(1ul)] + [TestCase(2ul)] + [TestCase(42ul)] + public void SanityCheck(ulong A) + { + // NOP + uint Opcode = 0xD503201F; + AThreadState ThreadState = SingleOpcode(Opcode, X0: A); + Assert.AreEqual(A, ThreadState.X0); + } + + [TestCase(0xFFFFFFFDu)] // Roots. + [TestCase(0x00000005u)] + public void Misc1(uint A) + { + // ((A + 3) * (A - 5)) / ((A + 5) * (A - 3)) = 0 + + /* + ADD W2, W0, 3 + SUB W1, W0, #5 + MUL W2, W2, W1 + ADD W1, W0, 5 + SUB W0, W0, #3 + MUL W0, W1, W0 + SDIV W0, W2, W0 + BRK #0 + RET + */ + + SetThreadState(X0: A); + Opcode(0x11000C02); + Opcode(0x51001401); + Opcode(0x1B017C42); + Opcode(0x11001401); + Opcode(0x51000C00); + Opcode(0x1B007C20); + Opcode(0x1AC00C40); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + ExecuteOpcodes(); + Assert.AreEqual(0, GetThreadState().X0); + } + + [TestCase(-20f, -5f)] // 18 integer solutions. + [TestCase(-12f, -6f)] + [TestCase(-12f, 3f)] + [TestCase(-8f, -8f)] + [TestCase(-6f, -12f)] + [TestCase(-5f, -20f)] + [TestCase(-4f, 2f)] + [TestCase(-3f, 12f)] + [TestCase(-2f, 4f)] + [TestCase(2f, -4f)] + [TestCase(3f, -12f)] + [TestCase(4f, -2f)] + [TestCase(5f, 20f)] + [TestCase(6f, 12f)] + [TestCase(8f, 8f)] + [TestCase(12f, -3f)] + [TestCase(12f, 6f)] + [TestCase(20f, 5f)] + public void Misc2(float A, float B) + { + // 1 / ((1 / A + 1 / B) ^ 2) = 16 + + /* + FMOV S2, 1.0e+0 + FDIV S0, S2, S0 + FDIV S1, S2, S1 + FADD S0, S0, S1 + FDIV S0, S2, S0 + FMUL S0, S0, S0 + BRK #0 + RET + */ + + SetThreadState(V0: new AVec { S0 = A }, V1: new AVec { S0 = B }); + Opcode(0x1E2E1002); + Opcode(0x1E201840); + Opcode(0x1E211841); + Opcode(0x1E212800); + Opcode(0x1E201840); + Opcode(0x1E200800); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + ExecuteOpcodes(); + Assert.AreEqual(16f, GetThreadState().V0.S0); + } + + [TestCase(-20d, -5d)] // 18 integer solutions. + [TestCase(-12d, -6d)] + [TestCase(-12d, 3d)] + [TestCase(-8d, -8d)] + [TestCase(-6d, -12d)] + [TestCase(-5d, -20d)] + [TestCase(-4d, 2d)] + [TestCase(-3d, 12d)] + [TestCase(-2d, 4d)] + [TestCase(2d, -4d)] + [TestCase(3d, -12d)] + [TestCase(4d, -2d)] + [TestCase(5d, 20d)] + [TestCase(6d, 12d)] + [TestCase(8d, 8d)] + [TestCase(12d, -3d)] + [TestCase(12d, 6d)] + [TestCase(20d, 5d)] + public void Misc3(double A, double B) + { + // 1 / ((1 / A + 1 / B) ^ 2) = 16 + + /* + FMOV D2, 1.0e+0 + FDIV D0, D2, D0 + FDIV D1, D2, D1 + FADD D0, D0, D1 + FDIV D0, D2, D0 + FMUL D0, D0, D0 + BRK #0 + RET + */ + + SetThreadState(V0: new AVec { D0 = A }, V1: new AVec { D0 = B }); + Opcode(0x1E6E1002); + Opcode(0x1E601840); + Opcode(0x1E611841); + Opcode(0x1E612800); + Opcode(0x1E601840); + Opcode(0x1E600800); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + ExecuteOpcodes(); + Assert.AreEqual(16d, GetThreadState().V0.D0); + } + + [Test] + public void MiscR() + { + ulong Result = 5; + + /* + 0x0000000000000000: MOV X0, #2 + 0x0000000000000004: MOV X1, #3 + 0x0000000000000008: ADD X0, X0, X1 + 0x000000000000000C: BRK #0 + 0x0000000000000010: RET + */ + + Opcode(0xD2800040); + Opcode(0xD2800061); + Opcode(0x8B010000); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + ExecuteOpcodes(); + Assert.AreEqual(Result, GetThreadState().X0); + + Reset(); + + /* + 0x0000000000000000: MOV X0, #3 + 0x0000000000000004: MOV X1, #2 + 0x0000000000000008: ADD X0, X0, X1 + 0x000000000000000C: BRK #0 + 0x0000000000000010: RET + */ + + Opcode(0xD2800060); + Opcode(0xD2800041); + Opcode(0x8B010000); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + ExecuteOpcodes(); + Assert.AreEqual(Result, GetThreadState().X0); + } + + [Test, Explicit] + public void Misc5() + { + /* + 0x0000000000000000: SUBS X0, X0, #1 + 0x0000000000000004: B.NE #0 + 0x0000000000000008: BRK #0 + 0x000000000000000C: RET + */ + + SetThreadState(X0: 0x100000000); + Opcode(0xF1000400); + Opcode(0x54FFFFE1); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + ExecuteOpcodes(); + Assert.AreEqual(0, GetThreadState().X0); + Assert.IsTrue(GetThreadState().Zero); + } + + [Test] + public void MiscF([Range(0, 92, 1)] int A) + { + ulong F_n(uint n) + { + ulong a = 0, b = 1, c; + + if (n == 0) + { + return a; + } + + for (uint i = 2; i <= n; i++) + { + c = a + b; + a = b; + b = c; + } + + return b; + } + + /* + 0x0000000000000000: MOV W4, W0 + 0x0000000000000004: CBZ W0, #0x3C + 0x0000000000000008: CMP W0, #1 + 0x000000000000000C: B.LS #0x48 + 0x0000000000000010: MOVZ W2, #0x2 + 0x0000000000000014: MOVZ X1, #0x1 + 0x0000000000000018: MOVZ X3, #0 + 0x000000000000001C: ADD X0, X3, X1 + 0x0000000000000020: ADD W2, W2, #1 + 0x0000000000000024: MOV X3, X1 + 0x0000000000000028: MOV X1, X0 + 0x000000000000002C: CMP W4, W2 + 0x0000000000000030: B.HS #0x1C + 0x0000000000000034: BRK #0 + 0x0000000000000038: RET + 0x000000000000003C: MOVZ X0, #0 + 0x0000000000000040: BRK #0 + 0x0000000000000044: RET + 0x0000000000000048: MOVZ X0, #0x1 + 0x000000000000004C: BRK #0 + 0x0000000000000050: RET + */ + + SetThreadState(X0: (uint)A); + Opcode(0x2A0003E4); + Opcode(0x340001C0); + Opcode(0x7100041F); + Opcode(0x540001E9); + Opcode(0x52800042); + Opcode(0xD2800021); + Opcode(0xD2800003); + Opcode(0x8B010060); + Opcode(0x11000442); + Opcode(0xAA0103E3); + Opcode(0xAA0003E1); + Opcode(0x6B02009F); + Opcode(0x54FFFF62); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + Opcode(0xD2800000); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + Opcode(0xD2800020); + Opcode(0xD4200000); + Opcode(0xD65F03C0); + ExecuteOpcodes(); + Assert.AreEqual(F_n((uint)A), GetThreadState().X0); + } + } +} diff --git a/Ryujinx.Tests/Cpu/CpuTestScalar.cs b/Ryujinx.Tests/Cpu/CpuTestScalar.cs index 26549b872..ffe01a299 100644 --- a/Ryujinx.Tests/Cpu/CpuTestScalar.cs +++ b/Ryujinx.Tests/Cpu/CpuTestScalar.cs @@ -3,8 +3,7 @@ using NUnit.Framework; namespace Ryujinx.Tests.Cpu { - [TestFixture] - public partial class CpuTest + public class CpuTestScalar : CpuTest { [TestCase(0x00000000u, 0x80000000u, 0x00000000u)] [TestCase(0x80000000u, 0x00000000u, 0x00000000u)] @@ -15,10 +14,9 @@ namespace Ryujinx.Tests.Cpu [TestCase(0x7F7FFFFFu, 0x807FFFFFu, 0x7F7FFFFFu)] [TestCase(0x7FC00000u, 0x3F800000u, 0x7FC00000u)] [TestCase(0x3F800000u, 0x7FC00000u, 0x7FC00000u)] - // NaN tests - //[TestCase(0x7F800001u, 0x7FC00042u, 0x7FC00001u)] - //[TestCase(0x7FC00042u, 0x7F800001u, 0x7FC00001u)] - //[TestCase(0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Au)] + [TestCase(0x7F800001u, 0x7FC00042u, 0x7FC00001u, Ignore = "NaN test.")] + [TestCase(0x7FC00042u, 0x7F800001u, 0x7FC00001u, Ignore = "NaN test.")] + [TestCase(0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Au, Ignore = "NaN test.")] public void Fmax_S(uint A, uint B, uint Result) { // FMAX S0, S1, S2 diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdMove.cs b/Ryujinx.Tests/Cpu/CpuTestSimdMove.cs index d77ac9e52..372689d08 100644 --- a/Ryujinx.Tests/Cpu/CpuTestSimdMove.cs +++ b/Ryujinx.Tests/Cpu/CpuTestSimdMove.cs @@ -3,8 +3,7 @@ using NUnit.Framework; namespace Ryujinx.Tests.Cpu { - [TestFixture] - public partial class CpuTest + public class CpuTestSimdMove : CpuTest { [TestCase(0u, 0u, 0x2313221221112010ul, 0x0000000000000000ul)] [TestCase(1u, 0u, 0x2313221221112010ul, 0x2717261625152414ul)] From eafc58c9f2e2e0c19d22f0da2a93ab5372aeef29 Mon Sep 17 00:00:00 2001 From: MS-DOS1999 Date: Fri, 23 Feb 2018 15:53:32 +0100 Subject: [PATCH 15/67] Add flags parameters in singleOpcode function, and add ADC Test (#36) * Add flags parameters in singleOpcode function, and add ADC Test * Update CpuTestAlu.cs * Update CpuTestAlu.cs * Update CpuTestAlu.cs * Update CpuTestAlu.cs --- Ryujinx.Tests/Cpu/CpuTest.cs | 12 +++++++++--- Ryujinx.Tests/Cpu/CpuTestAlu.cs | 9 +++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index 949b95969..92c74e443 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -58,7 +58,8 @@ namespace Ryujinx.Tests.Cpu } protected void SetThreadState(ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, - AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec)) + AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec), + bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false) { Thread.ThreadState.X0 = X0; Thread.ThreadState.X1 = X1; @@ -66,6 +67,10 @@ namespace Ryujinx.Tests.Cpu Thread.ThreadState.V0 = V0; Thread.ThreadState.V1 = V1; Thread.ThreadState.V2 = V2; + Thread.ThreadState.Overflow = Overflow; + Thread.ThreadState.Carry = Carry; + Thread.ThreadState.Zero = Zero; + Thread.ThreadState.Negative = Negative; } protected void ExecuteOpcodes() @@ -87,12 +92,13 @@ namespace Ryujinx.Tests.Cpu protected AThreadState SingleOpcode(uint Opcode, ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, - AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec)) + AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec), + bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false) { this.Opcode(Opcode); this.Opcode(0xD4200000); // BRK #0 this.Opcode(0xD65F03C0); // RET - SetThreadState(X0, X1, X2, V0, V1, V2); + SetThreadState(X0, X1, X2, V0, V1, V2, Overflow, Carry, Zero, Negative); ExecuteOpcodes(); return GetThreadState(); diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu.cs b/Ryujinx.Tests/Cpu/CpuTestAlu.cs index fd5357251..b73212ac5 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu.cs @@ -5,6 +5,15 @@ namespace Ryujinx.Tests.Cpu { public class CpuTestAlu : CpuTest { + [TestCase(2u, 3u, 6ul, true)] + [TestCase(2u, 3u, 5ul, false)] + public void Adc(uint A, uint B, ulong Result, bool CarryTest) + { + // ADC X0, X1, X2 + AThreadState ThreadState = SingleOpcode(0x9A020020, X1: A, X2: B, Carry: CarryTest); + Assert.AreEqual(Result, ThreadState.X0); + } + [Test] public void Add() { From 2ed733b1d5addad027f48acfdd407e64b71427fc Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 23 Feb 2018 18:48:27 -0300 Subject: [PATCH 16/67] Somewhat better NvFlinger (I guess) (fixes #30) --- .../OsHle/Objects/Android/GbpBuffer.cs | 60 +++ .../OsHle/Objects/Android/NvFlinger.cs | 392 ++++++++++++++++++ .../OsHle/Objects/{ => Android}/Parcel.cs | 0 Ryujinx.Core/OsHle/Objects/ErrorCode.cs | 2 - .../Objects/Hid/IActiveVibrationDeviceList.cs | 1 - .../OsHle/Objects/Vi/IHOSBinderDriver.cs | 178 +------- Ryujinx.Graphics/Gal/EmbeddedResource.cs | 20 + Ryujinx.Graphics/Gal/IGalRenderer.cs | 7 +- Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl | 13 + Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl | 26 ++ Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs | 228 ++++++++++ Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 40 +- Ryujinx.Graphics/Ryujinx.Graphics.csproj | 17 + Ryujinx/Ui/GLScreen.cs | 280 +------------ 14 files changed, 820 insertions(+), 444 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs create mode 100644 Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs rename Ryujinx.Core/OsHle/Objects/{ => Android}/Parcel.cs (100%) create mode 100644 Ryujinx.Graphics/Gal/EmbeddedResource.cs create mode 100644 Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl create mode 100644 Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl create mode 100644 Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs diff --git a/Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs b/Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs new file mode 100644 index 000000000..edd115237 --- /dev/null +++ b/Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs @@ -0,0 +1,60 @@ +using System.IO; + +namespace Ryujinx.Core.OsHle.Objects.Android +{ + struct GbpBuffer + { + public int Magic { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + public int Stride { get; private set; } + public int Format { get; private set; } + public int Usage { get; private set; } + + public int Pid { get; private set; } + public int RefCount { get; private set; } + + public int FdsCount { get; private set; } + public int IntsCount { get; private set; } + + public byte[] RawData { get; private set; } + + public int Size => RawData.Length + 10 * 4; + + public GbpBuffer(BinaryReader Reader) + { + Magic = Reader.ReadInt32(); + Width = Reader.ReadInt32(); + Height = Reader.ReadInt32(); + Stride = Reader.ReadInt32(); + Format = Reader.ReadInt32(); + Usage = Reader.ReadInt32(); + + Pid = Reader.ReadInt32(); + RefCount = Reader.ReadInt32(); + + FdsCount = Reader.ReadInt32(); + IntsCount = Reader.ReadInt32(); + + RawData = Reader.ReadBytes((FdsCount + IntsCount) * 4); + } + + public void Write(BinaryWriter Writer) + { + Writer.Write(Magic); + Writer.Write(Width); + Writer.Write(Height); + Writer.Write(Stride); + Writer.Write(Format); + Writer.Write(Usage); + + Writer.Write(Pid); + Writer.Write(RefCount); + + Writer.Write(FdsCount); + Writer.Write(IntsCount); + + Writer.Write(RawData); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs new file mode 100644 index 000000000..238630992 --- /dev/null +++ b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs @@ -0,0 +1,392 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Handles; +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +using static Ryujinx.Core.OsHle.Objects.Android.Parcel; + +namespace Ryujinx.Core.OsHle.Objects.Android +{ + class NvFlinger : IDisposable + { + private delegate long ServiceProcessParcel(ServiceCtx Context, BinaryReader ParcelReader); + + private Dictionary<(string, int), ServiceProcessParcel> Commands; + + private const int BufferQueueCount = 0x40; + private const int BufferQueueMask = BufferQueueCount - 1; + + [Flags] + private enum HalTransform + { + FlipX = 1 << 0, + FlipY = 1 << 1, + Rotate90 = 1 << 2 + } + + private enum BufferState + { + Free, + Dequeued, + Queued, + Acquired + } + + private struct BufferEntry + { + public BufferState State; + + public HalTransform Transform; + + public GbpBuffer Data; + } + + private BufferEntry[] BufferQueue; + + private ManualResetEvent WaitBufferFree; + + private bool KeepRunning; + + public NvFlinger() + { + Commands = new Dictionary<(string, int), ServiceProcessParcel>() + { + { ("android.gui.IGraphicBufferProducer", 0x1), GbpRequestBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x3), GbpDequeueBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x7), GbpQueueBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x8), GbpCancelBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x9), GbpQuery }, + { ("android.gui.IGraphicBufferProducer", 0xa), GbpConnect }, + { ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer } + }; + + BufferQueue = new BufferEntry[0x40]; + + WaitBufferFree = new ManualResetEvent(false); + + KeepRunning = true; + } + + public long ProcessParcelRequest(ServiceCtx Context, byte[] ParcelData, int Code) + { + using (MemoryStream MS = new MemoryStream(ParcelData)) + { + BinaryReader Reader = new BinaryReader(MS); + + MS.Seek(4, SeekOrigin.Current); + + int StrSize = Reader.ReadInt32(); + + string InterfaceName = Encoding.Unicode.GetString(Reader.ReadBytes(StrSize * 2)); + + long Remainder = MS.Position & 0xf; + + if (Remainder != 0) + { + MS.Seek(0x10 - Remainder, SeekOrigin.Current); + } + + MS.Seek(0x50, SeekOrigin.Begin); + + if (Commands.TryGetValue((InterfaceName, Code), out ServiceProcessParcel ProcReq)) + { + Logging.Debug($"{InterfaceName} {ProcReq.Method.Name}"); + + return ProcReq(Context, Reader); + } + else + { + throw new NotImplementedException($"{InterfaceName} {Code}"); + } + } + } + + private long GbpRequestBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + int Slot = ParcelReader.ReadInt32(); + + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + BufferEntry Entry = BufferQueue[Slot]; + + int BufferCount = 1; //? + long BufferSize = Entry.Data.Size; + + Writer.Write(BufferCount); + Writer.Write(BufferSize); + + Entry.Data.Write(Writer); + + Writer.Write(0); + + return MakeReplyParcel(Context, MS.ToArray()); + } + } + + private long GbpDequeueBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + //TODO: Errors. + int Format = ParcelReader.ReadInt32(); + int Width = ParcelReader.ReadInt32(); + int Height = ParcelReader.ReadInt32(); + int GetTimestamps = ParcelReader.ReadInt32(); + int Usage = ParcelReader.ReadInt32(); + + int Slot = GetFreeSlotBlocking(Width, Height); + + return MakeReplyParcel(Context, Slot, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + + private long GbpQueueBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + //TODO: Errors. + int Slot = ParcelReader.ReadInt32(); + int Unknown4 = ParcelReader.ReadInt32(); + int Unknown8 = ParcelReader.ReadInt32(); + int Unknownc = ParcelReader.ReadInt32(); + int Timestamp = ParcelReader.ReadInt32(); + int IsAutoTimestamp = ParcelReader.ReadInt32(); + int CropTop = ParcelReader.ReadInt32(); + int CropLeft = ParcelReader.ReadInt32(); + int CropRight = ParcelReader.ReadInt32(); + int CropBottom = ParcelReader.ReadInt32(); + int ScalingMode = ParcelReader.ReadInt32(); + int Transform = ParcelReader.ReadInt32(); + int StickyTransform = ParcelReader.ReadInt32(); + int Unknown34 = ParcelReader.ReadInt32(); + int Unknown38 = ParcelReader.ReadInt32(); + int IsFenceValid = ParcelReader.ReadInt32(); + int Fence0Id = ParcelReader.ReadInt32(); + int Fence0Value = ParcelReader.ReadInt32(); + int Fence1Id = ParcelReader.ReadInt32(); + int Fence1Value = ParcelReader.ReadInt32(); + + BufferQueue[Slot].Transform = (HalTransform)Transform; + + BufferQueue[Slot].State = BufferState.Queued; + + SendFrameBuffer(Context, Slot); + + return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); + } + + private long GbpCancelBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + //TODO: Errors. + int Slot = ParcelReader.ReadInt32(); + + BufferQueue[Slot].State = BufferState.Free; + + return MakeReplyParcel(Context, 0); + } + + private long GbpQuery(ServiceCtx Context, BinaryReader ParcelReader) + { + return MakeReplyParcel(Context, 0, 0); + } + + private long GbpConnect(ServiceCtx Context, BinaryReader ParcelReader) + { + return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); + } + + private long GbpPreallocBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + int Slot = ParcelReader.ReadInt32(); + + int BufferCount = ParcelReader.ReadInt32(); + long BufferSize = ParcelReader.ReadInt64(); + + BufferQueue[Slot].State = BufferState.Free; + + BufferQueue[Slot].Data = new GbpBuffer(ParcelReader); + + return MakeReplyParcel(Context, 0); + } + + private long MakeReplyParcel(ServiceCtx Context, params int[] Ints) + { + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + foreach (int Int in Ints) + { + Writer.Write(Int); + } + + return MakeReplyParcel(Context, MS.ToArray()); + } + } + + private long MakeReplyParcel(ServiceCtx Context, byte[] Data) + { + long ReplyPos = Context.Request.ReceiveBuff[0].Position; + long ReplySize = Context.Request.ReceiveBuff[0].Size; + + byte[] Reply = MakeParcel(Data, new byte[0]); + + AMemoryHelper.WriteBytes(Context.Memory, ReplyPos, Reply); + + return 0; + } + + private unsafe void SendFrameBuffer(ServiceCtx Context, int Slot) + { + int FbWidth = BufferQueue[Slot].Data.Width; + int FbHeight = BufferQueue[Slot].Data.Height; + + int FbSize = FbWidth * FbHeight * 4; + + HNvMap NvMap = GetNvMap(Context, Slot); + + if (NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize) + { + Logging.Error($"Frame buffer address {NvMap.Address:x16} is invalid!"); + + BufferQueue[Slot].State = BufferState.Free; + + WaitBufferFree.Set(); + + return; + } + + BufferQueue[Slot].State = BufferState.Acquired; + + float ScaleX = 1; + float ScaleY = 1; + float Rotate = 0; + + if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX)) + { + ScaleX = -1; + } + + if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY)) + { + ScaleY = -1; + } + + if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90)) + { + Rotate = MathF.PI * 0.5f; + } + + byte* Fb = (byte*)Context.Ns.Ram + NvMap.Address; + + Context.Ns.Gpu.Renderer.QueueAction(delegate() + { + Context.Ns.Gpu.Renderer.SetFrameBuffer( + Fb, + FbWidth, + FbHeight, + ScaleX, + ScaleY, + Rotate); + + BufferQueue[Slot].State = BufferState.Free; + + WaitBufferFree.Set(); + }); + } + + private HNvMap GetNvMap(ServiceCtx Context, int Slot) + { + int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c); + + if (!BitConverter.IsLittleEndian) + { + byte[] RawValue = BitConverter.GetBytes(NvMapHandle); + + Array.Reverse(RawValue); + + NvMapHandle = BitConverter.ToInt32(RawValue, 0); + } + + return Context.Ns.Os.Handles.GetData(NvMapHandle); + } + + private int GetFreeSlotBlocking(int Width, int Height) + { + int Slot; + + do + { + if ((Slot = GetFreeSlot(Width, Height)) != -1) + { + break; + } + + Logging.Debug("Waiting for a free BufferQueue slot..."); + + lock (WaitBufferFree) + { + if (!KeepRunning) + { + break; + } + + WaitBufferFree.Reset(); + } + + WaitBufferFree.WaitOne(); + } + while (KeepRunning); + + Logging.Debug($"Found free BufferQueue slot {Slot}!"); + + return Slot; + } + + private int GetFreeSlot(int Width, int Height) + { + lock (BufferQueue) + { + for (int Slot = 0; Slot < BufferQueue.Length; Slot++) + { + if (BufferQueue[Slot].State != BufferState.Free) + { + continue; + } + + GbpBuffer Data = BufferQueue[Slot].Data; + + if (Data.Width == Width && + Data.Height == Height) + { + BufferQueue[Slot].State = BufferState.Dequeued; + + return Slot; + } + } + } + + return -1; + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + lock (WaitBufferFree) + { + KeepRunning = false; + + WaitBufferFree.Set(); + } + + WaitBufferFree.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Parcel.cs b/Ryujinx.Core/OsHle/Objects/Android/Parcel.cs similarity index 100% rename from Ryujinx.Core/OsHle/Objects/Parcel.cs rename to Ryujinx.Core/OsHle/Objects/Android/Parcel.cs diff --git a/Ryujinx.Core/OsHle/Objects/ErrorCode.cs b/Ryujinx.Core/OsHle/Objects/ErrorCode.cs index 20f97f848..659ed8b94 100644 --- a/Ryujinx.Core/OsHle/Objects/ErrorCode.cs +++ b/Ryujinx.Core/OsHle/Objects/ErrorCode.cs @@ -1,5 +1,3 @@ -using System; - namespace Ryujinx.Core.OsHle.Objects { static class ErrorCode diff --git a/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs b/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs index 1f0c8592a..aae3c38d3 100644 --- a/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs +++ b/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs @@ -1,4 +1,3 @@ -using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; diff --git a/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs index cfd271e85..bbea3368c 100644 --- a/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs +++ b/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs @@ -1,34 +1,18 @@ using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; -using Ryujinx.Core.OsHle.Utilities; +using Ryujinx.Core.OsHle.Objects.Android; using System; using System.Collections.Generic; -using System.IO; -using System.Text; - -using static Ryujinx.Core.OsHle.Objects.Android.Parcel; namespace Ryujinx.Core.OsHle.Objects.Vi { - class IHOSBinderDriver : IIpcInterface + class IHOSBinderDriver : IIpcInterface, IDisposable { - private delegate long ServiceProcessParcel(ServiceCtx Context, byte[] ParcelData); - private Dictionary m_Commands; - private Dictionary<(string, int), ServiceProcessParcel> m_Methods; + public IReadOnlyDictionary Commands => m_Commands; - public IReadOnlyDictionary Commands => m_Commands; - - private class BufferObj - { - - } - - private IdPoolWithObj BufferSlots; - - private byte[] Gbfr; + private NvFlinger Flinger; public IHOSBinderDriver() { @@ -39,18 +23,7 @@ namespace Ryujinx.Core.OsHle.Objects.Vi { 2, GetNativeHandle } }; - m_Methods = new Dictionary<(string, int), ServiceProcessParcel>() - { - { ("android.gui.IGraphicBufferProducer", 0x1), GraphicBufferProducerRequestBuffer }, - { ("android.gui.IGraphicBufferProducer", 0x3), GraphicBufferProducerDequeueBuffer }, - { ("android.gui.IGraphicBufferProducer", 0x7), GraphicBufferProducerQueueBuffer }, - { ("android.gui.IGraphicBufferProducer", 0x8), GraphicBufferProducerCancelBuffer }, - { ("android.gui.IGraphicBufferProducer", 0x9), GraphicBufferProducerQuery }, - { ("android.gui.IGraphicBufferProducer", 0xa), GraphicBufferProducerConnect }, - { ("android.gui.IGraphicBufferProducer", 0xe), GraphicBufferPreallocateBuffer } - }; - - BufferSlots = new IdPoolWithObj(); + Flinger = new NvFlinger(); } public long TransactParcel(ServiceCtx Context) @@ -63,133 +36,9 @@ namespace Ryujinx.Core.OsHle.Objects.Vi byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, DataPos, (int)DataSize); - Data = GetParcelData(Data); + Data = Parcel.GetParcelData(Data); - using (MemoryStream MS = new MemoryStream(Data)) - { - BinaryReader Reader = new BinaryReader(MS); - - MS.Seek(4, SeekOrigin.Current); - - int StrSize = Reader.ReadInt32(); - - string InterfaceName = Encoding.Unicode.GetString(Data, 8, StrSize * 2); - - if (m_Methods.TryGetValue((InterfaceName, Code), out ServiceProcessParcel ProcReq)) - { - return ProcReq(Context, Data); - } - else - { - throw new NotImplementedException($"{InterfaceName} {Code}"); - } - } - } - - private long GraphicBufferProducerRequestBuffer(ServiceCtx Context, byte[] ParcelData) - { - int GbfrSize = Gbfr?.Length ?? 0; - - byte[] Data = new byte[GbfrSize + 4]; - - if (Gbfr != null) - { - Buffer.BlockCopy(Gbfr, 0, Data, 0, GbfrSize); - } - - return MakeReplyParcel(Context, Data); - } - - private long GraphicBufferProducerDequeueBuffer(ServiceCtx Context, byte[] ParcelData) - { - //Note: It seems that the maximum number of slots is 64, because if we return - //a Slot number > 63, it seems to cause a buffer overrun and it reads garbage. - //Note 2: The size of each object associated with the slot is 0x30. - int Slot = BufferSlots.GenerateId(new BufferObj()); - - return MakeReplyParcel(Context, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } - - private long GraphicBufferProducerQueueBuffer(ServiceCtx Context, byte[] ParcelData) - { - return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); - } - - private long GraphicBufferProducerCancelBuffer(ServiceCtx Context, byte[] ParcelData) - { - using (MemoryStream MS = new MemoryStream(ParcelData)) - { - BinaryReader Reader = new BinaryReader(MS); - - MS.Seek(0x50, SeekOrigin.Begin); - - int Slot = Reader.ReadInt32(); - - BufferSlots.Delete(Slot); - - return MakeReplyParcel(Context, 0); - } - } - - private long GraphicBufferProducerQuery(ServiceCtx Context, byte[] ParcelData) - { - return MakeReplyParcel(Context, 0, 0); - } - - private long GraphicBufferProducerConnect(ServiceCtx Context, byte[] ParcelData) - { - return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); - } - - private long GraphicBufferPreallocateBuffer(ServiceCtx Context, byte[] ParcelData) - { - int GbfrSize = ParcelData.Length - 0x54; - - Gbfr = new byte[GbfrSize]; - - Buffer.BlockCopy(ParcelData, 0x54, Gbfr, 0, GbfrSize); - - using (MemoryStream MS = new MemoryStream(ParcelData)) - { - BinaryReader Reader = new BinaryReader(MS); - - MS.Seek(0xd4, SeekOrigin.Begin); - - int Handle = Reader.ReadInt32(); - - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); - - Context.Ns.Gpu.Renderer.FrameBufferPtr = NvMap.Address; - } - - return MakeReplyParcel(Context, 0); - } - - private long MakeReplyParcel(ServiceCtx Context, params int[] Ints) - { - using (MemoryStream MS = new MemoryStream()) - { - BinaryWriter Writer = new BinaryWriter(MS); - - foreach (int Int in Ints) - { - Writer.Write(Int); - } - - return MakeReplyParcel(Context, MS.ToArray()); - } - } - - private long MakeReplyParcel(ServiceCtx Context, byte[] Data) - { - long ReplyPos = Context.Request.ReceiveBuff[0].Position; - long ReplySize = Context.Request.ReceiveBuff[0].Position; - - byte[] Reply = MakeParcel(Data, new byte[0]); - - AMemoryHelper.WriteBytes(Context.Memory, ReplyPos, Reply); - - return 0; + return Flinger.ProcessParcelRequest(Context, Data, Code); } public long AdjustRefcount(ServiceCtx Context) @@ -210,5 +59,18 @@ namespace Ryujinx.Core.OsHle.Objects.Vi return 0; } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + Flinger.Dispose(); + } + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/EmbeddedResource.cs b/Ryujinx.Graphics/Gal/EmbeddedResource.cs new file mode 100644 index 000000000..45b77da71 --- /dev/null +++ b/Ryujinx.Graphics/Gal/EmbeddedResource.cs @@ -0,0 +1,20 @@ +using System.IO; +using System.Reflection; + +namespace Ryujinx.Graphics.Gal +{ + static class EmbeddedResource + { + public static string GetString(string Name) + { + Assembly Asm = typeof(EmbeddedResource).Assembly; + + using (Stream ResStream = Asm.GetManifestResourceStream(Name)) + { + StreamReader Reader = new StreamReader(ResStream); + + return Reader.ReadToEnd(); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index 1870aca5b..5854c54a6 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -2,14 +2,15 @@ using System; namespace Ryujinx.Graphics.Gal { - public interface IGalRenderer + public unsafe interface IGalRenderer { - long FrameBufferPtr { get; set; } - void QueueAction(Action ActionMthd); void RunActions(); + void InitializeFrameBuffer(); void Render(); + void SetWindowSize(int Width, int Height); + void SetFrameBuffer(byte* Fb, int Width, int Height, float SX, float SY, float R); void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs); void SendR8G8B8A8Texture(int Index, byte[] Buffer, int Width, int Height); void BindTexture(int Index); diff --git a/Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl b/Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl new file mode 100644 index 000000000..74e33bd7c --- /dev/null +++ b/Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl @@ -0,0 +1,13 @@ +#version 330 core + +precision highp float; + +uniform sampler2D tex; + +in vec2 tex_coord; + +out vec4 out_frag_color; + +void main(void) { + out_frag_color = texture(tex, tex_coord); +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl b/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl new file mode 100644 index 000000000..933fa6aa9 --- /dev/null +++ b/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl @@ -0,0 +1,26 @@ +#version 330 core + +precision highp float; + +uniform vec2 window_size; +uniform mat2 transform; + +layout(location = 0) in vec2 in_position; +layout(location = 1) in vec2 in_tex_coord; + +out vec2 tex_coord; + +// Have a fixed aspect ratio, fit the image within the available space. +vec2 get_scale_ratio(void) { + vec2 native_size = vec2(1280, 720); + vec2 ratio = vec2( + (window_size.y * native_size.x) / (native_size.y * window_size.x), + (window_size.x * native_size.y) / (native_size.x * window_size.y) + ); + return min(ratio, 1); +} + +void main(void) { + tex_coord = in_tex_coord; + gl_Position = vec4((transform * in_position) * get_scale_ratio(), 0, 1); +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs new file mode 100644 index 000000000..c66c0cb75 --- /dev/null +++ b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs @@ -0,0 +1,228 @@ +using OpenTK; +using OpenTK.Graphics.OpenGL; +using System; + +namespace Ryujinx.Graphics.Gal.OpenGL +{ + unsafe class FrameBuffer + { + public int WindowWidth { get; set; } + public int WindowHeight { get; set; } + + private int VtxShaderHandle; + private int FragShaderHandle; + private int PrgShaderHandle; + + private int TexHandle; + private int TexWidth; + private int TexHeight; + + private int VaoHandle; + private int VboHandle; + + private int[] Pixels; + + private byte* FbPtr; + + public FrameBuffer(int Width, int Height) + { + if (Width < 0) + { + throw new ArgumentOutOfRangeException(nameof(Width)); + } + + if (Height < 0) + { + throw new ArgumentOutOfRangeException(nameof(Height)); + } + + TexWidth = Width; + TexHeight = Height; + + WindowWidth = Width; + WindowHeight = Height; + + SetupShaders(); + SetupTexture(); + SetupVertex(); + } + + private void SetupShaders() + { + VtxShaderHandle = GL.CreateShader(ShaderType.VertexShader); + FragShaderHandle = GL.CreateShader(ShaderType.FragmentShader); + + string VtxShaderSource = EmbeddedResource.GetString("GlFbVtxShader"); + string FragShaderSource = EmbeddedResource.GetString("GlFbFragShader"); + + GL.ShaderSource(VtxShaderHandle, VtxShaderSource); + GL.ShaderSource(FragShaderHandle, FragShaderSource); + GL.CompileShader(VtxShaderHandle); + GL.CompileShader(FragShaderHandle); + + PrgShaderHandle = GL.CreateProgram(); + + GL.AttachShader(PrgShaderHandle, VtxShaderHandle); + GL.AttachShader(PrgShaderHandle, FragShaderHandle); + GL.LinkProgram(PrgShaderHandle); + GL.UseProgram(PrgShaderHandle); + + int TexUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "tex"); + + GL.Uniform1(TexUniformLocation, 0); + + int WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size"); + + GL.Uniform2(WindowSizeUniformLocation, new Vector2(1280.0f, 720.0f)); + } + + private void SetupTexture() + { + Pixels = new int[TexWidth * TexHeight]; + + if (TexHandle == 0) + { + TexHandle = GL.GenTexture(); + } + + GL.BindTexture(TextureTarget.Texture2D, TexHandle); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.TexImage2D(TextureTarget.Texture2D, + 0, + PixelInternalFormat.Rgba, + TexWidth, + TexHeight, + 0, + PixelFormat.Rgba, + PixelType.UnsignedByte, + IntPtr.Zero); + } + + private void SetupVertex() + { + VaoHandle = GL.GenVertexArray(); + VboHandle = GL.GenBuffer(); + + float[] Buffer = new float[] + { + -1, 1, 0, 0, + 1, 1, 1, 0, + -1, -1, 0, 1, + 1, -1, 1, 1 + }; + + IntPtr Length = new IntPtr(Buffer.Length * 4); + + GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); + GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw); + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + + GL.BindVertexArray(VaoHandle); + + GL.EnableVertexAttribArray(0); + + GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); + + GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 16, 0); + + GL.EnableVertexAttribArray(1); + + GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); + + GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 16, 8); + + GL.BindVertexArray(0); + } + + public unsafe void Set(byte* Fb, int Width, int Height, Matrix2 Transform) + { + if (Fb == null) + { + throw new ArgumentNullException(nameof(Fb)); + } + + if (Width < 0) + { + throw new ArgumentOutOfRangeException(nameof(Width)); + } + + if (Height < 0) + { + throw new ArgumentOutOfRangeException(nameof(Height)); + } + + FbPtr = Fb; + + if (Width != TexWidth || + Height != TexHeight) + { + TexWidth = Width; + TexHeight = Height; + + SetupTexture(); + } + + GL.UseProgram(PrgShaderHandle); + + int TransformUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "transform"); + + GL.UniformMatrix2(TransformUniformLocation, false, ref Transform); + + int WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size"); + + GL.Uniform2(WindowSizeUniformLocation, new Vector2(WindowWidth, WindowHeight)); + } + + public void Render() + { + if (FbPtr == null) + { + return; + } + + for (int Y = 0; Y < TexHeight; Y++) + for (int X = 0; X < TexWidth; X++) + { + Pixels[X + Y * TexWidth] = *((int*)(FbPtr + GetSwizzleOffset(X, Y))); + } + + GL.BindTexture(TextureTarget.Texture2D, TexHandle); + GL.TexSubImage2D(TextureTarget.Texture2D, + 0, + 0, + 0, + TexWidth, + TexHeight, + PixelFormat.Rgba, + PixelType.UnsignedByte, + Pixels); + + GL.ActiveTexture(TextureUnit.Texture0); + + GL.BindVertexArray(VaoHandle); + + GL.UseProgram(PrgShaderHandle); + + GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4); + } + + private int GetSwizzleOffset(int X, int Y) + { + int Pos; + + Pos = (Y & 0x7f) >> 4; + Pos += (X >> 4) << 3; + Pos += (Y >> 7) * ((TexWidth >> 4) << 3); + Pos *= 1024; + Pos += ((Y & 0xf) >> 3) << 9; + Pos += ((X & 0xf) >> 3) << 8; + Pos += ((Y & 0x7) >> 1) << 6; + Pos += ((X & 0x7) >> 2) << 5; + Pos += ((Y & 0x1) >> 0) << 4; + Pos += ((X & 0x3) >> 0) << 2; + + return Pos; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index 7429569b6..6bf17d094 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -1,7 +1,9 @@ +using OpenTK; using OpenTK.Graphics.OpenGL; using System; using System.Collections.Generic; + namespace Ryujinx.Graphics.Gal.OpenGL { public class OpenGLRenderer : IGalRenderer @@ -25,6 +27,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL private Queue ActionsQueue; + private FrameBuffer FbRenderer; + public long FrameBufferPtr { get; set; } public OpenGLRenderer() @@ -36,6 +40,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL ActionsQueue = new Queue(); } + public void InitializeFrameBuffer() + { + FbRenderer = new FrameBuffer(1280, 720); + } + public void QueueAction(Action ActionMthd) { ActionsQueue.Enqueue(ActionMthd); @@ -43,14 +52,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL public void RunActions() { - while (ActionsQueue.Count > 0) + int Count = ActionsQueue.Count; + + while (Count-- > 0) { ActionsQueue.Dequeue()(); } - } + } public void Render() { + FbRenderer.Render(); + for (int Index = 0; Index < VertexBuffers.Count; Index++) { VertexBuffer Vb = VertexBuffers[Index]; @@ -62,7 +75,28 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.DrawArrays(PrimitiveType.TriangleStrip, 0, Vb.PrimCount); } } - + } + + public void SetWindowSize(int Width, int Height) + { + FbRenderer.WindowWidth = Width; + FbRenderer.WindowHeight = Height; + } + + public unsafe void SetFrameBuffer( + byte* Fb, + int Width, + int Height, + float ScaleX, + float ScaleY, + float Rotate) + { + Matrix2 Transform; + + Transform = Matrix2.CreateScale(ScaleX, ScaleY); + Transform *= Matrix2.CreateRotation(Rotate); + + FbRenderer.Set(Fb, Width, Height, Transform); } public void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs) diff --git a/Ryujinx.Graphics/Ryujinx.Graphics.csproj b/Ryujinx.Graphics/Ryujinx.Graphics.csproj index 657beb827..01bf41f83 100644 --- a/Ryujinx.Graphics/Ryujinx.Graphics.csproj +++ b/Ryujinx.Graphics/Ryujinx.Graphics.csproj @@ -4,6 +4,14 @@ netcoreapp2.0 + + true + + + + true + + @@ -12,4 +20,13 @@ + + + GlFbVtxShader + + + GlFbFragShader + + + diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 325e38cdf..3219303eb 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -1,7 +1,3 @@ -// This code was written for the OpenTK library and has been released -// to the Public Domain. -// It is provided "as is" without express or implied warranty of any kind. - using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; @@ -13,281 +9,25 @@ namespace Ryujinx { public class GLScreen : GameWindow { - class ScreenTexture : IDisposable - { - private Switch Ns; - private IGalRenderer Renderer; - - private int Width; - private int Height; - private int TexHandle; - - private int[] Pixels; - - public ScreenTexture(Switch Ns, IGalRenderer Renderer, int Width, int Height) - { - this.Ns = Ns; - this.Renderer = Renderer; - this.Width = Width; - this.Height = Height; - - Pixels = new int[Width * Height]; - - TexHandle = GL.GenTexture(); - - GL.BindTexture(TextureTarget.Texture2D, TexHandle); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - GL.TexImage2D(TextureTarget.Texture2D, - 0, - PixelInternalFormat.Rgba, - Width, - Height, - 0, - PixelFormat.Rgba, - PixelType.UnsignedByte, - IntPtr.Zero); - } - - public int Texture - { - get - { - UploadBitmap(); - - return TexHandle; - } - } - - unsafe void UploadBitmap() - { - int FbSize = Width * Height * 4; - - if (Renderer.FrameBufferPtr == 0 || Renderer.FrameBufferPtr + FbSize > uint.MaxValue) - { - return; - } - - byte* SrcPtr = (byte*)Ns.Ram + (uint)Renderer.FrameBufferPtr; - - for (int Y = 0; Y < Height; Y++) - { - for (int X = 0; X < Width; X++) - { - int SrcOffs = GetSwizzleOffset(X, Y, 4); - - Pixels[X + Y * Width] = *((int*)(SrcPtr + SrcOffs)); - } - } - - GL.BindTexture(TextureTarget.Texture2D, TexHandle); - GL.TexSubImage2D(TextureTarget.Texture2D, - 0, - 0, - 0, - Width, - Height, - PixelFormat.Rgba, - PixelType.UnsignedByte, - Pixels); - } - - private int GetSwizzleOffset(int X, int Y, int Bpp) - { - int Pos; - - Pos = (Y & 0x7f) >> 4; - Pos += (X >> 4) << 3; - Pos += (Y >> 7) * ((Width >> 4) << 3); - Pos *= 1024; - Pos += ((Y & 0xf) >> 3) << 9; - Pos += ((X & 0xf) >> 3) << 8; - Pos += ((Y & 0x7) >> 1) << 6; - Pos += ((X & 0x7) >> 2) << 5; - Pos += ((Y & 0x1) >> 0) << 4; - Pos += ((X & 0x3) >> 0) << 2; - - return Pos; - } - - private bool disposed; - - public void Dispose() - { - Dispose(true); - - GC.SuppressFinalize(this); - } - - void Dispose(bool disposing) - { - if (!disposed) - { - if (disposing) - { - GL.DeleteTexture(TexHandle); - } - - disposed = true; - } - } - } - - private string VtxShaderSource = @" -#version 330 core - -precision highp float; - -uniform vec2 window_size; - -layout(location = 0) in vec3 in_position; -layout(location = 1) in vec4 in_color; -layout(location = 2) in vec2 in_tex_coord; - -out vec4 color; -out vec2 tex_coord; - -// Have a fixed aspect ratio, fit the image within the available space. -vec3 get_scale_ratio() { - vec2 native_size = vec2(1280, 720); - vec2 ratio = vec2( - (window_size.y * native_size.x) / (native_size.y * window_size.x), - (window_size.x * native_size.y) / (native_size.x * window_size.y) - ); - return vec3(min(ratio, vec2(1, 1)) * vec2(1, -1), 1); -} - -void main(void) { - color = in_color; - tex_coord = in_tex_coord; - gl_Position = vec4(in_position * get_scale_ratio(), 1); -}"; - - private string FragShaderSource = @" -#version 330 core - -precision highp float; - -uniform sampler2D tex; - -in vec4 color; -in vec2 tex_coord; -out vec4 out_frag_color; - -void main(void) { - out_frag_color = vec4(texture(tex, tex_coord).rgb, color.a); -}"; - - private int VtxShaderHandle, - FragShaderHandle, - PrgShaderHandle; - - private int WindowSizeUniformLocation; - - private int VaoHandle; - private int VboHandle; - private Switch Ns; private IGalRenderer Renderer; - private ScreenTexture ScreenTex; - public GLScreen(Switch Ns, IGalRenderer Renderer) : base(1280, 720, new GraphicsMode(), "Ryujinx", 0, DisplayDevice.Default, 3, 3, GraphicsContextFlags.ForwardCompatible) { - this.Ns = Ns; + this.Ns = Ns; this.Renderer = Renderer; - - ScreenTex = new ScreenTexture(Ns, Renderer, 1280, 720); } protected override void OnLoad(EventArgs e) { VSync = VSyncMode.On; - CreateShaders(); - CreateVbo(); - - GL.Enable(EnableCap.Blend); - GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); - } - - protected override void OnUnload(EventArgs e) - { - ScreenTex.Dispose(); - - GL.DeleteVertexArray(VaoHandle); - GL.DeleteBuffer(VboHandle); - } - - private void CreateVbo() - { - VaoHandle = GL.GenVertexArray(); - VboHandle = GL.GenBuffer(); - - uint[] Buffer = new uint[] - { - 0xbf800000, 0x3f800000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x3f800000, 0x3f800000, 0x00000000, 0xffffffff, 0x00000000, 0x3f800000, 0x00000000, - 0xbf800000, 0xbf800000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x3f800000, - 0x3f800000, 0xbf800000, 0x00000000, 0xffffffff, 0x00000000, 0x3f800000, 0x3f800000 - }; - - IntPtr Length = new IntPtr(Buffer.Length * 4); - - GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); - GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw); - GL.BindBuffer(BufferTarget.ArrayBuffer, 0); - - GL.BindVertexArray(VaoHandle); - - GL.EnableVertexAttribArray(0); - - GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); - - GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 28, 0); - - GL.EnableVertexAttribArray(1); - - GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); - - GL.VertexAttribPointer(1, 4, VertexAttribPointerType.UnsignedByte, false, 28, 12); - - GL.EnableVertexAttribArray(2); - - GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle); - - GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 28, 20); - - GL.BindVertexArray(0); - } - - private void CreateShaders() - { - VtxShaderHandle = GL.CreateShader(ShaderType.VertexShader); - FragShaderHandle = GL.CreateShader(ShaderType.FragmentShader); - - GL.ShaderSource(VtxShaderHandle, VtxShaderSource); - GL.ShaderSource(FragShaderHandle, FragShaderSource); - GL.CompileShader(VtxShaderHandle); - GL.CompileShader(FragShaderHandle); - - PrgShaderHandle = GL.CreateProgram(); - - GL.AttachShader(PrgShaderHandle, VtxShaderHandle); - GL.AttachShader(PrgShaderHandle, FragShaderHandle); - GL.LinkProgram(PrgShaderHandle); - GL.UseProgram(PrgShaderHandle); - - int TexLocation = GL.GetUniformLocation(PrgShaderHandle, "tex"); - GL.Uniform1(TexLocation, 0); - - WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size"); - GL.Uniform2(WindowSizeUniformLocation, new Vector2(1280.0f, 720.0f)); + Renderer.InitializeFrameBuffer(); } protected override void OnUpdateFrame(FrameEventArgs e) @@ -382,12 +122,7 @@ void main(void) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - RenderFb(); - - GL.UseProgram(PrgShaderHandle); - Renderer.RunActions(); - Renderer.BindTexture(0); Renderer.Render(); SwapBuffers(); @@ -395,16 +130,7 @@ void main(void) { protected override void OnResize(EventArgs e) { - GL.UseProgram(PrgShaderHandle); - GL.Uniform2(WindowSizeUniformLocation, new Vector2(Width, Height)); - } - - void RenderFb() - { - GL.ActiveTexture(TextureUnit.Texture0); - GL.BindTexture(TextureTarget.Texture2D, ScreenTex.Texture); - GL.BindVertexArray(VaoHandle); - GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4); + Renderer.SetWindowSize(Width, Height); } } } \ No newline at end of file From 3936c934482a587635bc5a1e47962551aeb53aeb Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 23 Feb 2018 21:59:38 -0300 Subject: [PATCH 17/67] Map heap on heap base region, fix for thread start on homebrew, add FCVTMU and FCVTPU (general) instructions, fix FMOV (higher 64 bits) encodings, improve emit code for FCVT* (general) instructions --- ChocolArm64/AOpCodeTable.cs | 6 +- ChocolArm64/Instruction/AInstEmitSimdCvt.cs | 105 ++++++++++-------- Ryujinx.Core/Loaders/Executable.cs | 3 - .../Loaders/Executables/IExecutable.cs | 8 -- Ryujinx.Core/Loaders/Executables/Nro.cs | 4 - Ryujinx.Core/Loaders/Executables/Nso.cs | 4 - Ryujinx.Core/OsHle/Horizon.cs | 16 ++- Ryujinx.Core/OsHle/MemoryRegions.cs | 13 +++ .../OsHle/Objects/Android/NvFlinger.cs | 2 +- .../OsHle/Objects/FspSrv/IFileSystem.cs | 13 ++- Ryujinx.Core/OsHle/Process.cs | 19 ++-- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 8 +- Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 5 +- Ryujinx/Ui/Program.cs | 4 +- 14 files changed, 109 insertions(+), 101 deletions(-) create mode 100644 Ryujinx.Core/OsHle/MemoryRegions.cs diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index d4d6dd7c3..b8fe278dd 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -156,7 +156,9 @@ namespace ChocolArm64 Set("x00111100x100100000000xxxxxxxxxx", AInstEmit.Fcvtas_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x100101000000xxxxxxxxxx", AInstEmit.Fcvtau_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x110001000000xxxxxxxxxx", AInstEmit.Fcvtmu_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt)); + Set("x00111100x101001000000xxxxxxxxxx", AInstEmit.Fcvtpu_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Gp_Fix, typeof(AOpCodeSimdCvt)); Set("0>0011101<100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd)); @@ -179,8 +181,8 @@ namespace ChocolArm64 Set("0xx0111100000xxx111101xxxxxxxxxx", AInstEmit.Fmov_V, typeof(AOpCodeSimdImm)); Set("x00111100x100110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi, typeof(AOpCodeSimdCvt)); Set("x00111100x100111000000xxxxxxxxxx", AInstEmit.Fmov_Itof, typeof(AOpCodeSimdCvt)); - Set("x00111100x101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt)); - Set("x00111100x101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt)); + Set("1001111010101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt)); + Set("1001111010101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt)); Set("000111110x0xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fmsub_S, typeof(AOpCodeSimdReg)); Set("000111100x1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg)); Set("0>1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs index 00c2fe9b5..688f05a20 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs @@ -23,52 +23,62 @@ namespace ChocolArm64.Instruction public static void Fcvtas_Gp(AILEmitterCtx Context) { - Fcvta__Gp(Context, Signed: true); + EmitFcvt_s_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero)); } public static void Fcvtau_Gp(AILEmitterCtx Context) { - Fcvta__Gp(Context, Signed: false); + EmitFcvt_u_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero)); } public static void Fcvtms_Gp(AILEmitterCtx Context) { - EmitFcvt_s_Gp(Context, nameof(Math.Floor)); + EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor))); + } + + public static void Fcvtmu_Gp(AILEmitterCtx Context) + { + EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor))); } public static void Fcvtps_Gp(AILEmitterCtx Context) { - EmitFcvt_s_Gp(Context, nameof(Math.Ceiling)); + EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling))); + } + + public static void Fcvtpu_Gp(AILEmitterCtx Context) + { + EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling))); } public static void Fcvtzs_Gp(AILEmitterCtx Context) { - EmitFcvtz__Gp(Context, Signed: true); + EmitFcvt_s_Gp(Context, () => { }); } public static void Fcvtzs_Gp_Fix(AILEmitterCtx Context) { - EmitFcvtz__Gp_Fix(Context, Signed: true); + EmitFcvtzs_Gp_Fix(Context); } public static void Fcvtzs_V(AILEmitterCtx Context) { - EmitVectorFcvt(Context, Signed: true); + EmitVectorFcvtzs(Context); } public static void Fcvtzu_Gp(AILEmitterCtx Context) { - EmitFcvtz__Gp(Context, Signed: false); + EmitFcvt_u_Gp(Context, () => { }); } public static void Fcvtzu_Gp_Fix(AILEmitterCtx Context) { - EmitFcvtz__Gp_Fix(Context, Signed: false); + EmitFcvtzu_Gp_Fix(Context); } public static void Fcvtzu_V(AILEmitterCtx Context) { - EmitVectorFcvt(Context, Signed: false); + EmitVectorFcvtzu(Context); } public static void Scvtf_Gp(AILEmitterCtx Context) @@ -165,13 +175,23 @@ namespace ChocolArm64.Instruction } } - private static void Fcvta__Gp(AILEmitterCtx Context, bool Signed) + private static void EmitFcvt_s_Gp(AILEmitterCtx Context, Action Emit) + { + EmitFcvt___Gp(Context, Emit, true); + } + + private static void EmitFcvt_u_Gp(AILEmitterCtx Context, Action Emit) + { + EmitFcvt___Gp(Context, Emit, false); + } + + private static void EmitFcvt___Gp(AILEmitterCtx Context, Action Emit, bool Signed) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - EmitRoundMathCall(Context, MidpointRounding.AwayFromZero); + Emit(); if (Signed) { @@ -190,45 +210,14 @@ namespace ChocolArm64.Instruction Context.EmitStintzr(Op.Rd); } - private static void EmitFcvt_s_Gp(AILEmitterCtx Context, string Name) + private static void EmitFcvtzs_Gp_Fix(AILEmitterCtx Context) { - AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; - - EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - - EmitUnaryMathCall(Context, Name); - - EmitScalarFcvts(Context, Op.Size, 0); - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - Context.Emit(OpCodes.Conv_U8); - } - - Context.EmitStintzr(Op.Rd); + EmitFcvtz__Gp_Fix(Context, true); } - private static void EmitFcvtz__Gp(AILEmitterCtx Context, bool Signed) + private static void EmitFcvtzu_Gp_Fix(AILEmitterCtx Context) { - AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; - - EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - - if (Signed) - { - EmitScalarFcvts(Context, Op.Size, 0); - } - else - { - EmitScalarFcvtu(Context, Op.Size, 0); - } - - if (Context.CurrOp.RegisterSize == ARegisterSize.Int32) - { - Context.Emit(OpCodes.Conv_U8); - } - - Context.EmitStintzr(Op.Rd); + EmitFcvtz__Gp_Fix(Context, false); } private static void EmitFcvtz__Gp_Fix(AILEmitterCtx Context, bool Signed) @@ -254,6 +243,16 @@ namespace ChocolArm64.Instruction Context.EmitStintzr(Op.Rd); } + private static void EmitVectorScvtf(AILEmitterCtx Context) + { + EmitVectorCvtf(Context, true); + } + + private static void EmitVectorUcvtf(AILEmitterCtx Context) + { + EmitVectorCvtf(Context, false); + } + private static void EmitVectorCvtf(AILEmitterCtx Context, bool Signed) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; @@ -289,7 +288,17 @@ namespace ChocolArm64.Instruction } } - private static void EmitVectorFcvt(AILEmitterCtx Context, bool Signed) + private static void EmitVectorFcvtzs(AILEmitterCtx Context) + { + EmitVectorFcvtz(Context, true); + } + + private static void EmitVectorFcvtzu(AILEmitterCtx Context) + { + EmitVectorFcvtz(Context, false); + } + + private static void EmitVectorFcvtz(AILEmitterCtx Context, bool Signed) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index 25a621362..e26608389 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -13,7 +13,6 @@ namespace Ryujinx.Core.Loaders public long ImageBase { get; private set; } public long ImageEnd { get; private set; } - public Extensions Extension { get; private set; } public Executable(IExecutable Exe, AMemory Memory, long ImageBase) { @@ -47,8 +46,6 @@ namespace Ryujinx.Core.Loaders long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset; long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset; - Extension = Exe.Extension; - MapBss(BssStartOffset, BssEndOffset - BssStartOffset); ImageEnd = BssEndOffset; diff --git a/Ryujinx.Core/Loaders/Executables/IExecutable.cs b/Ryujinx.Core/Loaders/Executables/IExecutable.cs index f6aa31aca..73787b1d2 100644 --- a/Ryujinx.Core/Loaders/Executables/IExecutable.cs +++ b/Ryujinx.Core/Loaders/Executables/IExecutable.cs @@ -2,12 +2,6 @@ using System.Collections.ObjectModel; namespace Ryujinx.Core.Loaders.Executables { - public enum Extensions - { - NRO, - NSO - } - public interface IExecutable { ReadOnlyCollection Text { get; } @@ -19,7 +13,5 @@ namespace Ryujinx.Core.Loaders.Executables int ROOffset { get; } int DataOffset { get; } int BssSize { get; } - - Extensions Extension { get; } } } \ No newline at end of file diff --git a/Ryujinx.Core/Loaders/Executables/Nro.cs b/Ryujinx.Core/Loaders/Executables/Nro.cs index 7f492cc2b..3cbc4c5d4 100644 --- a/Ryujinx.Core/Loaders/Executables/Nro.cs +++ b/Ryujinx.Core/Loaders/Executables/Nro.cs @@ -20,8 +20,6 @@ namespace Ryujinx.Core.Loaders.Executables public int DataOffset { get; private set; } public int BssSize { get; private set; } - public Extensions Extension { get; private set; } - public Nro(Stream Input) { BinaryReader Reader = new BinaryReader(Input); @@ -49,8 +47,6 @@ namespace Ryujinx.Core.Loaders.Executables this.DataOffset = DataOffset; this.BssSize = BssSize; - this.Extension = Extensions.NRO; - byte[] Read(long Position, int Size) { Input.Seek(Position, SeekOrigin.Begin); diff --git a/Ryujinx.Core/Loaders/Executables/Nso.cs b/Ryujinx.Core/Loaders/Executables/Nso.cs index 63ae08aea..7b8bf253a 100644 --- a/Ryujinx.Core/Loaders/Executables/Nso.cs +++ b/Ryujinx.Core/Loaders/Executables/Nso.cs @@ -21,8 +21,6 @@ namespace Ryujinx.Core.Loaders.Executables public int DataOffset { get; private set; } public int BssSize { get; private set; } - public Extensions Extension { get; private set; } - [Flags] private enum NsoFlags { @@ -81,8 +79,6 @@ namespace Ryujinx.Core.Loaders.Executables this.DataOffset = DataMemOffset; this.BssSize = BssSize; - this.Extension = Extensions.NSO; - //Text segment Input.Seek(TextOffset, SeekOrigin.Begin); diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs index e2d38d522..9929102d6 100644 --- a/Ryujinx.Core/OsHle/Horizon.cs +++ b/Ryujinx.Core/OsHle/Horizon.cs @@ -114,25 +114,22 @@ namespace Ryujinx.Core.OsHle public void LoadProgram(string FileName) { + bool IsNro = Path.GetExtension(FileName).ToLower() == ".nro"; + int ProcessId = IdGen.GenerateId(); Process MainProcess = new Process(Ns, Allocator, ProcessId); using (FileStream Input = new FileStream(FileName, FileMode.Open)) { - if (Path.GetExtension(FileName).ToLower() == ".nro") - { - MainProcess.LoadProgram(new Nro(Input)); - } - else - { - MainProcess.LoadProgram(new Nso(Input)); - } + MainProcess.LoadProgram(IsNro + ? (IExecutable)new Nro(Input) + : (IExecutable)new Nso(Input)); } MainProcess.SetEmptyArgs(); MainProcess.InitializeHeap(); - MainProcess.Run(); + MainProcess.Run(IsNro); Processes.TryAdd(ProcessId, MainProcess); } @@ -190,6 +187,7 @@ namespace Ryujinx.Core.OsHle if (SharedMem.TryGetLastVirtualPosition(out long Position)) { Logging.Info($"HID shared memory successfully mapped to {Position:x16}!"); + Ns.Hid.Init(Position); } } diff --git a/Ryujinx.Core/OsHle/MemoryRegions.cs b/Ryujinx.Core/OsHle/MemoryRegions.cs new file mode 100644 index 000000000..e8ededc8f --- /dev/null +++ b/Ryujinx.Core/OsHle/MemoryRegions.cs @@ -0,0 +1,13 @@ +using ChocolArm64.Memory; + +namespace Ryujinx.Core.OsHle +{ + static class MemoryRegions + { + public const long MapRegionAddress = 0x80000000; + public const long MapRegionSize = 0x40000000; + + public const long HeapRegionAddress = MapRegionAddress + MapRegionSize; + public const long HeapRegionSize = 0x40000000; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs index 238630992..545883836 100644 --- a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs @@ -245,7 +245,7 @@ namespace Ryujinx.Core.OsHle.Objects.Android HNvMap NvMap = GetNvMap(Context, Slot); - if (NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize) + if (FbSize < 0 || NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize) { Logging.Error($"Frame buffer address {NvMap.Address:x16} is invalid!"); diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs index e18c1dafd..6b86a4739 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs @@ -273,7 +273,16 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv FileStream Stream = new FileStream(FileName, FileMode.Open); - MakeObject(Context, new IFile(Stream, FileName)); + IFile FileInterface = new IFile(Stream, FileName); + + FileInterface.Disposed += RemoveFileInUse; + + lock (OpenPaths) + { + OpenPaths.Add(FileName); + } + + MakeObject(Context, FileInterface); return 0; } @@ -353,7 +362,7 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv lock (OpenPaths) { - FileInterface.Disposed -= RemoveDirectoryInUse; + FileInterface.Disposed -= RemoveFileInUse; OpenPaths.Remove(FileInterface.HostPath); } diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index 022dc0f9a..3e265ed34 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -86,10 +86,10 @@ namespace Ryujinx.Core.OsHle public void InitializeHeap() { - Memory.Manager.SetHeapAddr((ImageBase + 0x3fffffff) & ~0x3fffffff); + Memory.Manager.SetHeapAddr(MemoryRegions.HeapRegionAddress); } - public bool Run() + public bool Run(bool UseHbAbi = false) { if (Executables.Count == 0) { @@ -109,6 +109,14 @@ namespace Ryujinx.Core.OsHle MainThread = Ns.Os.Handles.GetData(Handle); + if (UseHbAbi) + { + Homebrew Homebrew_ABI = new Homebrew(Memory, Executables[0].ImageEnd, (long)Handle); + + MainThread.Thread.ThreadState.X0 = (ulong)Executables[0].ImageEnd; + MainThread.Thread.ThreadState.X1 = ulong.MaxValue; + } + Scheduler.StartThread(MainThread); return true; @@ -186,13 +194,6 @@ namespace Ryujinx.Core.OsHle Thread.ThreadState.X1 = (ulong)Handle; Thread.ThreadState.X31 = (ulong)StackTop; - if (Executables[0].Extension == Extensions.NRO) - { - Homebrew Homebrew_ABI = new Homebrew(Memory, Executables[0].ImageEnd, (long)Handle); - Thread.ThreadState.X0 = (ulong)Executables[0].ImageEnd; - Thread.ThreadState.X1 = 0xFFFFFFFFFFFFFFFF; - } - Thread.WorkFinished += ThreadFinished; ThreadsByTpidr.TryAdd(Thread.ThreadState.Tpidr, ThreadHnd); diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index f33d2ac8e..71edfbd69 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -182,22 +182,22 @@ namespace Ryujinx.Core.OsHle.Svc private ulong GetMapRegionBaseAddr() { - return 0x80000000; + return MemoryRegions.MapRegionAddress; } private ulong GetMapRegionSize() { - return 0x40000000; + return MemoryRegions.MapRegionSize; } private ulong GetHeapRegionBaseAddr() { - return GetMapRegionBaseAddr() + GetMapRegionSize(); + return MemoryRegions.HeapRegionAddress; } private ulong GetHeapRegionSize() { - return 0x40000000; + return MemoryRegions.HeapRegionSize; } private ulong GetTotalMem() diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index 6bf17d094..5ae5e2259 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -3,7 +3,6 @@ using OpenTK.Graphics.OpenGL; using System; using System.Collections.Generic; - namespace Ryujinx.Graphics.Gal.OpenGL { public class OpenGLRenderer : IGalRenderer @@ -29,8 +28,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL private FrameBuffer FbRenderer; - public long FrameBufferPtr { get; set; } - public OpenGLRenderer() { VertexBuffers = new List(); @@ -58,7 +55,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL { ActionsQueue.Dequeue()(); } - } + } public void Render() { diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs index 7912147ee..b5f8cb976 100644 --- a/Ryujinx/Ui/Program.cs +++ b/Ryujinx/Ui/Program.cs @@ -59,9 +59,7 @@ namespace Ryujinx Screen.Run(60.0); } - Ns.FinalizeAllProcesses(); - - Ns.Dispose(); + Environment.Exit(0); } } } From 035efc913e7f2a68315d4206cef46672005b8442 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 24 Feb 2018 11:19:28 -0300 Subject: [PATCH 18/67] Fix cpu issue with cmp optimization, add HINT and FRINTX (scalar) instructions, fix for NvFlinger sometimes missing free buffers --- ChocolArm64/AOpCodeTable.cs | 2 ++ ChocolArm64/ATranslator.cs | 6 ++--- ChocolArm64/Decoder/AOpCodeSimd.cs | 2 -- .../Instruction/AInstEmitSimdArithmetic.cs | 26 +++++++++++++++++++ ChocolArm64/Instruction/AInstEmitSystem.cs | 5 ++++ ChocolArm64/Instruction/ASoftFallback.cs | 26 +++++++++++++++++++ ChocolArm64/State/ARoundMode.cs | 10 +++++++ ChocolArm64/Translation/AILEmitterCtx.cs | 22 +++++++++------- Ryujinx.Core/OsHle/MemoryRegions.cs | 2 -- .../OsHle/Objects/Android/NvFlinger.cs | 19 ++++++++------ 10 files changed, 96 insertions(+), 24 deletions(-) create mode 100644 ChocolArm64/State/ARoundMode.cs diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index b8fe278dd..71a944cf8 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -51,6 +51,7 @@ namespace ChocolArm64 Set("x10100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm)); Set("x1001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs)); Set("x00100111x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs)); + Set("11010101000000110010xxxxxxx11111", AInstEmit.Hint, typeof(AOpCodeSystem)); Set("xx001000110xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldar, typeof(AOpCodeMemEx)); Set("1x001000011xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxp, typeof(AOpCodeMemEx)); Set("xx001000010xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxr, typeof(AOpCodeMemEx)); @@ -193,6 +194,7 @@ namespace ChocolArm64 Set("000111100x100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd)); Set("000111100x100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd)); Set("000111100x100100110000xxxxxxxxxx", AInstEmit.Frintp_S, typeof(AOpCodeSimd)); + Set("000111100x100111010000xxxxxxxxxx", AInstEmit.Frintx_S, typeof(AOpCodeSimd)); Set("000111100x100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd)); Set("000111100x1xxxxx001110xxxxxxxxxx", AInstEmit.Fsub_S, typeof(AOpCodeSimdReg)); Set("0>0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg)); diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs index 96bbc89ea..04cef44f1 100644 --- a/ChocolArm64/ATranslator.cs +++ b/ChocolArm64/ATranslator.cs @@ -6,7 +6,7 @@ using System.Reflection.Emit; namespace ChocolArm64 { - class ATranslator + public class ATranslator { public AThread Thread { get; private set; } @@ -41,7 +41,7 @@ namespace ChocolArm64 while (Position != 0 && KeepRunning); } - public bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) + internal bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) { if (OpCode.Emitter != AInstEmit.Bl) { @@ -53,7 +53,7 @@ namespace ChocolArm64 return TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub); } - public bool TryGetCachedSub(long Position, out ATranslatedSub Sub) + internal bool TryGetCachedSub(long Position, out ATranslatedSub Sub) { return CachedSubs.TryGetValue(Position, out Sub); } diff --git a/ChocolArm64/Decoder/AOpCodeSimd.cs b/ChocolArm64/Decoder/AOpCodeSimd.cs index 5f940b220..417085172 100644 --- a/ChocolArm64/Decoder/AOpCodeSimd.cs +++ b/ChocolArm64/Decoder/AOpCodeSimd.cs @@ -10,8 +10,6 @@ namespace ChocolArm64.Decoder public int Opc { get; private set; } public int Size { get; protected set; } - public int SizeF => Size & 1; - public AOpCodeSimd(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { Rd = (OpCode >> 0) & 0x1f; diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index 6665f219e..e1fd56e00 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -265,6 +265,32 @@ namespace ChocolArm64.Instruction }); } + public static void Frintx_S(AILEmitterCtx Context) + { + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + + EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); + + Context.EmitLdarg(ATranslatedSub.StateArgIdx); + + Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr)); + + if (Op.Size == 0) + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF)); + } + else if (Op.Size == 1) + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round)); + } + else + { + throw new InvalidOperationException(); + } + + EmitScalarSetF(Context, Op.Rd, Op.Size); + } + public static void Fsqrt_S(AILEmitterCtx Context) { EmitScalarUnaryOpF(Context, () => diff --git a/ChocolArm64/Instruction/AInstEmitSystem.cs b/ChocolArm64/Instruction/AInstEmitSystem.cs index 6754be7a8..f9d186020 100644 --- a/ChocolArm64/Instruction/AInstEmitSystem.cs +++ b/ChocolArm64/Instruction/AInstEmitSystem.cs @@ -9,6 +9,11 @@ namespace ChocolArm64.Instruction { static partial class AInstEmit { + public static void Hint(AILEmitterCtx Context) + { + //Execute as no-op. + } + public static void Mrs(AILEmitterCtx Context) { AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp; diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs index a57966baf..5127182dd 100644 --- a/ChocolArm64/Instruction/ASoftFallback.cs +++ b/ChocolArm64/Instruction/ASoftFallback.cs @@ -189,6 +189,32 @@ namespace ChocolArm64.Instruction (Value >> 6) & 1 + (Value >> 7); } + public static float RoundF(float Value, int Fpcr) + { + switch ((ARoundMode)((Fpcr >> 22) & 3)) + { + case ARoundMode.ToNearest: return MathF.Round (Value); + case ARoundMode.TowardsPlusInfinity: return MathF.Ceiling (Value); + case ARoundMode.TowardsMinusInfinity: return MathF.Floor (Value); + case ARoundMode.TowardsZero: return MathF.Truncate(Value); + } + + throw new InvalidOperationException(); + } + + public static double Round(double Value, int Fpcr) + { + switch ((ARoundMode)((Fpcr >> 22) & 3)) + { + case ARoundMode.ToNearest: return Math.Round (Value); + case ARoundMode.TowardsPlusInfinity: return Math.Ceiling (Value); + case ARoundMode.TowardsMinusInfinity: return Math.Floor (Value); + case ARoundMode.TowardsZero: return Math.Truncate(Value); + } + + throw new InvalidOperationException(); + } + public static AVec Tbl1_V64(AVec Vector, AVec Tb0) { return Tbl(Vector, 8, Tb0); diff --git a/ChocolArm64/State/ARoundMode.cs b/ChocolArm64/State/ARoundMode.cs new file mode 100644 index 000000000..9896f3075 --- /dev/null +++ b/ChocolArm64/State/ARoundMode.cs @@ -0,0 +1,10 @@ +namespace ChocolArm64.State +{ + public enum ARoundMode + { + ToNearest = 0, + TowardsPlusInfinity = 1, + TowardsMinusInfinity = 2, + TowardsZero = 3 + } +} \ No newline at end of file diff --git a/ChocolArm64/Translation/AILEmitterCtx.cs b/ChocolArm64/Translation/AILEmitterCtx.cs index cf6445401..9199eddc6 100644 --- a/ChocolArm64/Translation/AILEmitterCtx.cs +++ b/ChocolArm64/Translation/AILEmitterCtx.cs @@ -18,8 +18,8 @@ namespace ChocolArm64.Translation private AILBlock ILBlock; - private AOpCode LastCmpOp; - private AOpCode LastFlagOp; + private AOpCode OptOpLastCompare; + private AOpCode OptOpLastFlagSet; private int BlkIndex; private int OpcIndex; @@ -75,6 +75,9 @@ namespace ChocolArm64.Translation BlkIndex++; OpcIndex = -1; + OptOpLastFlagSet = null; + OptOpLastCompare = null; + ILBlock = Emitter.GetILBlock(BlkIndex); } @@ -120,7 +123,7 @@ namespace ChocolArm64.Translation public void TryOptMarkCondWithoutCmp() { - LastCmpOp = CurrOp; + OptOpLastCompare = CurrOp; AInstEmitAluHelper.EmitDataLoadOpers(this); @@ -146,14 +149,15 @@ namespace ChocolArm64.Translation { OpCode ILOp; - int IntCond = (int)Cond; + int IntCond = (int)Cond; - if (LastCmpOp != null && LastFlagOp == LastCmpOp && BranchOps.ContainsKey(Cond)) + if (OptOpLastCompare != null && + OptOpLastCompare == OptOpLastFlagSet && BranchOps.ContainsKey(Cond)) { - Ldloc(Tmp3Index, AIoType.Int, LastCmpOp.RegisterSize); - Ldloc(Tmp4Index, AIoType.Int, LastCmpOp.RegisterSize); + Ldloc(Tmp3Index, AIoType.Int, OptOpLastCompare.RegisterSize); + Ldloc(Tmp4Index, AIoType.Int, OptOpLastCompare.RegisterSize); - if (LastCmpOp.Emitter == AInstEmit.Adds) + if (OptOpLastCompare.Emitter == AInstEmit.Adds) { Emit(OpCodes.Neg); } @@ -356,7 +360,7 @@ namespace ChocolArm64.Translation public void EmitLdflg(int Index) => Ldloc(Index, AIoType.Flag); public void EmitStflg(int Index) { - LastFlagOp = CurrOp; + OptOpLastFlagSet = CurrOp; Stloc(Index, AIoType.Flag); } diff --git a/Ryujinx.Core/OsHle/MemoryRegions.cs b/Ryujinx.Core/OsHle/MemoryRegions.cs index e8ededc8f..86d266f60 100644 --- a/Ryujinx.Core/OsHle/MemoryRegions.cs +++ b/Ryujinx.Core/OsHle/MemoryRegions.cs @@ -1,5 +1,3 @@ -using ChocolArm64.Memory; - namespace Ryujinx.Core.OsHle { static class MemoryRegions diff --git a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs index 545883836..11069cb22 100644 --- a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs @@ -291,7 +291,10 @@ namespace Ryujinx.Core.OsHle.Objects.Android BufferQueue[Slot].State = BufferState.Free; - WaitBufferFree.Set(); + lock (WaitBufferFree) + { + WaitBufferFree.Set(); + } }); } @@ -317,15 +320,15 @@ namespace Ryujinx.Core.OsHle.Objects.Android do { - if ((Slot = GetFreeSlot(Width, Height)) != -1) - { - break; - } - - Logging.Debug("Waiting for a free BufferQueue slot..."); - lock (WaitBufferFree) { + if ((Slot = GetFreeSlot(Width, Height)) != -1) + { + break; + } + + Logging.Debug("Waiting for a free BufferQueue slot..."); + if (!KeepRunning) { break; From c02a2b510f4f461c96e4a98e0059f35b5dde97c9 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 24 Feb 2018 13:30:37 -0300 Subject: [PATCH 19/67] Fix build link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 975b23406..d2199244d 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,4 @@ Run `dotnet run -c Release -- path\to\game_exefs_and_romfs_folder` to run offici **Latest build** These builds are compiled automatically for each commit on the master branch. They may be unstable or not work at all. -To download the latest automatic build for Windows (64-bits), [Click Here](https://ci.appveyor.com/api/projects/gdkchan/ryujinx/artifacts/ryujinx_lastest_unstable.zip). +To download the latest automatic build for Windows (64-bits), [Click Here](https://ci.appveyor.com/api/projects/gdkchan/ryujinx/artifacts/ryujinx_latest_unstable.zip). From 31b35a9645524ce25f4bcbcd5f0df8b9784e6b52 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 24 Feb 2018 18:47:08 -0300 Subject: [PATCH 20/67] Add FABD (scalar), ADCS, SBCS instructions, update config with better default control mappings, update readme with the new mappings --- ChocolArm64/AOpCodeTable.cs | 3 ++ ChocolArm64/ATranslator.cs | 6 +-- ChocolArm64/Instruction/AInstEmitAlu.cs | 30 +++++++++++-- ChocolArm64/Instruction/AInstEmitAluHelper.cs | 19 ++++++++ .../Instruction/AInstEmitSimdArithmetic.cs | 45 +++++++++++-------- .../Instruction/AInstEmitSimdHelper.cs | 32 ++++++------- README.md | 44 +++++++++++------- Ryujinx/Ryujinx.conf | 40 ++++++++--------- 8 files changed, 138 insertions(+), 81 deletions(-) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 71a944cf8..14ca231ba 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -11,6 +11,7 @@ namespace ChocolArm64 #region "OpCode Table" //Integer Set("x0011010000xxxxx000000xxxxxxxxxx", AInstEmit.Adc, typeof(AOpCodeAluRs)); + Set("x0111010000xxxxx000000xxxxxxxxxx", AInstEmit.Adcs, typeof(AOpCodeAluRs)); Set("x00100010xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluImm)); Set("x0001011<<0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs)); Set("x0001011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRx)); @@ -90,6 +91,7 @@ namespace ChocolArm64 Set("1101101011000000000011xxxxxxxxxx", AInstEmit.Rev64, typeof(AOpCodeAlu)); Set("x0011010110xxxxx001011xxxxxxxxxx", AInstEmit.Rorv, typeof(AOpCodeAluRs)); Set("x1011010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbc, typeof(AOpCodeAluRs)); + Set("x1111010000xxxxx000000xxxxxxxxxx", AInstEmit.Sbcs, typeof(AOpCodeAluRs)); Set("x00100110xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sbfm, typeof(AOpCodeBfm)); Set("x0011010110xxxxx000011xxxxxxxxxx", AInstEmit.Sdiv, typeof(AOpCodeAluRs)); Set("10011011001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smaddl, typeof(AOpCodeMul)); @@ -145,6 +147,7 @@ namespace ChocolArm64 Set("01011110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_S, typeof(AOpCodeSimdIns)); Set("0x001110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_V, typeof(AOpCodeSimdIns)); Set("0x101110001xxxxx000111xxxxxxxxxx", AInstEmit.Eor_V, typeof(AOpCodeSimdReg)); + Set("011111101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fabd_S, typeof(AOpCodeSimdReg)); Set("000111100x100000110000xxxxxxxxxx", AInstEmit.Fabs_S, typeof(AOpCodeSimd)); Set("000111100x1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg)); Set("0>0011100<1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg)); diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs index 04cef44f1..96bbc89ea 100644 --- a/ChocolArm64/ATranslator.cs +++ b/ChocolArm64/ATranslator.cs @@ -6,7 +6,7 @@ using System.Reflection.Emit; namespace ChocolArm64 { - public class ATranslator + class ATranslator { public AThread Thread { get; private set; } @@ -41,7 +41,7 @@ namespace ChocolArm64 while (Position != 0 && KeepRunning); } - internal bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) + public bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) { if (OpCode.Emitter != AInstEmit.Bl) { @@ -53,7 +53,7 @@ namespace ChocolArm64 return TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub); } - internal bool TryGetCachedSub(long Position, out ATranslatedSub Sub) + public bool TryGetCachedSub(long Position, out ATranslatedSub Sub) { return CachedSubs.TryGetValue(Position, out Sub); } diff --git a/ChocolArm64/Instruction/AInstEmitAlu.cs b/ChocolArm64/Instruction/AInstEmitAlu.cs index 72903f5b3..71d9a6607 100644 --- a/ChocolArm64/Instruction/AInstEmitAlu.cs +++ b/ChocolArm64/Instruction/AInstEmitAlu.cs @@ -11,7 +11,10 @@ namespace ChocolArm64.Instruction { static partial class AInstEmit { - public static void Adc(AILEmitterCtx Context) + public static void Adc(AILEmitterCtx Context) => EmitAdc(Context, false); + public static void Adcs(AILEmitterCtx Context) => EmitAdc(Context, true); + + private static void EmitAdc(AILEmitterCtx Context, bool SetFlags) { EmitDataLoadOpers(Context); @@ -27,11 +30,19 @@ namespace ChocolArm64.Instruction if (Context.CurrOp.RegisterSize != ARegisterSize.Int32) { - Context.Emit(OpCodes.Conv_I8); + Context.Emit(OpCodes.Conv_U8); } Context.Emit(OpCodes.Add); + if (SetFlags) + { + Context.EmitZNFlagCheck(); + + EmitAddsCCheck(Context); + EmitAddsVCheck(Context); + } + EmitDataStore(Context); } @@ -145,7 +156,10 @@ namespace ChocolArm64.Instruction public static void Lslv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shl); public static void Lsrv(AILEmitterCtx Context) => EmitDataOpShift(Context, OpCodes.Shr_Un); - public static void Sbc(AILEmitterCtx Context) + public static void Sbc(AILEmitterCtx Context) => EmitSbc(Context, false); + public static void Sbcs(AILEmitterCtx Context) => EmitSbc(Context, true); + + private static void EmitSbc(AILEmitterCtx Context, bool SetFlags) { EmitDataLoadOpers(Context); @@ -165,11 +179,19 @@ namespace ChocolArm64.Instruction if (Context.CurrOp.RegisterSize != ARegisterSize.Int32) { - Context.Emit(OpCodes.Conv_I8); + Context.Emit(OpCodes.Conv_U8); } Context.Emit(OpCodes.Sub); + if (SetFlags) + { + Context.EmitZNFlagCheck(); + + EmitSbcsCCheck(Context); + EmitSubsVCheck(Context); + } + EmitDataStore(Context); } diff --git a/ChocolArm64/Instruction/AInstEmitAluHelper.cs b/ChocolArm64/Instruction/AInstEmitAluHelper.cs index e848742d0..b2ea92a65 100644 --- a/ChocolArm64/Instruction/AInstEmitAluHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitAluHelper.cs @@ -41,6 +41,25 @@ namespace ChocolArm64.Instruction Context.EmitStflg((int)APState.VBit); } + public static void EmitSbcsCCheck(AILEmitterCtx Context) + { + //C = (Rn == Rm && CIn) || Rn > Rm + EmitDataLoadOpers(Context); + + Context.Emit(OpCodes.Ceq); + + Context.EmitLdflg((int)APState.CBit); + + Context.Emit(OpCodes.And); + + EmitDataLoadOpers(Context); + + Context.Emit(OpCodes.Cgt_Un); + Context.Emit(OpCodes.Or); + + Context.EmitStflg((int)APState.CBit); + } + public static void EmitSubsCCheck(AILEmitterCtx Context) { //C = Rn == Rm || Rn > Rm = !(Rn < Rm) diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index e1fd56e00..e790d6786 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -101,6 +101,16 @@ namespace ChocolArm64.Instruction } } + public static void Fabd_S(AILEmitterCtx Context) + { + EmitScalarBinaryOpF(Context, () => + { + Context.Emit(OpCodes.Sub); + + EmitUnaryMathCall(Context, nameof(Math.Abs)); + }); + } + public static void Fabs_S(AILEmitterCtx Context) { EmitScalarUnaryOpF(Context, () => @@ -269,26 +279,25 @@ namespace ChocolArm64.Instruction { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); - - Context.EmitLdarg(ATranslatedSub.StateArgIdx); - - Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr)); - - if (Op.Size == 0) + EmitScalarUnaryOpF(Context, () => { - ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF)); - } - else if (Op.Size == 1) - { - ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round)); - } - else - { - throw new InvalidOperationException(); - } + Context.EmitLdarg(ATranslatedSub.StateArgIdx); - EmitScalarSetF(Context, Op.Rd, Op.Size); + Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr)); + + if (Op.Size == 0) + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF)); + } + else if (Op.Size == 1) + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round)); + } + else + { + throw new InvalidOperationException(); + } + }); } public static void Fsqrt_S(AILEmitterCtx Context) diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs index 20c8be26d..68ee3d3e4 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs @@ -36,20 +36,18 @@ namespace ChocolArm64.Instruction { IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp; + int SizeF = Op.Size & 1; + MethodInfo MthdInfo; - if (Op.Size == 0) + if (SizeF == 0) { MthdInfo = typeof(MathF).GetMethod(Name, new Type[] { typeof(float) }); } - else if (Op.Size == 1) + else /* if (SizeF == 1) */ { MthdInfo = typeof(Math).GetMethod(Name, new Type[] { typeof(double) }); } - else - { - throw new InvalidOperationException(); - } Context.EmitCall(MthdInfo); } @@ -58,20 +56,18 @@ namespace ChocolArm64.Instruction { IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp; + int SizeF = Op.Size & 1; + MethodInfo MthdInfo; - if (Op.Size == 0) + if (SizeF == 0) { MthdInfo = typeof(MathF).GetMethod(Name, new Type[] { typeof(float), typeof(float) }); } - else if (Op.Size == 1) + else /* if (SizeF == 1) */ { MthdInfo = typeof(Math).GetMethod(Name, new Type[] { typeof(double), typeof(double) }); } - else - { - throw new InvalidOperationException(); - } Context.EmitCall(MthdInfo); } @@ -80,28 +76,26 @@ namespace ChocolArm64.Instruction { IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp; + int SizeF = Op.Size & 1; + Context.EmitLdc_I4((int)RoundMode); MethodInfo MthdInfo; Type[] Types = new Type[] { null, typeof(MidpointRounding) }; - Types[0] = Op.Size == 0 + Types[0] = SizeF == 0 ? typeof(float) : typeof(double); - if (Op.Size == 0) + if (SizeF == 0) { MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types); } - else if (Op.Size == 1) + else /* if (SizeF == 1) */ { MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types); } - else - { - throw new InvalidOperationException(); - } Context.EmitCall(MthdInfo); } diff --git a/README.md b/README.md index d2199244d..6a2411279 100644 --- a/README.md +++ b/README.md @@ -18,23 +18,33 @@ Or just drag'n'drop the *.NRO / *.NSO or the game folder on the executable if yo https://openal.org/downloads/OpenAL11CoreSDK.zip - Keyboard Input is partially supported: - - Arrows. - - Enter > "Start" & Tab > "Select" - - Qwerty: - - A > "A" (QWERTY) / Q > "A" (AZERTY) - - S > "B" - - Z > "X" (QWERTY) / W > "X" (AZERTY) - - X > "Y" - - Key_Up > "Right Stick Up" - - Key_Down > "Right Stick Down" - - Key_Left > "Right Stick Left" - - Key_Right > "Right Stick Right" - - I > "Left Stick Up" - - K > "Left Stick Down" - - J > "Left Stick Left" - - L > "Left Stick Right" - - Tab > "Minus" - - Enter > "Plus" + - Left Joycon: + - Stick Up = W + - Stick Down = S + - Stick Left = A + - Stick Right = D + - Stick Button = F + - DPad Up = Up + - DPad Down = Down + - DPad Left = Left + - DPad Right = Right + - Minus = - + - L = E + - ZL = Q + + - Right Joycon: + - Stick Up = I + - Stick Down = K + - Stick Left = J + - Stick Right = L + - Stick Button = H + - A = Z + - B = X + - X = C + - Y = V + - Plus = + + - R = U + - ZR = O - Config File: `Ryujinx.conf` should be present in executable folder. For more informations [you can go here](CONFIG.md). diff --git a/Ryujinx/Ryujinx.conf b/Ryujinx/Ryujinx.conf index 8f791df31..7b9af87ac 100644 --- a/Ryujinx/Ryujinx.conf +++ b/Ryujinx/Ryujinx.conf @@ -20,28 +20,28 @@ Logging_Enable_Fatal = true Logging_Enable_LogFile = false #https://github.com/opentk/opentk/blob/develop/src/OpenTK/Input/Key.cs -Controls_Left_FakeJoycon_Stick_Up = 91 -Controls_Left_FakeJoycon_Stick_Down = 93 -Controls_Left_FakeJoycon_Stick_Left = 92 -Controls_Left_FakeJoycon_Stick_Right = 94 -Controls_Left_FakeJoycon_Stick_Button = 0 +Controls_Left_FakeJoycon_Stick_Up = 105 +Controls_Left_FakeJoycon_Stick_Down = 101 +Controls_Left_FakeJoycon_Stick_Left = 83 +Controls_Left_FakeJoycon_Stick_Right = 86 +Controls_Left_FakeJoycon_Stick_Button = 88 Controls_Left_FakeJoycon_DPad_Up = 45 Controls_Left_FakeJoycon_DPad_Down = 46 Controls_Left_FakeJoycon_DPad_Left = 47 Controls_Left_FakeJoycon_DPad_Right = 48 -Controls_Left_FakeJoycon_Button_Minus = 52 -Controls_Left_FakeJoycon_Button_L = 0 -Controls_Left_FakeJoycon_Button_ZL = 0 +Controls_Left_FakeJoycon_Button_Minus = 120 +Controls_Left_FakeJoycon_Button_L = 87 +Controls_Left_FakeJoycon_Button_ZL = 99 -Controls_Right_FakeJoycon_Stick_Up = 45 -Controls_Right_FakeJoycon_Stick_Down = 46 -Controls_Right_FakeJoycon_Stick_Left = 47 -Controls_Right_FakeJoycon_Stick_Right = 48 -Controls_Right_FakeJoycon_Stick_Button = 0 -Controls_Right_FakeJoycon_Button_A = 83 -Controls_Right_FakeJoycon_Button_B = 101 -Controls_Right_FakeJoycon_Button_X = 106 -Controls_Right_FakeJoycon_Button_Y = 108 -Controls_Right_FakeJoycon_Button_Plus = 49 -Controls_Right_FakeJoycon_Button_R = 0 -Controls_Right_FakeJoycon_Button_ZR = 0 +Controls_Right_FakeJoycon_Stick_Up = 91 +Controls_Right_FakeJoycon_Stick_Down = 93 +Controls_Right_FakeJoycon_Stick_Left = 92 +Controls_Right_FakeJoycon_Stick_Right = 94 +Controls_Right_FakeJoycon_Stick_Button = 90 +Controls_Right_FakeJoycon_Button_A = 108 +Controls_Right_FakeJoycon_Button_B = 106 +Controls_Right_FakeJoycon_Button_X = 85 +Controls_Right_FakeJoycon_Button_Y = 104 +Controls_Right_FakeJoycon_Button_Plus = 121 +Controls_Right_FakeJoycon_Button_R = 103 +Controls_Right_FakeJoycon_Button_ZR = 97 From c9f54aabfb7e5cffe0f384cada09a71c59298e03 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Sun, 25 Feb 2018 00:08:29 +0100 Subject: [PATCH 21/67] Update IpcHandler.cs (#39) Temporary Fix by Misson20000 --- Ryujinx.Core/OsHle/Ipc/IpcHandler.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs index 612d15eb0..5785dbf30 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs @@ -86,7 +86,7 @@ namespace Ryujinx.Core.OsHle.Ipc long CmdPtr, int HndId) { - IpcMessage Response = new IpcMessage(Request.IsDomain); + IpcMessage Response = new IpcMessage(Request.IsDomain && Request.Type == IpcMessageType.Request); using (MemoryStream Raw = new MemoryStream(Request.RawData)) { @@ -192,6 +192,7 @@ namespace Ryujinx.Core.OsHle.Ipc { case 0: Request = IpcConvertSessionToDomain(Ns, Session, Response, HndId); break; case 3: Request = IpcQueryBufferPointerSize(Response); break; + case 2: //IpcDuplicateSession, differences is unknown. case 4: Request = IpcDuplicateSessionEx(Ns, Session, Response, ReqReader); break; default: throw new NotImplementedException(CmdId.ToString()); @@ -280,4 +281,4 @@ namespace Ryujinx.Core.OsHle.Ipc return Response; } } -} \ No newline at end of file +} From 8fa26a18c58c773dd0f3cf0190bd30f8d2d1430d Mon Sep 17 00:00:00 2001 From: Ac_K Date: Sun, 25 Feb 2018 00:08:54 +0100 Subject: [PATCH 22/67] Update IpcMessage.cs (#38) Temporary Fix by Misson20000 --- Ryujinx.Core/OsHle/Ipc/IpcMessage.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs index 3b38c4516..447f3f9a6 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs @@ -108,7 +108,7 @@ namespace Ryujinx.Core.OsHle.Ipc RecvListCount = 0; } - if (Domain) + if (Domain && Type == IpcMessageType.Request) { int DomWord0 = Reader.ReadInt32(); @@ -228,4 +228,4 @@ namespace Ryujinx.Core.OsHle.Ipc return -1; } } -} \ No newline at end of file +} From e90a0f0e33099565ab25cccfb0f62abe49930b7a Mon Sep 17 00:00:00 2001 From: Ac_K Date: Sun, 25 Feb 2018 00:09:10 +0100 Subject: [PATCH 23/67] Update SvcSystem.cs (#40) * Update SvcSystem.cs Implement SvcGetInfo 0 * Update SvcSystem.cs --- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index 71edfbd69..a69d3b409 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -161,6 +161,7 @@ namespace Ryujinx.Core.OsHle.Svc switch (InfoType) { + case 0: ThreadState.X1 = AllowedCpuIdBitmask(); break; case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break; case 3: ThreadState.X1 = GetMapRegionSize(); break; case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break; @@ -179,6 +180,11 @@ namespace Ryujinx.Core.OsHle.Svc ThreadState.X0 = (int)SvcResult.Success; } + + private ulong AllowedCpuIdBitmask() + { + return 0xF; //Mephisto value. + } private ulong GetMapRegionBaseAddr() { @@ -230,4 +236,4 @@ namespace Ryujinx.Core.OsHle.Svc return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr(); } } -} \ No newline at end of file +} From a4ff0d34848416a68dff9f165bb90afae7a4fd20 Mon Sep 17 00:00:00 2001 From: MS-DOS1999 Date: Sun, 25 Feb 2018 02:50:58 +0100 Subject: [PATCH 24/67] Update ADC test, add WZR/WSP, ADCS, SBCS test (#37) * add 'ADC 32bit and Overflow' test * Add WZR/WSP tests * fix ADC and ADDS * add ADCS test * add SBCS test * indent my code and delete comment * '/' <- i hate you x) * remove spacebar char * remove false tab --- Ryujinx.Tests/Cpu/CpuTest.cs | 7 ++-- Ryujinx.Tests/Cpu/CpuTestAlu.cs | 64 +++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index 92c74e443..7af2d55d0 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -57,13 +57,14 @@ namespace Ryujinx.Tests.Cpu Position += 4; } - protected void SetThreadState(ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, + protected void SetThreadState(ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X31 = 0, AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec), bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false) { Thread.ThreadState.X0 = X0; Thread.ThreadState.X1 = X1; Thread.ThreadState.X2 = X2; + Thread.ThreadState.X31 = X31; Thread.ThreadState.V0 = V0; Thread.ThreadState.V1 = V1; Thread.ThreadState.V2 = V2; @@ -91,14 +92,14 @@ namespace Ryujinx.Tests.Cpu } protected AThreadState SingleOpcode(uint Opcode, - ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, + ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X31 = 0, AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec), bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false) { this.Opcode(Opcode); this.Opcode(0xD4200000); // BRK #0 this.Opcode(0xD65F03C0); // RET - SetThreadState(X0, X1, X2, V0, V1, V2, Overflow, Carry, Zero, Negative); + SetThreadState(X0, X1, X2, X31, V0, V1, V2, Overflow, Carry, Zero, Negative); ExecuteOpcodes(); return GetThreadState(); diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu.cs b/Ryujinx.Tests/Cpu/CpuTestAlu.cs index b73212ac5..0445c97ab 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu.cs @@ -5,12 +5,31 @@ namespace Ryujinx.Tests.Cpu { public class CpuTestAlu : CpuTest { - [TestCase(2u, 3u, 6ul, true)] - [TestCase(2u, 3u, 5ul, false)] - public void Adc(uint A, uint B, ulong Result, bool CarryTest) + [TestCase(0x9A020020u, 2u, 3u, true, 6u)] + [TestCase(0x9A020020u, 2u, 3u, false, 5u)] + [TestCase(0x1A020020u, 2u, 3u, true, 6u)] + [TestCase(0x1A020020u, 2u, 3u, false, 5u)] + [TestCase(0x1A020020u, 0xFFFFFFFFu, 0x2u, false, 0x1u)] + public void Adc(uint Opcode, uint A, uint B, bool CarryState, uint Result) { - // ADC X0, X1, X2 - AThreadState ThreadState = SingleOpcode(0x9A020020, X1: A, X2: B, Carry: CarryTest); + // ADC (X0/W0), (X1/W1), (X2/W2) + AThreadState ThreadState = SingleOpcode(Opcode, X1: A, X2: B, Carry: CarryState); + Assert.AreEqual(Result, ThreadState.X0); + } + + [TestCase(0x3A020020u, 2u, 3u, false, false, false, 5u)] + [TestCase(0x3A020020u, 2u, 3u, true, false, false, 6u)] + [TestCase(0xBA020020u, 2u, 3u, false, false, false, 5u)] + [TestCase(0xBA020020u, 2u, 3u, true, false, false, 6u)] + [TestCase(0x3A020020u, 0xFFFFFFFEu, 0x1u, true, true, true, 0x0u)] + public void Adcs(uint Opcode, uint A, uint B, bool CarryState, bool Zero, bool Carry, uint Result) + { + //ADCS (X0/W0), (X1, W1), (X2/W2) + AThreadState ThreadState = SingleOpcode(Opcode, X1: A, X2: B, Carry: CarryState); + Assert.IsFalse(ThreadState.Negative); + Assert.IsFalse(ThreadState.Overflow); + Assert.AreEqual(Zero, ThreadState.Zero); + Assert.AreEqual(Carry, ThreadState.Carry); Assert.AreEqual(Result, ThreadState.X0); } @@ -22,7 +41,23 @@ namespace Ryujinx.Tests.Cpu Assert.AreEqual(3, ThreadState.X0); } - [TestCase(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFul, true, false)] + [TestCase(2u, false, false)] + [TestCase(5u, false, false)] + [TestCase(7u, false, false)] + [TestCase(0xFFFFFFFFu, false, true )] + [TestCase(0xFFFFFFFBu, true, true )] + public void Adds(uint A, bool Zero, bool Carry) + { + //ADDS WZR, WSP, #5 + AThreadState ThreadState = SingleOpcode(0x310017FF, X31: A); + Assert.IsFalse(ThreadState.Negative); + Assert.AreEqual(Zero, ThreadState.Zero); + Assert.AreEqual(Carry, ThreadState.Carry); + Assert.IsFalse(ThreadState.Overflow); + Assert.AreEqual(A, ThreadState.X31); + } + + [TestCase(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFul, true, false)] [TestCase(0xFFFFFFFFu, 0x00000000u, 0x00000000ul, false, true)] [TestCase(0x12345678u, 0x7324A993u, 0x12240010ul, false, false)] public void Ands(uint A, uint B, ulong Result, bool Negative, bool Zero) @@ -67,5 +102,22 @@ namespace Ryujinx.Tests.Cpu AThreadState ThreadState = SingleOpcode(0x5AC00821, X1: 0x12345678); Assert.AreEqual(0x78563412, ThreadState.X1); } + + [TestCase(0x7A020020u, 4u, 2u, false, false, false, true, 1u)] + [TestCase(0x7A020020u, 4u, 2u, true, false, false, true, 2u)] + [TestCase(0xFA020020u, 4u, 2u, false, false, false, true, 1u)] + [TestCase(0xFA020020u, 4u, 2u, true, false, false, true, 2u)] + [TestCase(0x7A020020u, 4u, 4u, false, true, false, false, 0xFFFFFFFFu)] + [TestCase(0x7A020020u, 4u, 4u, true, false, true, true, 0x0u)] + public void Sbcs(uint Opcode, uint A, uint B, bool CarryState, bool Negative, bool Zero, bool Carry, uint Result) + { + //SBCS (X0/W0), (X1, W1), (X2/W2) + AThreadState ThreadState = SingleOpcode(Opcode, X1: A, X2: B, Carry: CarryState); + Assert.AreEqual(Negative, ThreadState.Negative); + Assert.IsFalse(ThreadState.Overflow); + Assert.AreEqual(Zero, ThreadState.Zero); + Assert.AreEqual(Carry, ThreadState.Carry); + Assert.AreEqual(Result, ThreadState.X0); + } } } From fba0bf873257c4ac17f4584036661be08a1694d3 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 25 Feb 2018 01:34:16 -0300 Subject: [PATCH 25/67] Refactor IPC services to have commands into separate classes, fix readme url --- README.md | 2 +- Ryujinx.Core/OsHle/Handles/HSession.cs | 10 +- Ryujinx.Core/OsHle/Ipc/IpcHandler.cs | 78 ++------------- .../Acc/IManagerForApplication.cs | 4 +- .../{Objects => IpcServices}/Acc/IProfile.cs | 4 +- .../OsHle/IpcServices/Acc/ServiceAcc.cs | 49 ++++++++++ .../Am/IApplicationFunctions.cs | 6 +- .../Am/IApplicationProxy.cs | 6 +- .../Am/IAudioController.cs | 4 +- .../Am/ICommonStateGetter.cs | 4 +- .../Am/IDebugFunctions.cs | 4 +- .../Am/IDisplayController.cs | 4 +- .../Am/ILibraryAppletCreator.cs | 4 +- .../Am/ISelfController.cs | 4 +- .../{Objects => IpcServices}/Am/IStorage.cs | 6 +- .../Am/IStorageAccessor.cs | 4 +- .../Am/IWindowController.cs | 4 +- .../OsHle/IpcServices/Am/ServiceAppletOE.cs | 29 ++++++ .../Android/GbpBuffer.cs | 2 +- .../Android/NvFlinger.cs | 4 +- .../Android/Parcel.cs | 2 +- .../{Objects => IpcServices}/Apm/ISession.cs | 4 +- .../OsHle/IpcServices/Apm/ServiceApm.cs | 29 ++++++ .../{Objects => IpcServices}/Aud/IAudioOut.cs | 4 +- .../Aud/IAudioRenderer.cs | 4 +- .../OsHle/IpcServices/Aud/ServiceAudOut.cs | 57 +++++++++++ .../OsHle/IpcServices/Aud/ServiceAudRen.cs | 51 ++++++++++ .../{Objects => IpcServices}/ErrorCode.cs | 2 +- .../{Objects => IpcServices}/ErrorModule.cs | 2 +- .../Friend/IFriendService.cs | 4 +- .../OsHle/IpcServices/Friend/ServiceFriend.cs | 29 ++++++ .../{Objects => IpcServices}/FspSrv/FsErr.cs | 2 +- .../FspSrv/IDirectory.cs | 4 +- .../{Objects => IpcServices}/FspSrv/IFile.cs | 4 +- .../FspSrv/IFileSystem.cs | 8 +- .../FspSrv/IStorage.cs | 4 +- .../OsHle/IpcServices/FspSrv/ServiceFspSrv.cs | 67 +++++++++++++ .../Hid/IActiveVibrationDeviceList.cs | 4 +- .../Hid/IAppletResource.cs | 4 +- .../OsHle/IpcServices/Hid/ServiceHid.cs | 98 +++++++++++++++++++ .../IIpcService.cs} | 4 +- .../OsHle/IpcServices/Lm/ServiceLm.cs | 27 +++++ .../NvServices}/ServiceNvDrv.cs | 41 +++++--- .../{Objects => IpcServices}/ObjHelper.cs | 2 +- .../Pctl}/IParentalControlService.cs | 4 +- .../OsHle/IpcServices/Pctl/ServicePctl.cs | 29 ++++++ .../OsHle/IpcServices/Pl/ServicePl.cs | 51 ++++++++++ .../OsHle/IpcServices/ServiceFactory.cs | 50 ++++++++++ .../Set}/ServiceSet.cs | 20 +++- .../{Services => IpcServices/Sm}/ServiceSm.cs | 29 +++++- .../Time/ISteadyClock.cs | 4 +- .../Time/ISystemClock.cs | 4 +- .../Time/ITimeZoneService.cs | 4 +- .../OsHle/IpcServices/Time/ServiceTime.cs | 62 ++++++++++++ .../Time/SystemClockType.cs | 2 +- .../Vi/IApplicationDisplayService.cs | 8 +- .../Vi/IHOSBinderDriver.cs | 6 +- .../Vi/IManagerDisplayService.cs | 4 +- .../Vi/ISystemDisplayService.cs | 4 +- .../OsHle/IpcServices/Vi/ServiceVi.cs | 31 ++++++ Ryujinx.Core/OsHle/Services/ServiceAcc.cs | 33 ------- Ryujinx.Core/OsHle/Services/ServiceApm.cs | 16 --- .../OsHle/Services/ServiceAppletOE.cs | 16 --- Ryujinx.Core/OsHle/Services/ServiceAud.cs | 71 -------------- Ryujinx.Core/OsHle/Services/ServiceFriend.cs | 16 --- Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs | 49 ---------- Ryujinx.Core/OsHle/Services/ServiceHid.cs | 77 --------------- Ryujinx.Core/OsHle/Services/ServiceLm.cs | 12 --- Ryujinx.Core/OsHle/Services/ServicePctl.cs | 16 --- Ryujinx.Core/OsHle/Services/ServicePl.cs | 35 ------- Ryujinx.Core/OsHle/Services/ServiceTime.cs | 45 --------- Ryujinx.Core/OsHle/Services/ServiceVi.cs | 18 ---- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 3 +- 73 files changed, 825 insertions(+), 583 deletions(-) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Acc/IManagerForApplication.cs (88%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Acc/IProfile.cs (91%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/IApplicationFunctions.cs (93%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/IApplicationProxy.cs (93%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/IAudioController.cs (82%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/ICommonStateGetter.cs (95%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/IDebugFunctions.cs (82%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/IDisplayController.cs (82%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/ILibraryAppletCreator.cs (82%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/ISelfController.cs (95%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/IStorage.cs (83%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/IStorageAccessor.cs (94%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Am/IWindowController.cs (89%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Android/GbpBuffer.cs (97%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Android/NvFlinger.cs (99%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Android/Parcel.cs (96%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Apm/ISession.cs (89%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Aud/IAudioOut.cs (98%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Aud/IAudioRenderer.cs (96%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs rename Ryujinx.Core/OsHle/{Objects => IpcServices}/ErrorCode.cs (81%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/ErrorModule.cs (55%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Friend/IFriendService.cs (82%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs rename Ryujinx.Core/OsHle/{Objects => IpcServices}/FspSrv/FsErr.cs (79%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/FspSrv/IDirectory.cs (97%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/FspSrv/IFile.cs (96%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/FspSrv/IFileSystem.cs (98%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/FspSrv/IStorage.cs (94%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Hid/IActiveVibrationDeviceList.cs (79%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Hid/IAppletResource.cs (89%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs rename Ryujinx.Core/OsHle/{Objects/IIpcInterface.cs => IpcServices/IIpcService.cs} (69%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs rename Ryujinx.Core/OsHle/{Services => IpcServices/NvServices}/ServiceNvDrv.cs (94%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/ObjHelper.cs (93%) rename Ryujinx.Core/OsHle/{Objects/Am => IpcServices/Pctl}/IParentalControlService.cs (81%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs create mode 100644 Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs rename Ryujinx.Core/OsHle/{Services => IpcServices/Set}/ServiceSet.cs (57%) rename Ryujinx.Core/OsHle/{Services => IpcServices/Sm}/ServiceSm.cs (56%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Time/ISteadyClock.cs (83%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Time/ISystemClock.cs (92%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Time/ITimeZoneService.cs (82%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Time/SystemClockType.cs (64%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Vi/IApplicationDisplayService.cs (96%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Vi/IHOSBinderDriver.cs (93%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Vi/IManagerDisplayService.cs (89%) rename Ryujinx.Core/OsHle/{Objects => IpcServices}/Vi/ISystemDisplayService.cs (85%) create mode 100644 Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceAcc.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceApm.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceAud.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceFriend.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceHid.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceLm.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServicePctl.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServicePl.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceTime.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceVi.cs diff --git a/README.md b/README.md index 6a2411279..841a8258c 100644 --- a/README.md +++ b/README.md @@ -67,4 +67,4 @@ Run `dotnet run -c Release -- path\to\game_exefs_and_romfs_folder` to run offici **Latest build** These builds are compiled automatically for each commit on the master branch. They may be unstable or not work at all. -To download the latest automatic build for Windows (64-bits), [Click Here](https://ci.appveyor.com/api/projects/gdkchan/ryujinx/artifacts/ryujinx_latest_unstable.zip). +To download the latest automatic build for Windows (64-bits), [Click Here](https://ci.appveyor.com/api/projects/gdkchan/ryujinx/artifacts/ryujinx_latest_unstable.zip?pr=false). diff --git a/Ryujinx.Core/OsHle/Handles/HSession.cs b/Ryujinx.Core/OsHle/Handles/HSession.cs index 8aa1c06bc..f30e91f98 100644 --- a/Ryujinx.Core/OsHle/Handles/HSession.cs +++ b/Ryujinx.Core/OsHle/Handles/HSession.cs @@ -1,21 +1,23 @@ +using Ryujinx.Core.OsHle.IpcServices; + namespace Ryujinx.Core.OsHle.Handles { class HSession { - public string ServiceName { get; private set; } + public IIpcService Service { get; private set; } public bool IsInitialized { get; private set; } public int State { get; set; } - public HSession(string ServiceName) + public HSession(IIpcService Service) { - this.ServiceName = ServiceName; + this.Service = Service; } public HSession(HSession Session) { - ServiceName = Session.ServiceName; + Service = Session.Service; IsInitialized = Session.IsInitialized; } diff --git a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs index 5785dbf30..2495d7014 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs @@ -1,79 +1,13 @@ using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Objects; -using Ryujinx.Core.OsHle.Services; +using Ryujinx.Core.OsHle.IpcServices; using System; -using System.Collections.Generic; using System.IO; namespace Ryujinx.Core.OsHle.Ipc { static class IpcHandler { - private static Dictionary<(string, int), ServiceProcessRequest> ServiceCmds = - new Dictionary<(string, int), ServiceProcessRequest>() - { - { ( "acc:u0", 3), Service.AccU0ListOpenUsers }, - { ( "acc:u0", 5), Service.AccU0GetProfile }, - { ( "acc:u0", 100), Service.AccU0InitializeApplicationInfo }, - { ( "acc:u0", 101), Service.AccU0GetBaasAccountManagerForApplication }, - { ( "apm", 0), Service.ApmOpenSession }, - { ( "apm:p", 0), Service.ApmOpenSession }, - { ( "appletOE", 0), Service.AppletOpenApplicationProxy }, - { ( "audout:u", 0), Service.AudOutListAudioOuts }, - { ( "audout:u", 1), Service.AudOutOpenAudioOut }, - { ( "audren:u", 0), Service.AudRenOpenAudioRenderer }, - { ( "audren:u", 1), Service.AudRenGetAudioRendererWorkBufferSize }, - { ( "friend:a", 0), Service.FriendCreateFriendService }, - { ( "fsp-srv", 1), Service.FspSrvInitialize }, - { ( "fsp-srv", 18), Service.FspSrvMountSdCard }, - { ( "fsp-srv", 51), Service.FspSrvMountSaveData }, - { ( "fsp-srv", 200), Service.FspSrvOpenDataStorageByCurrentProcess }, - { ( "fsp-srv", 203), Service.FspSrvOpenRomStorage }, - { ( "fsp-srv", 1005), Service.FspSrvGetGlobalAccessLogMode }, - { ( "hid", 0), Service.HidCreateAppletResource }, - { ( "hid", 11), Service.HidActivateTouchScreen }, - { ( "hid", 100), Service.HidSetSupportedNpadStyleSet }, - { ( "hid", 101), Service.HidGetSupportedNpadStyleSet }, - { ( "hid", 102), Service.HidSetSupportedNpadIdType }, - { ( "hid", 103), Service.HidActivateNpad }, - { ( "hid", 120), Service.HidSetNpadJoyHoldType }, - { ( "hid", 121), Service.HidGetNpadJoyHoldType }, - { ( "hid", 203), Service.HidCreateActiveVibrationDeviceList }, - { ( "lm", 0), Service.LmInitialize }, - { ( "nvdrv", 0), Service.NvDrvOpen }, - { ( "nvdrv", 1), Service.NvDrvIoctl }, - { ( "nvdrv", 2), Service.NvDrvClose }, - { ( "nvdrv", 3), Service.NvDrvInitialize }, - { ( "nvdrv", 4), Service.NvDrvQueryEvent }, - { ( "nvdrv", 8), Service.NvDrvSetClientPid }, - { ( "nvdrv:a", 0), Service.NvDrvOpen }, - { ( "nvdrv:a", 1), Service.NvDrvIoctl }, - { ( "nvdrv:a", 2), Service.NvDrvClose }, - { ( "nvdrv:a", 3), Service.NvDrvInitialize }, - { ( "nvdrv:a", 4), Service.NvDrvQueryEvent }, - { ( "nvdrv:a", 8), Service.NvDrvSetClientPid }, - { ( "pctl:a", 0), Service.PctlCreateService }, - { ( "pl:u", 1), Service.PlGetLoadState }, - { ( "pl:u", 2), Service.PlGetFontSize }, - { ( "pl:u", 3), Service.PlGetSharedMemoryAddressOffset }, - { ( "pl:u", 4), Service.PlGetSharedMemoryNativeHandle }, - { ( "set", 1), Service.SetGetAvailableLanguageCodes }, - { ( "sm:", 0), Service.SmInitialize }, - { ( "sm:", 1), Service.SmGetService }, - { ( "time:u", 0), Service.TimeGetStandardUserSystemClock }, - { ( "time:u", 1), Service.TimeGetStandardNetworkSystemClock }, - { ( "time:u", 2), Service.TimeGetStandardSteadyClock }, - { ( "time:u", 3), Service.TimeGetTimeZoneService }, - { ( "time:u", 4), Service.TimeGetStandardLocalSystemClock }, - { ( "time:s", 0), Service.TimeGetStandardUserSystemClock }, - { ( "time:s", 1), Service.TimeGetStandardNetworkSystemClock }, - { ( "time:s", 2), Service.TimeGetStandardSteadyClock }, - { ( "time:s", 3), Service.TimeGetTimeZoneService }, - { ( "time:s", 4), Service.TimeGetStandardLocalSystemClock }, - { ( "vi:m", 2), Service.ViGetDisplayService }, - }; - private const long SfciMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'I' << 24; private const long SfcoMagic = 'S' << 0 | 'F' << 8 | 'C' << 16 | 'O' << 24; @@ -94,7 +28,7 @@ namespace Ryujinx.Core.OsHle.Ipc if (Request.Type == IpcMessageType.Request) { - string ServiceName = Session.ServiceName; + string ServiceName = Session.Service.GetType().Name; ServiceProcessRequest ProcReq = null; @@ -113,13 +47,13 @@ namespace Ryujinx.Core.OsHle.Ipc if (Obj is HDomain) { - ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq); + Session.Service.Commands.TryGetValue(CmdId, out ProcReq); DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}"; } else if (Obj != null) { - ((IIpcInterface)Obj).Commands.TryGetValue(CmdId, out ProcReq); + ((IIpcService)Obj).Commands.TryGetValue(CmdId, out ProcReq); DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}"; } @@ -142,13 +76,13 @@ namespace Ryujinx.Core.OsHle.Ipc { object Obj = ((HSessionObj)Session).Obj; - ((IIpcInterface)Obj).Commands.TryGetValue(CmdId, out ProcReq); + ((IIpcService)Obj).Commands.TryGetValue(CmdId, out ProcReq); DbgServiceName = $"{Obj.GetType().Name} {ProcReq?.Method.Name ?? CmdId.ToString()}"; } else { - ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq); + Session.Service.Commands.TryGetValue(CmdId, out ProcReq); DbgServiceName = $"{ProcReq?.Method.Name ?? CmdId.ToString()}"; } diff --git a/Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs b/Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs similarity index 88% rename from Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs rename to Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs index afbfab240..ab491eac7 100644 --- a/Ryujinx.Core/OsHle/Objects/Acc/IManagerForApplication.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Acc +namespace Ryujinx.Core.OsHle.IpcServices.Acc { - class IManagerForApplication : IIpcInterface + class IManagerForApplication : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs b/Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs similarity index 91% rename from Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs rename to Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs index 94d171833..77fe2b48c 100644 --- a/Ryujinx.Core/OsHle/Objects/Acc/IProfile.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Acc +namespace Ryujinx.Core.OsHle.IpcServices.Acc { - class IProfile : IIpcInterface + class IProfile : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs b/Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs new file mode 100644 index 000000000..8844bb5d1 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs @@ -0,0 +1,49 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Acc +{ + class ServiceAcc : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceAcc() + { + m_Commands = new Dictionary() + { + { 3, ListOpenUsers }, + { 5, GetProfile }, + { 100, InitializeApplicationInfo }, + { 101, GetBaasAccountManagerForApplication } + }; + } + + public long ListOpenUsers(ServiceCtx Context) + { + return 0; + } + + public long GetProfile(ServiceCtx Context) + { + MakeObject(Context, new IProfile()); + + return 0; + } + + public long InitializeApplicationInfo(ServiceCtx Context) + { + return 0; + } + + public long GetBaasAccountManagerForApplication(ServiceCtx Context) + { + MakeObject(Context, new IManagerForApplication()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs similarity index 93% rename from Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs index 939ad2486..30020c1d8 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IApplicationFunctions.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs @@ -2,11 +2,11 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; using System.IO; -using static Ryujinx.Core.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class IApplicationFunctions : IIpcInterface + class IApplicationFunctions : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs similarity index 93% rename from Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs index 4a164daf1..5417d7f04 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IApplicationProxy.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs @@ -1,11 +1,11 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -using static Ryujinx.Core.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class IApplicationProxy : IIpcInterface + class IApplicationProxy : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs similarity index 82% rename from Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs index c37042fdb..1212f1e24 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IAudioController.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class IAudioController : IIpcInterface + class IAudioController : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs b/Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs similarity index 95% rename from Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs index 83d61fa64..2999bbbae 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/ICommonStateGetter.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class ICommonStateGetter : IIpcInterface + class ICommonStateGetter : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs similarity index 82% rename from Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs index d04d8363f..944e58d81 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IDebugFunctions.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class IDebugFunctions : IIpcInterface + class IDebugFunctions : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs similarity index 82% rename from Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs index 9eafa70dc..979e842a6 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IDisplayController.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class IDisplayController : IIpcInterface + class IDisplayController : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs b/Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs similarity index 82% rename from Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs index 10e0f4f4a..9f5b5e69c 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/ILibraryAppletCreator.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class ILibraryAppletCreator : IIpcInterface + class ILibraryAppletCreator : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs b/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs similarity index 95% rename from Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs index 712874e87..90ddd54b8 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/ISelfController.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class ISelfController : IIpcInterface + class ISelfController : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/IStorage.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs similarity index 83% rename from Ryujinx.Core/OsHle/Objects/Am/IStorage.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs index b30059ba2..375b960b1 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IStorage.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs @@ -1,11 +1,11 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -using static Ryujinx.Core.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class IStorage : IIpcInterface + class IStorage : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs similarity index 94% rename from Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs index df260cc3e..6d83e6f94 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IStorageAccessor.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs @@ -3,9 +3,9 @@ using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class IStorageAccessor : IIpcInterface + class IStorageAccessor : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs b/Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs similarity index 89% rename from Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs rename to Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs index aa6e961e0..ddc73bced 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IWindowController.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Am { - class IWindowController : IIpcInterface + class IWindowController : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs new file mode 100644 index 000000000..b60c93dd5 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Am +{ + class ServiceAppletOE : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceAppletOE() + { + m_Commands = new Dictionary() + { + { 0, OpenApplicationProxy } + }; + } + + public long OpenApplicationProxy(ServiceCtx Context) + { + MakeObject(Context, new IApplicationProxy()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs b/Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs similarity index 97% rename from Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs rename to Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs index edd115237..5fe585d06 100644 --- a/Ryujinx.Core/OsHle/Objects/Android/GbpBuffer.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Ryujinx.Core.OsHle.Objects.Android +namespace Ryujinx.Core.OsHle.IpcServices.Android { struct GbpBuffer { diff --git a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs similarity index 99% rename from Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs rename to Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs index 11069cb22..85a06cea4 100644 --- a/Ryujinx.Core/OsHle/Objects/Android/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text; using System.Threading; -using static Ryujinx.Core.OsHle.Objects.Android.Parcel; +using static Ryujinx.Core.OsHle.IpcServices.Android.Parcel; -namespace Ryujinx.Core.OsHle.Objects.Android +namespace Ryujinx.Core.OsHle.IpcServices.Android { class NvFlinger : IDisposable { diff --git a/Ryujinx.Core/OsHle/Objects/Android/Parcel.cs b/Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs similarity index 96% rename from Ryujinx.Core/OsHle/Objects/Android/Parcel.cs rename to Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs index cd7179e1e..3404c227e 100644 --- a/Ryujinx.Core/OsHle/Objects/Android/Parcel.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Ryujinx.Core.OsHle.Objects.Android +namespace Ryujinx.Core.OsHle.IpcServices.Android { static class Parcel { diff --git a/Ryujinx.Core/OsHle/Objects/Apm/ISession.cs b/Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs similarity index 89% rename from Ryujinx.Core/OsHle/Objects/Apm/ISession.cs rename to Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs index 3ab330055..500f7596c 100644 --- a/Ryujinx.Core/OsHle/Objects/Apm/ISession.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Apm +namespace Ryujinx.Core.OsHle.IpcServices.Apm { - class ISession : IIpcInterface + class ISession : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs b/Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs new file mode 100644 index 000000000..d6c0400ac --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Apm +{ + class ServiceApm : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceApm() + { + m_Commands = new Dictionary() + { + { 0, OpenSession } + }; + } + + public long OpenSession(ServiceCtx Context) + { + MakeObject(Context, new ISession()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs similarity index 98% rename from Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs rename to Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs index 061c63763..a45b23ccd 100644 --- a/Ryujinx.Core/OsHle/Objects/Aud/IAudioOut.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs @@ -7,9 +7,9 @@ using System; using System.Collections.Generic; using System.IO; -namespace Ryujinx.Core.OsHle.Objects.Aud +namespace Ryujinx.Core.OsHle.IpcServices.Aud { - class IAudioOut : IIpcInterface + class IAudioOut : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs similarity index 96% rename from Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs rename to Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs index 053564773..bfde0b65b 100644 --- a/Ryujinx.Core/OsHle/Objects/Aud/IAudioRenderer.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs @@ -2,9 +2,9 @@ using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Aud +namespace Ryujinx.Core.OsHle.IpcServices.Aud { - class IAudioRenderer : IIpcInterface + class IAudioRenderer : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs b/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs new file mode 100644 index 000000000..eb923562b --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs @@ -0,0 +1,57 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; +using System.Text; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Aud +{ + class ServiceAudOut : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceAudOut() + { + m_Commands = new Dictionary() + { + { 0, ListAudioOuts }, + { 1, OpenAudioOut }, + }; + } + + public long ListAudioOuts(ServiceCtx Context) + { + long Position = Context.Request.ReceiveBuff[0].Position; + + AMemoryHelper.WriteBytes(Context.Memory, Position, Encoding.ASCII.GetBytes("iface")); + + Context.ResponseData.Write(1); + + return 0; + } + + public long OpenAudioOut(ServiceCtx Context) + { + MakeObject(Context, new IAudioOut()); + + Context.ResponseData.Write(48000); //Sample Rate + Context.ResponseData.Write(2); //Channel Count + Context.ResponseData.Write(2); //PCM Format + /* + 0 - Invalid + 1 - INT8 + 2 - INT16 + 3 - INT24 + 4 - INT32 + 5 - PCM Float + 6 - ADPCM + */ + Context.ResponseData.Write(0); //Unknown + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs b/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs new file mode 100644 index 000000000..eccc699c4 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs @@ -0,0 +1,51 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Aud +{ + class ServiceAudRen : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceAudRen() + { + m_Commands = new Dictionary() + { + { 0, OpenAudioRenderer }, + { 1, GetAudioRendererWorkBufferSize }, + }; + } + + public long OpenAudioRenderer(ServiceCtx Context) + { + MakeObject(Context, new IAudioRenderer()); + + return 0; + } + + public long GetAudioRendererWorkBufferSize(ServiceCtx Context) + { + int SampleRate = Context.RequestData.ReadInt32(); + int Unknown4 = Context.RequestData.ReadInt32(); + int Unknown8 = Context.RequestData.ReadInt32(); + int UnknownC = Context.RequestData.ReadInt32(); + int Unknown10 = Context.RequestData.ReadInt32(); + int Unknown14 = Context.RequestData.ReadInt32(); + int Unknown18 = Context.RequestData.ReadInt32(); + int Unknown1c = Context.RequestData.ReadInt32(); + int Unknown20 = Context.RequestData.ReadInt32(); + int Unknown24 = Context.RequestData.ReadInt32(); + int Unknown28 = Context.RequestData.ReadInt32(); + int Unknown2c = Context.RequestData.ReadInt32(); + int Rev1Magic = Context.RequestData.ReadInt32(); + + Context.ResponseData.Write(0x400L); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/ErrorCode.cs b/Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs similarity index 81% rename from Ryujinx.Core/OsHle/Objects/ErrorCode.cs rename to Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs index 659ed8b94..a4e197b22 100644 --- a/Ryujinx.Core/OsHle/Objects/ErrorCode.cs +++ b/Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Core.OsHle.Objects +namespace Ryujinx.Core.OsHle.IpcServices { static class ErrorCode { diff --git a/Ryujinx.Core/OsHle/Objects/ErrorModule.cs b/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs similarity index 55% rename from Ryujinx.Core/OsHle/Objects/ErrorModule.cs rename to Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs index 0221031b4..0d15db60a 100644 --- a/Ryujinx.Core/OsHle/Objects/ErrorModule.cs +++ b/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Core.OsHle.Objects +namespace Ryujinx.Core.OsHle.IpcServices { enum ErrorModule { diff --git a/Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs b/Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs similarity index 82% rename from Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs rename to Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs index e98e27cad..e3e03da85 100644 --- a/Ryujinx.Core/OsHle/Objects/Friend/IFriendService.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Friend +namespace Ryujinx.Core.OsHle.IpcServices.Friend { - class IFriendService : IIpcInterface + class IFriendService : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs b/Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs new file mode 100644 index 000000000..674877f67 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Friend +{ + class ServiceFriend : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceFriend() + { + m_Commands = new Dictionary() + { + { 0, CreateFriendService } + }; + } + + public static long CreateFriendService(ServiceCtx Context) + { + MakeObject(Context, new IFriendService()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs similarity index 79% rename from Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs rename to Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs index d9aa60ae7..656d529f2 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/FsErr.cs +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Core.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { static class FsErr { diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs similarity index 97% rename from Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs rename to Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs index 785b1ba38..54dbec746 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IDirectory.cs +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using System.IO; using System.Text; -namespace Ryujinx.Core.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { - class IDirectory : IIpcInterface, IDisposable + class IDirectory : IIpcService, IDisposable { private const int DirectoryEntrySize = 0x310; diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs similarity index 96% rename from Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs rename to Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs index 82706f609..ac2100f29 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFile.cs +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using System.IO; -namespace Ryujinx.Core.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { - class IFile : IIpcInterface, IDisposable + class IFile : IIpcService, IDisposable { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs similarity index 98% rename from Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs rename to Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs index 6b86a4739..ee9de8bc8 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs @@ -4,12 +4,12 @@ using System; using System.Collections.Generic; using System.IO; -using static Ryujinx.Core.OsHle.Objects.ErrorCode; -using static Ryujinx.Core.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.IpcServices.ErrorCode; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; -namespace Ryujinx.Core.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { - class IFileSystem : IIpcInterface + class IFileSystem : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs similarity index 94% rename from Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs rename to Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs index 4eca37e8e..297461a04 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IStorage.cs +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs @@ -3,9 +3,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; using System.IO; -namespace Ryujinx.Core.OsHle.Objects.FspSrv +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { - class IStorage : IIpcInterface + class IStorage : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs new file mode 100644 index 000000000..991f40272 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs @@ -0,0 +1,67 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.FspSrv +{ + class ServiceFspSrv : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceFspSrv() + { + m_Commands = new Dictionary() + { + { 1, Initialize }, + { 18, MountSdCard }, + { 51, MountSaveData }, + { 200, OpenDataStorageByCurrentProcess }, + { 203, OpenRomStorage }, + { 1005, GetGlobalAccessLogMode } + }; + } + + public long Initialize(ServiceCtx Context) + { + return 0; + } + + public long MountSdCard(ServiceCtx Context) + { + MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetSdCardPath())); + + return 0; + } + + public long MountSaveData(ServiceCtx Context) + { + MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetGameSavesPath())); + + return 0; + } + + public long OpenDataStorageByCurrentProcess(ServiceCtx Context) + { + MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs)); + + return 0; + } + + public long OpenRomStorage(ServiceCtx Context) + { + MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs)); + + return 0; + } + + public long GetGlobalAccessLogMode(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs b/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs similarity index 79% rename from Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs rename to Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs index aae3c38d3..020e8e7e6 100644 --- a/Ryujinx.Core/OsHle/Objects/Hid/IActiveVibrationDeviceList.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Hid +namespace Ryujinx.Core.OsHle.IpcServices.Hid { - class IActiveApplicationDeviceList : IIpcInterface + class IActiveApplicationDeviceList : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs similarity index 89% rename from Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs rename to Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs index 7d56d04ba..d22e0ff23 100644 --- a/Ryujinx.Core/OsHle/Objects/Hid/IAppletResource.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs @@ -2,9 +2,9 @@ using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Hid +namespace Ryujinx.Core.OsHle.IpcServices.Hid { - class IAppletResource : IIpcInterface + class IAppletResource : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs new file mode 100644 index 000000000..5cca9319e --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs @@ -0,0 +1,98 @@ +using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Hid +{ + class ServiceHid : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceHid() + { + m_Commands = new Dictionary() + { + { 0, CreateAppletResource }, + { 11, ActivateTouchScreen }, + { 100, SetSupportedNpadStyleSet }, + { 101, GetSupportedNpadStyleSet }, + { 102, SetSupportedNpadIdType }, + { 103, ActivateNpad }, + { 120, SetNpadJoyHoldType }, + { 121, GetNpadJoyHoldType }, + { 203, CreateActiveVibrationDeviceList }, + }; + } + + public long CreateAppletResource(ServiceCtx Context) + { + HSharedMem HidHndData = Context.Ns.Os.Handles.GetData(Context.Ns.Os.HidHandle); + + MakeObject(Context, new IAppletResource(HidHndData)); + + return 0; + } + + public long ActivateTouchScreen(ServiceCtx Context) + { + long Unknown = Context.RequestData.ReadInt64(); + + return 0; + } + + public long GetSupportedNpadStyleSet(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + return 0; + } + + public long SetSupportedNpadStyleSet(ServiceCtx Context) + { + long Unknown0 = Context.RequestData.ReadInt64(); + long Unknown8 = Context.RequestData.ReadInt64(); + + return 0; + } + + public long SetSupportedNpadIdType(ServiceCtx Context) + { + long Unknown = Context.RequestData.ReadInt64(); + + return 0; + } + + public long ActivateNpad(ServiceCtx Context) + { + long Unknown = Context.RequestData.ReadInt64(); + + return 0; + } + + public long SetNpadJoyHoldType(ServiceCtx Context) + { + long Unknown0 = Context.RequestData.ReadInt64(); + long Unknown8 = Context.RequestData.ReadInt64(); + + return 0; + } + + public long GetNpadJoyHoldType(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + + return 0; + } + + public long CreateActiveVibrationDeviceList(ServiceCtx Context) + { + MakeObject(Context, new IActiveApplicationDeviceList()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/IIpcInterface.cs b/Ryujinx.Core/OsHle/IpcServices/IIpcService.cs similarity index 69% rename from Ryujinx.Core/OsHle/Objects/IIpcInterface.cs rename to Ryujinx.Core/OsHle/IpcServices/IIpcService.cs index c57a09748..eebcdfbe5 100644 --- a/Ryujinx.Core/OsHle/Objects/IIpcInterface.cs +++ b/Ryujinx.Core/OsHle/IpcServices/IIpcService.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects +namespace Ryujinx.Core.OsHle.IpcServices { - interface IIpcInterface + interface IIpcService { IReadOnlyDictionary Commands { get; } } diff --git a/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs b/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs new file mode 100644 index 000000000..e665253c1 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs @@ -0,0 +1,27 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Lm +{ + class ServiceLm : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceLm() + { + m_Commands = new Dictionary() + { + { 0, Initialize } + }; + } + + public long Initialize(ServiceCtx Context) + { + Context.Session.Initialize(); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs similarity index 94% rename from Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs rename to Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs index 6c5fdaedd..1de0ab706 100644 --- a/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs @@ -6,14 +6,14 @@ using Ryujinx.Graphics.Gpu; using System; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Services +namespace Ryujinx.Core.OsHle.IpcServices.NvServices { - static partial class Service + class ServiceNvDrv : IIpcService { - private delegate long ServiceProcessRequest(ServiceCtx Context); + private delegate long ServiceProcessIoctl(ServiceCtx Context); - private static Dictionary<(string, int), ServiceProcessRequest> IoctlCmds = - new Dictionary<(string, int), ServiceProcessRequest>() + private static Dictionary<(string, int), ServiceProcessIoctl> IoctlCmds = + new Dictionary<(string, int), ServiceProcessIoctl>() { { ("/dev/nvhost-as-gpu", 0x4101), NvGpuAsIoctlBindChannel }, { ("/dev/nvhost-as-gpu", 0x4102), NvGpuAsIoctlAllocSpace }, @@ -42,7 +42,24 @@ namespace Ryujinx.Core.OsHle.Services { ("/dev/nvmap", 0x010e), NvMapIocGetId }, }; - public static long NvDrvOpen(ServiceCtx Context) + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceNvDrv() + { + m_Commands = new Dictionary() + { + { 0, Open }, + { 1, Ioctl }, + { 2, Close }, + { 3, Initialize }, + { 4, QueryEvent }, + { 8, SetClientPid }, + }; + } + + public static long Open(ServiceCtx Context) { long NamePtr = Context.Request.SendBuff[0].Position; @@ -56,7 +73,7 @@ namespace Ryujinx.Core.OsHle.Services return 0; } - public static long NvDrvIoctl(ServiceCtx Context) + public static long Ioctl(ServiceCtx Context) { int Fd = Context.RequestData.ReadInt32(); int Cmd = Context.RequestData.ReadInt32() & 0xffff; @@ -67,7 +84,7 @@ namespace Ryujinx.Core.OsHle.Services Context.ResponseData.Write(0); - if (IoctlCmds.TryGetValue((FdData.Name, Cmd), out ServiceProcessRequest ProcReq)) + if (IoctlCmds.TryGetValue((FdData.Name, Cmd), out ServiceProcessIoctl ProcReq)) { return ProcReq(Context); } @@ -77,7 +94,7 @@ namespace Ryujinx.Core.OsHle.Services } } - public static long NvDrvClose(ServiceCtx Context) + public static long Close(ServiceCtx Context) { int Fd = Context.RequestData.ReadInt32(); @@ -88,7 +105,7 @@ namespace Ryujinx.Core.OsHle.Services return 0; } - public static long NvDrvInitialize(ServiceCtx Context) + public static long Initialize(ServiceCtx Context) { long TransferMemSize = Context.RequestData.ReadInt64(); int TransferMemHandle = Context.Request.HandleDesc.ToCopy[0]; @@ -98,7 +115,7 @@ namespace Ryujinx.Core.OsHle.Services return 0; } - public static long NvDrvQueryEvent(ServiceCtx Context) + public static long QueryEvent(ServiceCtx Context) { int Fd = Context.RequestData.ReadInt32(); int EventId = Context.RequestData.ReadInt32(); @@ -110,7 +127,7 @@ namespace Ryujinx.Core.OsHle.Services return 0; } - public static long NvDrvSetClientPid(ServiceCtx Context) + public static long SetClientPid(ServiceCtx Context) { long Pid = Context.RequestData.ReadInt64(); diff --git a/Ryujinx.Core/OsHle/Objects/ObjHelper.cs b/Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs similarity index 93% rename from Ryujinx.Core/OsHle/Objects/ObjHelper.cs rename to Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs index a151a2879..ff71838a6 100644 --- a/Ryujinx.Core/OsHle/Objects/ObjHelper.cs +++ b/Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs @@ -1,7 +1,7 @@ using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; -namespace Ryujinx.Core.OsHle.Objects +namespace Ryujinx.Core.OsHle.IpcServices { static class ObjHelper { diff --git a/Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs b/Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs similarity index 81% rename from Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs rename to Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs index 1feacfa64..4eb92d31d 100644 --- a/Ryujinx.Core/OsHle/Objects/Am/IParentalControlService.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Am +namespace Ryujinx.Core.OsHle.IpcServices.Pctl { - class IParentalControlService : IIpcInterface + class IParentalControlService : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs b/Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs new file mode 100644 index 000000000..2d5e22a46 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Pctl +{ + class ServicePctl : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServicePctl() + { + m_Commands = new Dictionary() + { + { 0, CreateService } + }; + } + + public static long CreateService(ServiceCtx Context) + { + MakeObject(Context, new IParentalControlService()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs b/Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs new file mode 100644 index 000000000..abc34ed21 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs @@ -0,0 +1,51 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Pl +{ + class ServicePl : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServicePl() + { + m_Commands = new Dictionary() + { + { 1, GetLoadState }, + { 2, GetFontSize }, + { 3, GetSharedMemoryAddressOffset }, + { 4, GetSharedMemoryNativeHandle } + }; + } + + public static long GetLoadState(ServiceCtx Context) + { + Context.ResponseData.Write(1); //Loaded + + return 0; + } + + public static long GetFontSize(ServiceCtx Context) + { + Context.ResponseData.Write(Horizon.FontSize); + + return 0; + } + + public static long GetSharedMemoryAddressOffset(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + return 0; + } + + public static long GetSharedMemoryNativeHandle(ServiceCtx Context) + { + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.FontHandle); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs b/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs new file mode 100644 index 000000000..e9613050f --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs @@ -0,0 +1,50 @@ +using Ryujinx.Core.OsHle.IpcServices.Acc; +using Ryujinx.Core.OsHle.IpcServices.Am; +using Ryujinx.Core.OsHle.IpcServices.Apm; +using Ryujinx.Core.OsHle.IpcServices.Aud; +using Ryujinx.Core.OsHle.IpcServices.Friend; +using Ryujinx.Core.OsHle.IpcServices.FspSrv; +using Ryujinx.Core.OsHle.IpcServices.Hid; +using Ryujinx.Core.OsHle.IpcServices.Lm; +using Ryujinx.Core.OsHle.IpcServices.NvServices; +using Ryujinx.Core.OsHle.IpcServices.Pctl; +using Ryujinx.Core.OsHle.IpcServices.Pl; +using Ryujinx.Core.OsHle.IpcServices.Set; +using Ryujinx.Core.OsHle.IpcServices.Sm; +using Ryujinx.Core.OsHle.IpcServices.Time; +using Ryujinx.Core.OsHle.IpcServices.Vi; +using System; + +namespace Ryujinx.Core.OsHle.IpcServices +{ + static class ServiceFactory + { + public static IIpcService MakeService(string Name) + { + switch (Name) + { + case "acc:u0": return new ServiceAcc(); + case "apm": return new ServiceApm(); + case "apm:p": return new ServiceApm(); + case "appletOE": return new ServiceAppletOE(); + case "audout:u": return new ServiceAudOut(); + case "audren:u": return new ServiceAudRen(); + case "friend:a": return new ServiceFriend(); + case "fsp-srv": return new ServiceFspSrv(); + case "hid": return new ServiceHid(); + case "lm": return new ServiceLm(); + case "nvdrv": return new ServiceNvDrv(); + case "nvdrv:a": return new ServiceNvDrv(); + case "pctl:a": return new ServicePctl(); + case "pl:u": return new ServicePl(); + case "set": return new ServiceSet(); + case "sm:": return new ServiceSm(); + case "time:s": return new ServiceTime(); + case "time:u": return new ServiceTime(); + case "vi:m": return new ServiceVi(); + } + + throw new NotImplementedException(Name); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceSet.cs b/Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs similarity index 57% rename from Ryujinx.Core/OsHle/Services/ServiceSet.cs rename to Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs index 83ea5b2ce..05e409b0d 100644 --- a/Ryujinx.Core/OsHle/Services/ServiceSet.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs @@ -1,12 +1,26 @@ using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Services +namespace Ryujinx.Core.OsHle.IpcServices.Set { - static partial class Service + class ServiceSet : IIpcService { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceSet() + { + m_Commands = new Dictionary() + { + { 1, GetAvailableLanguageCodes } + }; + } + private const int LangCodesCount = 13; - public static long SetGetAvailableLanguageCodes(ServiceCtx Context) + public static long GetAvailableLanguageCodes(ServiceCtx Context) { int PtrBuffSize = Context.RequestData.ReadInt32(); diff --git a/Ryujinx.Core/OsHle/Services/ServiceSm.cs b/Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs similarity index 56% rename from Ryujinx.Core/OsHle/Services/ServiceSm.cs rename to Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs index 58abed241..a5f1b329b 100644 --- a/Ryujinx.Core/OsHle/Services/ServiceSm.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs @@ -1,20 +1,34 @@ using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Services +namespace Ryujinx.Core.OsHle.IpcServices.Sm { - static partial class Service + class ServiceSm : IIpcService { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceSm() + { + m_Commands = new Dictionary() + { + { 0, Initialize }, + { 1, GetService } + }; + } + private const int SmNotInitialized = 0x415; - public static long SmInitialize(ServiceCtx Context) + public long Initialize(ServiceCtx Context) { Context.Session.Initialize(); return 0; } - public static long SmGetService(ServiceCtx Context) + public long GetService(ServiceCtx Context) { //Only for kernel version > 3.0.0. if (!Context.Session.IsInitialized) @@ -36,7 +50,12 @@ namespace Ryujinx.Core.OsHle.Services } } - HSession Session = new HSession(Name); + if (Name == string.Empty) + { + return 0; + } + + HSession Session = new HSession(ServiceFactory.MakeService(Name)); int Handle = Context.Ns.Os.Handles.GenerateId(Session); diff --git a/Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs b/Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs similarity index 83% rename from Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs rename to Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs index 1116b8492..d20e4378a 100644 --- a/Ryujinx.Core/OsHle/Objects/Time/ISteadyClock.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Time +namespace Ryujinx.Core.OsHle.IpcServices.Time { - class ISteadyClock : IIpcInterface + class ISteadyClock : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs b/Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs similarity index 92% rename from Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs rename to Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs index 3aa706915..4d4493dad 100644 --- a/Ryujinx.Core/OsHle/Objects/Time/ISystemClock.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs @@ -2,9 +2,9 @@ using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Time +namespace Ryujinx.Core.OsHle.IpcServices.Time { - class ISystemClock : IIpcInterface + class ISystemClock : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs similarity index 82% rename from Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs rename to Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs index c083628bb..9875fa2fc 100644 --- a/Ryujinx.Core/OsHle/Objects/Time/ITimeZoneService.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Time +namespace Ryujinx.Core.OsHle.IpcServices.Time { - class ITimeZoneService : IIpcInterface + class ITimeZoneService : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs b/Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs new file mode 100644 index 000000000..43f28bb80 --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs @@ -0,0 +1,62 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Time +{ + class ServiceTime : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceTime() + { + m_Commands = new Dictionary() + { + { 0, GetStandardUserSystemClock }, + { 1, GetStandardNetworkSystemClock }, + { 2, GetStandardSteadyClock }, + { 3, GetTimeZoneService }, + { 4, GetStandardLocalSystemClock } + }; + } + + public long GetStandardUserSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.User)); + + return 0; + } + + public long GetStandardNetworkSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.Network)); + + return 0; + } + + public long GetStandardSteadyClock(ServiceCtx Context) + { + MakeObject(Context, new ISteadyClock()); + + return 0; + } + + public long GetTimeZoneService(ServiceCtx Context) + { + MakeObject(Context, new ITimeZoneService()); + + return 0; + } + + public long GetStandardLocalSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.Local)); + + return 0; + } + + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs b/Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs similarity index 64% rename from Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs rename to Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs index f447ca1cf..2314942a3 100644 --- a/Ryujinx.Core/OsHle/Objects/Time/SystemClockType.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Core.OsHle.Objects.Time +namespace Ryujinx.Core.OsHle.IpcServices.Time { enum SystemClockType { diff --git a/Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs similarity index 96% rename from Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs rename to Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs index b3ec0e90c..a899cdd56 100644 --- a/Ryujinx.Core/OsHle/Objects/Vi/IApplicationDisplayService.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs @@ -4,12 +4,12 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; using System.IO; -using static Ryujinx.Core.OsHle.Objects.Android.Parcel; -using static Ryujinx.Core.OsHle.Objects.ObjHelper; +using static Ryujinx.Core.OsHle.IpcServices.Android.Parcel; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; -namespace Ryujinx.Core.OsHle.Objects.Vi +namespace Ryujinx.Core.OsHle.IpcServices.Vi { - class IApplicationDisplayService : IIpcInterface + class IApplicationDisplayService : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs similarity index 93% rename from Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs rename to Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs index bbea3368c..a89c1df82 100644 --- a/Ryujinx.Core/OsHle/Objects/Vi/IHOSBinderDriver.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs @@ -1,12 +1,12 @@ using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Ipc; -using Ryujinx.Core.OsHle.Objects.Android; +using Ryujinx.Core.OsHle.IpcServices.Android; using System; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Vi +namespace Ryujinx.Core.OsHle.IpcServices.Vi { - class IHOSBinderDriver : IIpcInterface, IDisposable + class IHOSBinderDriver : IIpcService, IDisposable { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs similarity index 89% rename from Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs rename to Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs index f1b3cdd0a..5adee78d1 100644 --- a/Ryujinx.Core/OsHle/Objects/Vi/IManagerDisplayService.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Vi +namespace Ryujinx.Core.OsHle.IpcServices.Vi { - class IManagerDisplayService : IIpcInterface + class IManagerDisplayService : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs similarity index 85% rename from Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs rename to Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs index 4c83c25f1..d87fcbf6e 100644 --- a/Ryujinx.Core/OsHle/Objects/Vi/ISystemDisplayService.cs +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs @@ -1,9 +1,9 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Objects.Vi +namespace Ryujinx.Core.OsHle.IpcServices.Vi { - class ISystemDisplayService : IIpcInterface + class ISystemDisplayService : IIpcService { private Dictionary m_Commands; diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs b/Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs new file mode 100644 index 000000000..2c3dd2a3c --- /dev/null +++ b/Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs @@ -0,0 +1,31 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Vi +{ + class ServiceVi : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceVi() + { + m_Commands = new Dictionary() + { + { 2, GetDisplayService } + }; + } + + public long GetDisplayService(ServiceCtx Context) + { + int Unknown = Context.RequestData.ReadInt32(); + + MakeObject(Context, new IApplicationDisplayService()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceAcc.cs b/Ryujinx.Core/OsHle/Services/ServiceAcc.cs deleted file mode 100644 index f25113e59..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceAcc.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Acc; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long AccU0ListOpenUsers(ServiceCtx Context) - { - return 0; - } - - public static long AccU0GetProfile(ServiceCtx Context) - { - MakeObject(Context, new IProfile()); - - return 0; - } - - public static long AccU0InitializeApplicationInfo(ServiceCtx Context) - { - return 0; - } - - public static long AccU0GetBaasAccountManagerForApplication(ServiceCtx Context) - { - MakeObject(Context, new IManagerForApplication()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceApm.cs b/Ryujinx.Core/OsHle/Services/ServiceApm.cs deleted file mode 100644 index e1bc0d348..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceApm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Apm; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long ApmOpenSession(ServiceCtx Context) - { - MakeObject(Context, new ISession()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs deleted file mode 100644 index bbb2484b4..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Am; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long AppletOpenApplicationProxy(ServiceCtx Context) - { - MakeObject(Context, new IApplicationProxy()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceAud.cs b/Ryujinx.Core/OsHle/Services/ServiceAud.cs deleted file mode 100644 index a8ba7dc01..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceAud.cs +++ /dev/null @@ -1,71 +0,0 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Objects.Aud; -using System.Text; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long AudOutListAudioOuts(ServiceCtx Context) - { - long Position = Context.Request.ReceiveBuff[0].Position; - - AMemoryHelper.WriteBytes(Context.Memory, Position, Encoding.ASCII.GetBytes("iface")); - - Context.ResponseData.Write(1); - - return 0; - } - - public static long AudOutOpenAudioOut(ServiceCtx Context) - { - MakeObject(Context, new IAudioOut()); - - Context.ResponseData.Write(48000); //Sample Rate - Context.ResponseData.Write(2); //Channel Count - Context.ResponseData.Write(2); //PCM Format - /* - 0 - Invalid - 1 - INT8 - 2 - INT16 - 3 - INT24 - 4 - INT32 - 5 - PCM Float - 6 - ADPCM - */ - Context.ResponseData.Write(0); //Unknown - - return 0; - } - - public static long AudRenOpenAudioRenderer(ServiceCtx Context) - { - MakeObject(Context, new IAudioRenderer()); - - return 0; - } - - public static long AudRenGetAudioRendererWorkBufferSize(ServiceCtx Context) - { - int SampleRate = Context.RequestData.ReadInt32(); - int Unknown4 = Context.RequestData.ReadInt32(); - int Unknown8 = Context.RequestData.ReadInt32(); - int UnknownC = Context.RequestData.ReadInt32(); - int Unknown10 = Context.RequestData.ReadInt32(); - int Unknown14 = Context.RequestData.ReadInt32(); - int Unknown18 = Context.RequestData.ReadInt32(); - int Unknown1c = Context.RequestData.ReadInt32(); - int Unknown20 = Context.RequestData.ReadInt32(); - int Unknown24 = Context.RequestData.ReadInt32(); - int Unknown28 = Context.RequestData.ReadInt32(); - int Unknown2c = Context.RequestData.ReadInt32(); - int Rev1Magic = Context.RequestData.ReadInt32(); - - Context.ResponseData.Write(0x400L); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceFriend.cs b/Ryujinx.Core/OsHle/Services/ServiceFriend.cs deleted file mode 100644 index d1229bd46..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceFriend.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Friend; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long FriendCreateFriendService(ServiceCtx Context) - { - MakeObject(Context, new IFriendService()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs deleted file mode 100644 index 3fe41cf06..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.FspSrv; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long FspSrvInitialize(ServiceCtx Context) - { - return 0; - } - - public static long FspSrvMountSdCard(ServiceCtx Context) - { - MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetSdCardPath())); - - return 0; - } - - public static long FspSrvMountSaveData(ServiceCtx Context) - { - MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetGameSavesPath())); - - return 0; - } - - public static long FspSrvOpenDataStorageByCurrentProcess(ServiceCtx Context) - { - MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs)); - - return 0; - } - - public static long FspSrvOpenRomStorage(ServiceCtx Context) - { - MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs)); - - return 0; - } - - public static long FspSrvGetGlobalAccessLogMode(ServiceCtx Context) - { - Context.ResponseData.Write(0); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/ServiceHid.cs deleted file mode 100644 index aed3e959c..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceHid.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Objects.Hid; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long HidCreateAppletResource(ServiceCtx Context) - { - HSharedMem HidHndData = Context.Ns.Os.Handles.GetData(Context.Ns.Os.HidHandle); - - MakeObject(Context, new IAppletResource(HidHndData)); - - return 0; - } - - public static long HidActivateTouchScreen(ServiceCtx Context) - { - long Unknown = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidGetSupportedNpadStyleSet(ServiceCtx Context) - { - Context.ResponseData.Write(0); - - return 0; - } - - public static long HidSetSupportedNpadStyleSet(ServiceCtx Context) - { - long Unknown0 = Context.RequestData.ReadInt64(); - long Unknown8 = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidSetSupportedNpadIdType(ServiceCtx Context) - { - long Unknown = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidActivateNpad(ServiceCtx Context) - { - long Unknown = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidSetNpadJoyHoldType(ServiceCtx Context) - { - long Unknown0 = Context.RequestData.ReadInt64(); - long Unknown8 = Context.RequestData.ReadInt64(); - - return 0; - } - - public static long HidGetNpadJoyHoldType(ServiceCtx Context) - { - Context.ResponseData.Write(0L); - - return 0; - } - - public static long HidCreateActiveVibrationDeviceList(ServiceCtx Context) - { - MakeObject(Context, new IActiveApplicationDeviceList()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceLm.cs b/Ryujinx.Core/OsHle/Services/ServiceLm.cs deleted file mode 100644 index 1fdde5521..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceLm.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long LmInitialize(ServiceCtx Context) - { - Context.Session.Initialize(); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServicePctl.cs b/Ryujinx.Core/OsHle/Services/ServicePctl.cs deleted file mode 100644 index 9c4406bb6..000000000 --- a/Ryujinx.Core/OsHle/Services/ServicePctl.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Am; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long PctlCreateService(ServiceCtx Context) - { - MakeObject(Context, new IParentalControlService()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServicePl.cs b/Ryujinx.Core/OsHle/Services/ServicePl.cs deleted file mode 100644 index 21e6741cd..000000000 --- a/Ryujinx.Core/OsHle/Services/ServicePl.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Ryujinx.Core.OsHle.Ipc; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long PlGetLoadState(ServiceCtx Context) - { - Context.ResponseData.Write(1); //Loaded - - return 0; - } - - public static long PlGetFontSize(ServiceCtx Context) - { - Context.ResponseData.Write(Horizon.FontSize); - - return 0; - } - - public static long PlGetSharedMemoryAddressOffset(ServiceCtx Context) - { - Context.ResponseData.Write(0); - - return 0; - } - - public static long PlGetSharedMemoryNativeHandle(ServiceCtx Context) - { - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.FontHandle); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceTime.cs b/Ryujinx.Core/OsHle/Services/ServiceTime.cs deleted file mode 100644 index a5fddcba6..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceTime.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Time; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long TimeGetStandardUserSystemClock(ServiceCtx Context) - { - MakeObject(Context, new ISystemClock(SystemClockType.User)); - - return 0; - } - - public static long TimeGetStandardNetworkSystemClock(ServiceCtx Context) - { - MakeObject(Context, new ISystemClock(SystemClockType.Network)); - - return 0; - } - - public static long TimeGetStandardSteadyClock(ServiceCtx Context) - { - MakeObject(Context, new ISteadyClock()); - - return 0; - } - - public static long TimeGetTimeZoneService(ServiceCtx Context) - { - MakeObject(Context, new ITimeZoneService()); - - return 0; - } - - public static long TimeGetStandardLocalSystemClock(ServiceCtx Context) - { - MakeObject(Context, new ISystemClock(SystemClockType.Local)); - - return 0; - } - - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceVi.cs b/Ryujinx.Core/OsHle/Services/ServiceVi.cs deleted file mode 100644 index 75cdc31b2..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceVi.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Ryujinx.Core.OsHle.Objects.Vi; - -using static Ryujinx.Core.OsHle.Objects.ObjHelper; - -namespace Ryujinx.Core.OsHle.Services -{ - static partial class Service - { - public static long ViGetDisplayService(ServiceCtx Context) - { - int Unknown = Context.RequestData.ReadInt32(); - - MakeObject(Context, new IApplicationDisplayService()); - - return 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index a69d3b409..3b9142c78 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -3,6 +3,7 @@ using ChocolArm64.State; using Ryujinx.Core.OsHle.Exceptions; using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; +using Ryujinx.Core.OsHle.IpcServices; using System; using System.Threading; @@ -61,7 +62,7 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Validate that app has perms to access the service, and that the service //actually exists, return error codes otherwise. - HSession Session = new HSession(Name); + HSession Session = new HSession(ServiceFactory.MakeService(Name)); ThreadState.X1 = (ulong)Ns.Os.Handles.GenerateId(Session); ThreadState.X0 = (int)SvcResult.Success; From e174100474fcfe484cc8e93c4db447886096615d Mon Sep 17 00:00:00 2001 From: Ac_K Date: Sun, 25 Feb 2018 19:58:16 +0100 Subject: [PATCH 26/67] Implement many objects, improve logging. (#42) * Implement many objects, improve logging. Change and rename folders of Services Add Logging of IpcMessage. Add "lm" Log Service. Parse Errors of SetTerminateResult Add Svc Calls. Add many object implementations. * Corrections Forgotten Debug Conf * Corrections 2 * Corrections 3 * Corrections 4 --- CONFIG.md | 4 + Ryujinx.Core/Config.cs | 14 +- Ryujinx.Core/Logging.cs | 93 ++++++++- Ryujinx.Core/OsHle/Handles/HThread.cs | 2 +- Ryujinx.Core/OsHle/Ipc/IpcLog.cs | 179 ++++++++++++++++++ Ryujinx.Core/OsHle/Ipc/IpcMessage.cs | 2 + Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs | 7 - .../Acc/IManagerForApplication.cs | 0 .../{IpcServices => Services}/Acc/IProfile.cs | 0 .../Acc/ServiceAcc.cs | 0 .../Am/IApplicationFunctions.cs | 14 ++ .../Am/IApplicationProxy.cs | 0 .../Am/IAudioController.cs | 0 .../Am/ICommonStateGetter.cs | 0 .../Am/IDebugFunctions.cs | 0 .../Am/IDisplayController.cs | 0 .../Am/ILibraryAppletCreator.cs | 0 .../Am/ISelfController.cs | 14 ++ .../{IpcServices => Services}/Am/IStorage.cs | 0 .../Am/IStorageAccessor.cs | 0 .../Am/IWindowController.cs | 0 .../Am/ServiceAppletOE.cs | 0 .../{IpcServices => Services}/Apm/ISession.cs | 0 .../Apm/ServiceApm.cs | 0 .../Aud/IAudioOut.cs | 0 .../Aud/IAudioRenderer.cs | 0 .../Aud/ServiceAudOut.cs | 0 .../Aud/ServiceAudRen.cs | 0 .../{IpcServices => Services}/ErrorCode.cs | 0 Ryujinx.Core/OsHle/Services/ErrorModule.cs | 63 ++++++ .../Friend/IFriendService.cs | 0 .../Friend/ServiceFriend.cs | 0 .../{IpcServices => Services}/FspSrv/FsErr.cs | 0 .../FspSrv/IDirectory.cs | 0 .../{IpcServices => Services}/FspSrv/IFile.cs | 0 .../FspSrv/IFileSystem.cs | 0 .../FspSrv/IStorage.cs | 0 .../FspSrv/ServiceFspSrv.cs | 0 .../Hid/IActiveVibrationDeviceList.cs | 12 +- .../Hid/IAppletResource.cs | 0 .../Hid/ServiceHid.cs | 10 + .../{IpcServices => Services}/IIpcService.cs | 0 Ryujinx.Core/OsHle/Services/Lm/ILogger.cs | 143 ++++++++++++++ .../{IpcServices => Services}/Lm/ServiceLm.cs | 4 + .../Ns/ServiceNs.cs} | 8 +- .../Nv}/ServiceNvDrv.cs | 0 .../{IpcServices => Services}/ObjHelper.cs | 0 .../Pctl/IParentalControlService.cs | 0 .../Pctl/ServicePctl.cs | 0 .../{IpcServices => Services}/Pl/ServicePl.cs | 0 .../ServiceFactory.cs | 4 + .../Set/ServiceSet.cs | 0 .../{IpcServices => Services}/Sm/ServiceSm.cs | 0 .../Time/ISteadyClock.cs | 0 .../Time/ISystemClock.cs | 0 .../OsHle/Services/Time/ITimeZoneService.cs | 69 +++++++ .../Time/ServiceTime.cs | 0 .../Time/SystemClockType.cs | 0 .../Android => Services/Vi}/GbpBuffer.cs | 0 .../Vi/IApplicationDisplayService.cs | 0 .../Vi/IHOSBinderDriver.cs | 0 .../Vi/IManagerDisplayService.cs | 0 .../Vi/ISystemDisplayService.cs | 0 .../Android => Services/Vi}/NvFlinger.cs | 0 .../Android => Services/Vi}/Parcel.cs | 0 .../{IpcServices => Services}/Vi/ServiceVi.cs | 0 Ryujinx.Core/OsHle/Svc/SvcHandler.cs | 3 + Ryujinx.Core/OsHle/Svc/SvcThread.cs | 39 ++++ Ryujinx/Ryujinx.conf | 3 + 69 files changed, 660 insertions(+), 27 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Ipc/IpcLog.cs delete mode 100644 Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs rename Ryujinx.Core/OsHle/{IpcServices => Services}/Acc/IManagerForApplication.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Acc/IProfile.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Acc/ServiceAcc.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/IApplicationFunctions.cs (85%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/IApplicationProxy.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/IAudioController.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/ICommonStateGetter.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/IDebugFunctions.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/IDisplayController.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/ILibraryAppletCreator.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/ISelfController.cs (82%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/IStorage.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/IStorageAccessor.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/IWindowController.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Am/ServiceAppletOE.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Apm/ISession.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Apm/ServiceApm.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Aud/IAudioOut.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Aud/IAudioRenderer.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Aud/ServiceAudOut.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Aud/ServiceAudRen.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/ErrorCode.cs (100%) create mode 100644 Ryujinx.Core/OsHle/Services/ErrorModule.cs rename Ryujinx.Core/OsHle/{IpcServices => Services}/Friend/IFriendService.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Friend/ServiceFriend.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/FspSrv/FsErr.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/FspSrv/IDirectory.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/FspSrv/IFile.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/FspSrv/IFileSystem.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/FspSrv/IStorage.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/FspSrv/ServiceFspSrv.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Hid/IActiveVibrationDeviceList.cs (63%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Hid/IAppletResource.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Hid/ServiceHid.cs (89%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/IIpcService.cs (100%) create mode 100644 Ryujinx.Core/OsHle/Services/Lm/ILogger.cs rename Ryujinx.Core/OsHle/{IpcServices => Services}/Lm/ServiceLm.cs (85%) rename Ryujinx.Core/OsHle/{IpcServices/Time/ITimeZoneService.cs => Services/Ns/ServiceNs.cs} (71%) rename Ryujinx.Core/OsHle/{IpcServices/NvServices => Services/Nv}/ServiceNvDrv.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/ObjHelper.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Pctl/IParentalControlService.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Pctl/ServicePctl.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Pl/ServicePl.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/ServiceFactory.cs (90%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Set/ServiceSet.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Sm/ServiceSm.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Time/ISteadyClock.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Time/ISystemClock.cs (100%) create mode 100644 Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs rename Ryujinx.Core/OsHle/{IpcServices => Services}/Time/ServiceTime.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Time/SystemClockType.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices/Android => Services/Vi}/GbpBuffer.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Vi/IApplicationDisplayService.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Vi/IHOSBinderDriver.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Vi/IManagerDisplayService.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Vi/ISystemDisplayService.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices/Android => Services/Vi}/NvFlinger.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices/Android => Services/Vi}/Parcel.cs (100%) rename Ryujinx.Core/OsHle/{IpcServices => Services}/Vi/ServiceVi.cs (100%) diff --git a/CONFIG.md b/CONFIG.md index 09fa13b7b..764eb528d 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -26,6 +26,10 @@ Enable the Fatal Logging (Enabled in Debug recommanded). +- `Logging_Enable_Ipc` *(bool)* + + Enable the Ipc Message Logging. + - `Logging_Enable_LogFile` *(bool)* Enable writing the logging inside a Ryujinx.log file. diff --git a/Ryujinx.Core/Config.cs b/Ryujinx.Core/Config.cs index b97e80b89..7db49319c 100644 --- a/Ryujinx.Core/Config.cs +++ b/Ryujinx.Core/Config.cs @@ -8,12 +8,13 @@ namespace Ryujinx.Core { public static class Config { - public static bool LoggingEnableInfo { get; private set; } - public static bool LoggingEnableTrace { get; private set; } - public static bool LoggingEnableDebug { get; private set; } - public static bool LoggingEnableWarn { get; private set; } - public static bool LoggingEnableError { get; private set; } - public static bool LoggingEnableFatal { get; private set; } + public static bool LoggingEnableInfo { get; private set; } + public static bool LoggingEnableTrace { get; private set; } + public static bool LoggingEnableDebug { get; private set; } + public static bool LoggingEnableWarn { get; private set; } + public static bool LoggingEnableError { get; private set; } + public static bool LoggingEnableFatal { get; private set; } + public static bool LoggingEnableIpc { get; private set; } public static bool LoggingEnableLogFile { get; private set; } public static JoyCon FakeJoyCon { get; private set; } @@ -30,6 +31,7 @@ namespace Ryujinx.Core LoggingEnableWarn = Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")); LoggingEnableError = Convert.ToBoolean(Parser.Value("Logging_Enable_Error")); LoggingEnableFatal = Convert.ToBoolean(Parser.Value("Logging_Enable_Fatal")); + LoggingEnableIpc = Convert.ToBoolean(Parser.Value("Logging_Enable_Ipc")); LoggingEnableLogFile = Convert.ToBoolean(Parser.Value("Logging_Enable_LogFile")); FakeJoyCon = new JoyCon diff --git a/Ryujinx.Core/Logging.cs b/Ryujinx.Core/Logging.cs index e14e5587a..b14f26653 100644 --- a/Ryujinx.Core/Logging.cs +++ b/Ryujinx.Core/Logging.cs @@ -1,6 +1,8 @@ -using System; +using Ryujinx.Core.OsHle.Ipc; +using System; using System.Diagnostics; using System.IO; +using System.Text; namespace Ryujinx.Core { @@ -9,13 +11,14 @@ namespace Ryujinx.Core private static Stopwatch ExecutionTime = new Stopwatch(); private const string LogFileName = "Ryujinx.log"; - public static bool EnableInfo = Config.LoggingEnableInfo; - public static bool EnableTrace = Config.LoggingEnableTrace; - public static bool EnableDebug = Config.LoggingEnableDebug; - public static bool EnableWarn = Config.LoggingEnableWarn; - public static bool EnableError = Config.LoggingEnableError; - public static bool EnableFatal = Config.LoggingEnableFatal; - public static bool EnableLogFile = Config.LoggingEnableLogFile; + private static bool EnableInfo = Config.LoggingEnableInfo; + private static bool EnableTrace = Config.LoggingEnableTrace; + private static bool EnableDebug = Config.LoggingEnableDebug; + private static bool EnableWarn = Config.LoggingEnableWarn; + private static bool EnableError = Config.LoggingEnableError; + private static bool EnableFatal = Config.LoggingEnableFatal; + private static bool EnableIpc = Config.LoggingEnableIpc; + private static bool EnableLogFile = Config.LoggingEnableLogFile; static Logging() { @@ -128,5 +131,79 @@ namespace Ryujinx.Core LogFile(Text); } } + + public static void Ipc(byte[] Data, long CmdPtr, bool Domain) + { + if (EnableIpc) + { + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine(IpcLog.Message(Data, CmdPtr, Domain)); + Console.ResetColor(); + } + } + + //https://www.codeproject.com/Articles/36747/Quick-and-Dirty-HexDump-of-a-Byte-Array + public static string HexDump(byte[] bytes, int bytesPerLine = 16) + { + if (bytes == null) return ""; + int bytesLength = bytes.Length; + + char[] HexChars = "0123456789ABCDEF".ToCharArray(); + + int firstHexColumn = + 8 // 8 characters for the address + + 3; // 3 spaces + + int firstCharColumn = firstHexColumn + + bytesPerLine * 3 // - 2 digit for the hexadecimal value and 1 space + + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th + + 2; // 2 spaces + + int lineLength = firstCharColumn + + bytesPerLine // - characters to show the ascii value + + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2) + + char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray(); + int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine; + StringBuilder result = new StringBuilder(expectedLines * lineLength); + + for (int i = 0; i < bytesLength; i += bytesPerLine) + { + line[0] = HexChars[(i >> 28) & 0xF]; + line[1] = HexChars[(i >> 24) & 0xF]; + line[2] = HexChars[(i >> 20) & 0xF]; + line[3] = HexChars[(i >> 16) & 0xF]; + line[4] = HexChars[(i >> 12) & 0xF]; + line[5] = HexChars[(i >> 8) & 0xF]; + line[6] = HexChars[(i >> 4) & 0xF]; + line[7] = HexChars[(i >> 0) & 0xF]; + + int hexColumn = firstHexColumn; + int charColumn = firstCharColumn; + + for (int j = 0; j < bytesPerLine; j++) + { + if (j > 0 && (j & 7) == 0) hexColumn++; + if (i + j >= bytesLength) + { + line[hexColumn] = ' '; + line[hexColumn + 1] = ' '; + line[charColumn] = ' '; + } + else + { + byte b = bytes[i + j]; + line[hexColumn] = HexChars[(b >> 4) & 0xF]; + line[hexColumn + 1] = HexChars[b & 0xF]; + line[charColumn] = (b < 32 ? '·' : (char)b); + } + hexColumn += 3; + charColumn++; + } + + result.Append(line); + } + return result.ToString(); + } } } diff --git a/Ryujinx.Core/OsHle/Handles/HThread.cs b/Ryujinx.Core/OsHle/Handles/HThread.cs index 8bb276fa8..c631cedc6 100644 --- a/Ryujinx.Core/OsHle/Handles/HThread.cs +++ b/Ryujinx.Core/OsHle/Handles/HThread.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle.Handles public AThread Thread { get; private set; } public int ProcessorId { get; private set; } - public int Priority { get; private set; } + public int Priority { get; set; } public int ThreadId => Thread.ThreadId; diff --git a/Ryujinx.Core/OsHle/Ipc/IpcLog.cs b/Ryujinx.Core/OsHle/Ipc/IpcLog.cs new file mode 100644 index 000000000..dfec7ccfd --- /dev/null +++ b/Ryujinx.Core/OsHle/Ipc/IpcLog.cs @@ -0,0 +1,179 @@ +using System; +using System.IO; + +namespace Ryujinx.Core.OsHle.Ipc +{ + public static class IpcLog + { + public static string Message(byte[] Data, long CmdPtr, bool Domain) + { + string IpcMessage = ""; + + using (MemoryStream MS = new MemoryStream(Data)) + { + BinaryReader Reader = new BinaryReader(MS); + + int Word0 = Reader.ReadInt32(); + int Word1 = Reader.ReadInt32(); + + int Type = (Word0 & 0xffff); + + int PtrBuffCount = (Word0 >> 16) & 0xf; + int SendBuffCount = (Word0 >> 20) & 0xf; + int RecvBuffCount = (Word0 >> 24) & 0xf; + int XchgBuffCount = (Word0 >> 28) & 0xf; + + int RawDataSize = (Word1 >> 0) & 0x3ff; + int RecvListFlags = (Word1 >> 10) & 0xf; + bool HndDescEnable = ((Word1 >> 31) & 0x1) != 0; + + IpcMessage += Environment.NewLine + $" {Logging.GetExecutionTime()} | IpcMessage >" + Environment.NewLine + + $" Type: {Enum.GetName(typeof(IpcMessageType), Type)}" + Environment.NewLine + + + $" PtrBuffCount: {PtrBuffCount.ToString()}" + Environment.NewLine + + $" SendBuffCount: {SendBuffCount.ToString()}" + Environment.NewLine + + $" RecvBuffCount: {RecvBuffCount.ToString()}" + Environment.NewLine + + $" XchgBuffCount: {XchgBuffCount.ToString()}" + Environment.NewLine + + + $" RawDataSize: {RawDataSize.ToString()}" + Environment.NewLine + + $" RecvListFlags: {RecvListFlags.ToString()}" + Environment.NewLine + + $" HndDescEnable: {HndDescEnable.ToString()}" + Environment.NewLine; + + if (HndDescEnable) + { + int Word = Reader.ReadInt32(); + + bool HasPId = (Word & 1) != 0; + + int[] ToCopy = new int[(Word >> 1) & 0xf]; + int[] ToMove = new int[(Word >> 5) & 0xf]; + + long PId = HasPId ? Reader.ReadInt64() : 0; + + for (int Index = 0; Index < ToCopy.Length; Index++) + { + ToCopy[Index] = Reader.ReadInt32(); + } + + for (int Index = 0; Index < ToMove.Length; Index++) + { + ToMove[Index] = Reader.ReadInt32(); + } + + IpcMessage += Environment.NewLine + " HndDesc:" + Environment.NewLine + + $" PId: {PId.ToString()}" + Environment.NewLine + + $" ToCopy.Length: {ToCopy.Length.ToString()}" + Environment.NewLine + + $" ToMove.Length: {ToMove.Length.ToString()}" + Environment.NewLine; + } + + for (int Index = 0; Index < PtrBuffCount; Index++) + { + long IpcPtrBuffDescWord0 = Reader.ReadUInt32(); + long IpcPtrBuffDescWord1 = Reader.ReadUInt32(); + + long Position = IpcPtrBuffDescWord1; + Position |= (IpcPtrBuffDescWord0 << 20) & 0x0f00000000; + Position |= (IpcPtrBuffDescWord0 << 30) & 0x7000000000; + + int IpcPtrBuffDescIndex = ((int)IpcPtrBuffDescWord0 >> 0) & 0x03f; + IpcPtrBuffDescIndex |= ((int)IpcPtrBuffDescWord0 >> 3) & 0x1c0; + + short Size = (short)(IpcPtrBuffDescWord0 >> 16); + + IpcMessage += Environment.NewLine + $" PtrBuff[{Index}]:" + Environment.NewLine + + $" Position: {Position.ToString()}" + Environment.NewLine + + $" IpcPtrBuffDescIndex: {IpcPtrBuffDescIndex.ToString()}" + Environment.NewLine + + $" Size: {Size.ToString()}" + Environment.NewLine; + } + + ReadIpcBuffValues(Reader, SendBuffCount, IpcMessage, "SendBuff"); + ReadIpcBuffValues(Reader, RecvBuffCount, IpcMessage, "RecvBuff"); + ReadIpcBuffValues(Reader, XchgBuffCount, IpcMessage, "XchgBuff"); + + RawDataSize *= 4; + + long RecvListPos = Reader.BaseStream.Position + RawDataSize; + long Pad0 = 0; + + if ((Reader.BaseStream.Position + CmdPtr & 0xf) != 0) + { + Pad0 = 0x10 - (Reader.BaseStream.Position + CmdPtr & 0xf); + } + + Reader.BaseStream.Seek(Pad0, SeekOrigin.Current); + + int RecvListCount = RecvListFlags - 2; + + if (RecvListCount == 0) + { + RecvListCount = 1; + } + else if (RecvListCount < 0) + { + RecvListCount = 0; + } + + if (Domain && (IpcMessageType)Type == IpcMessageType.Request) + { + int DomWord0 = Reader.ReadInt32(); + + int DomCmd = (DomWord0 & 0xff); + + RawDataSize = (DomWord0 >> 16) & 0xffff; + + int DomObjId = Reader.ReadInt32(); + + Reader.ReadInt64(); //Padding + + IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine + + $" DomCmd: {Enum.GetName(typeof(IpcDomCmd), DomCmd)}" + Environment.NewLine + + $" DomObjId: {DomObjId.ToString()}" + Environment.NewLine; + } + + byte[] RawData = Reader.ReadBytes(RawDataSize); + + IpcMessage += Environment.NewLine + $" RawData:" + Environment.NewLine + Logging.HexDump(RawData); + + Reader.BaseStream.Seek(RecvListPos, SeekOrigin.Begin); + + for (int Index = 0; Index < RecvListCount; Index++) + { + long RecvListBuffValue = Reader.ReadInt64(); + long RecvListBuffPosition = RecvListBuffValue & 0xffffffffffff; + long RecvListBuffSize = (short)(RecvListBuffValue >> 48); + + IpcMessage += Environment.NewLine + $" RecvList[{Index}]:" + Environment.NewLine + + $" Value: {RecvListBuffValue.ToString()}" + Environment.NewLine + + $" Position: {RecvListBuffPosition.ToString()}" + Environment.NewLine + + $" Size: {RecvListBuffSize.ToString()}" + Environment.NewLine; + } + } + + return IpcMessage; + } + + private static void ReadIpcBuffValues(BinaryReader Reader, int Count, string IpcMessage, string BufferName) + { + for (int Index = 0; Index < Count; Index++) + { + long Word0 = Reader.ReadUInt32(); + long Word1 = Reader.ReadUInt32(); + long Word2 = Reader.ReadUInt32(); + + long Position = Word1; + Position |= (Word2 << 4) & 0x0f00000000; + Position |= (Word2 << 34) & 0x7000000000; + + long Size = Word0; + Size |= (Word2 << 8) & 0xf00000000; + + int Flags = (int)Word2 & 3; + + IpcMessage += Environment.NewLine + $" {BufferName}[{Index}]:" + Environment.NewLine + + $" Position: {Position.ToString()}" + Environment.NewLine + + $" Flags: {Flags.ToString()}" + Environment.NewLine + + $" Size: {Size.ToString()}" + Environment.NewLine; + } + } + } +} diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs index 447f3f9a6..cc26df108 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs @@ -41,6 +41,8 @@ namespace Ryujinx.Core.OsHle.Ipc public IpcMessage(byte[] Data, long CmdPtr, bool Domain) : this() { + Logging.Ipc(Data, CmdPtr, Domain); + using (MemoryStream MS = new MemoryStream(Data)) { BinaryReader Reader = new BinaryReader(MS); diff --git a/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs b/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs deleted file mode 100644 index 0d15db60a..000000000 --- a/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Core.OsHle.IpcServices -{ - enum ErrorModule - { - Fs = 2, - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs b/Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs rename to Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs b/Ryujinx.Core/OsHle/Services/Acc/IProfile.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs rename to Ryujinx.Core/OsHle/Services/Acc/IProfile.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs b/Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs rename to Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs b/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs similarity index 85% rename from Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs rename to Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs index 30020c1d8..6c5beeb3e 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs +++ b/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs @@ -1,4 +1,5 @@ using Ryujinx.Core.OsHle.Ipc; +using System; using System.Collections.Generic; using System.IO; @@ -19,6 +20,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am { 1, PopLaunchParameter }, { 20, EnsureSaveData }, { 21, GetDesiredLanguage }, + { 22, SetTerminateResult }, { 40, NotifyRunning } }; } @@ -52,6 +54,18 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am return 0; } + public long SetTerminateResult(ServiceCtx Context) + { + int ErrorCode = Context.RequestData.ReadInt32(); + + int Module = ErrorCode & 0xFF; + int Description = (ErrorCode >> 9) & 0xFFF; + + Logging.Info($"({(ErrorModule)Module}){2000 + Module}-{Description}"); + + return 0; + } + public long NotifyRunning(ServiceCtx Context) { Context.ResponseData.Write(1); diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs b/Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs rename to Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs b/Ryujinx.Core/OsHle/Services/Am/IAudioController.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs rename to Ryujinx.Core/OsHle/Services/Am/IAudioController.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs b/Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs rename to Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs b/Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs rename to Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs b/Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs rename to Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs b/Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs rename to Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs b/Ryujinx.Core/OsHle/Services/Am/ISelfController.cs similarity index 82% rename from Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs rename to Ryujinx.Core/OsHle/Services/Am/ISelfController.cs index 90ddd54b8..403e4072d 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs +++ b/Ryujinx.Core/OsHle/Services/Am/ISelfController.cs @@ -13,14 +13,21 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am { m_Commands = new Dictionary() { + { 1, Exit }, { 10, SetScreenShotPermission }, { 11, SetOperationModeChangedNotification }, { 12, SetPerformanceModeChangedNotification }, { 13, SetFocusHandlingMode }, + { 14, SetRestartMessageEnabled }, { 16, SetOutOfFocusSuspendingEnabled } }; } + public long Exit(ServiceCtx Context) + { + return 0; + } + public long SetScreenShotPermission(ServiceCtx Context) { bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; @@ -51,6 +58,13 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am return 0; } + public long SetRestartMessageEnabled(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + public long SetOutOfFocusSuspendingEnabled(ServiceCtx Context) { bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs b/Ryujinx.Core/OsHle/Services/Am/IStorage.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs rename to Ryujinx.Core/OsHle/Services/Am/IStorage.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs b/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs rename to Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs b/Ryujinx.Core/OsHle/Services/Am/IWindowController.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs rename to Ryujinx.Core/OsHle/Services/Am/IWindowController.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs rename to Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs b/Ryujinx.Core/OsHle/Services/Apm/ISession.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs rename to Ryujinx.Core/OsHle/Services/Apm/ISession.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs b/Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs rename to Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs rename to Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs rename to Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs rename to Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs rename to Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs b/Ryujinx.Core/OsHle/Services/ErrorCode.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs rename to Ryujinx.Core/OsHle/Services/ErrorCode.cs diff --git a/Ryujinx.Core/OsHle/Services/ErrorModule.cs b/Ryujinx.Core/OsHle/Services/ErrorModule.cs new file mode 100644 index 000000000..78af6195d --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/ErrorModule.cs @@ -0,0 +1,63 @@ +namespace Ryujinx.Core.OsHle.IpcServices +{ + enum ErrorModule + { + Kernel = 1, + Fs = 2, + Nvidia_TransferMemory = 3, + Ncm = 5, + Dd = 6, + Lr = 8, + Loader = 9, + IPC_Command_Interface = 10, + IPC = 11, + Pm = 15, + Ns = 16, + Htc = 18, + Sm = 21, + RO_Userland = 22, + SdMmc = 24, + Spl = 26, + Ethc = 100, + I2C = 101, + Settings = 105, + Nifm = 110, + Display = 114, + Ntc = 116, + Fdm = 117, + Pcie = 120, + Friends = 121, + SSL = 123, + Account = 124, + Mii = 126, + Am = 128, + Play_Report = 129, + Pcv = 133, + Omm = 134, + Nim = 137, + Psc = 138, + Usb = 140, + Nsd = 141, + Btm = 143, + Erpt = 147, + Apm = 148, + Audio = 153, + Npns = 154, + Arp = 157, + Boot = 158, + Nfc = 161, + Userland_Assert = 162, + Userland_Crash = 168, + Hid = 203, + Capture = 206, + Libnx = 345, + Homebrew_ABI = 346, + Homebrew_Loader = 347, + libnx_Nvidia_Errors = 348, + Tc = 651, + General_Web_Applet = 800, + Wifi_Web_Auth_Applet = 809, + Whitelisted_Applet = 810, + ShopN = 811 + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs b/Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs rename to Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs b/Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs rename to Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs b/Ryujinx.Core/OsHle/Services/FspSrv/FsErr.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/FsErr.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs b/Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs similarity index 63% rename from Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs rename to Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs index 020e8e7e6..f6596f429 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs @@ -11,7 +11,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid public IActiveApplicationDeviceList() { - m_Commands = new Dictionary() { }; + m_Commands = new Dictionary() + { + { 0, ActivateVibrationDevice } + }; + } + + public long ActivateVibrationDevice(ServiceCtx Context) + { + int VibrationDeviceHandle = Context.RequestData.ReadInt32(); + + return 0; } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs rename to Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs similarity index 89% rename from Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs rename to Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs index 5cca9319e..b0e5f44e2 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid { 103, ActivateNpad }, { 120, SetNpadJoyHoldType }, { 121, GetNpadJoyHoldType }, + { 200, GetVibrationDeviceInfo }, { 203, CreateActiveVibrationDeviceList }, }; } @@ -88,6 +89,15 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid return 0; } + public long GetVibrationDeviceInfo(ServiceCtx Context) + { + int VibrationDeviceHandle = Context.RequestData.ReadInt32(); + + Context.ResponseData.Write(0L); //VibrationDeviceInfoForIpc + + return 0; + } + public long CreateActiveVibrationDeviceList(ServiceCtx Context) { MakeObject(Context, new IActiveApplicationDeviceList()); diff --git a/Ryujinx.Core/OsHle/IpcServices/IIpcService.cs b/Ryujinx.Core/OsHle/Services/IIpcService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/IIpcService.cs rename to Ryujinx.Core/OsHle/Services/IIpcService.cs diff --git a/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs new file mode 100644 index 000000000..5ee097b6f --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs @@ -0,0 +1,143 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Ryujinx.Core.OsHle.IpcServices.Lm +{ + class ILogger : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ILogger() + { + m_Commands = new Dictionary() + { + { 0, Log } + }; + } + + enum Flags + { + Padding, + IsHead, + IsTail + } + + enum Severity + { + Trace, + Info, + Warning, + Error, + Critical + } + + enum Field + { + Padding, + Skip, + Message, + Line, + Filename, + Function, + Module, + Thread + } + + public long Log(ServiceCtx Context) + { + long BufferPosition = Context.Request.PtrBuff[0].Position; + long BufferLen = Context.Request.PtrBuff[0].Size; + + byte[] LogBuffer = AMemoryHelper.ReadBytes(Context.Memory, BufferPosition, (int)BufferLen); + + MemoryStream LogMessage = new MemoryStream(LogBuffer); + BinaryReader bReader = new BinaryReader(LogMessage); + + //Header reading. + long Pid = bReader.ReadInt64(); + long ThreadCxt = bReader.ReadInt64(); + int Infos = bReader.ReadInt32(); + int PayloadLen = bReader.ReadInt32(); + + int iFlags = Infos & 0xFFFF; + int iSeverity = (Infos >> 17) & 0x7F; + int iVerbosity = (Infos >> 25) & 0x7F; + + //ToDo: For now we don't care about Head or Tail Log. + bool IsHeadLog = Convert.ToBoolean(iFlags & (int)Flags.IsHead); + bool IsTailLog = Convert.ToBoolean(iFlags & (int)Flags.IsTail); + + string LogString = "nn::diag::detail::LogImpl()" + Environment.NewLine + Environment.NewLine + + "Header:" + Environment.NewLine + + $" Pid: {Pid}" + Environment.NewLine + + $" ThreadContext: {ThreadCxt}" + Environment.NewLine + + $" Flags: {IsHeadLog}/{IsTailLog}" + Environment.NewLine + + $" Severity: {Enum.GetName(typeof(Severity), iSeverity)}" + Environment.NewLine + + $" Verbosity: {iVerbosity}"; + + LogString += Environment.NewLine + Environment.NewLine + "Message:" + Environment.NewLine; + + string StrMessage = "", StrLine = "", StrFilename = "", StrFunction = "", + StrModule = "", StrThread = ""; + + do + { + byte FieldType = bReader.ReadByte(); + byte FieldSize = bReader.ReadByte(); + + if ((Field)FieldType != Field.Skip || FieldSize != 0) + { + byte[] Message = bReader.ReadBytes(FieldSize); + switch ((Field)FieldType) + { + case Field.Message: + StrMessage = Encoding.UTF8.GetString(Message); + break; + + case Field.Line: + StrLine = BitConverter.ToInt32(Message, 0).ToString(); + break; + + case Field.Filename: + StrFilename = Encoding.UTF8.GetString(Message); + break; + + case Field.Function: + StrFunction = Encoding.UTF8.GetString(Message); + break; + + case Field.Module: + StrModule = Encoding.UTF8.GetString(Message); + break; + + case Field.Thread: + StrThread = Encoding.UTF8.GetString(Message); + break; + } + } + + } + while (LogMessage.Position != PayloadLen + 0x18); // 0x18 - Size of Header LogMessage. + + LogString += StrModule + " > " + StrThread + ": " + StrFilename + "@" + StrFunction + "(" + StrLine + ") '" + StrMessage + "'" + Environment.NewLine; + + switch((Severity)iSeverity) + { + case Severity.Trace: Logging.Trace(LogString); break; + case Severity.Info: Logging.Info(LogString); break; + case Severity.Warning: Logging.Warn(LogString); break; + case Severity.Error: Logging.Error(LogString); break; + case Severity.Critical: Logging.Fatal(LogString); break; + } + + return 0; + } + } +} + \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs b/Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs similarity index 85% rename from Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs rename to Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs index e665253c1..ca3fe35e8 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs +++ b/Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs @@ -1,6 +1,8 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + namespace Ryujinx.Core.OsHle.IpcServices.Lm { class ServiceLm : IIpcService @@ -21,6 +23,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Lm { Context.Session.Initialize(); + MakeObject(Context, new ILogger()); + return 0; } } diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs similarity index 71% rename from Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs rename to Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs index 9875fa2fc..720baa6ec 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs +++ b/Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs @@ -1,19 +1,19 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.IpcServices.Time +namespace Ryujinx.Core.OsHle.IpcServices.Ns { - class ITimeZoneService : IIpcService + class ServiceNs : IIpcService { private Dictionary m_Commands; public IReadOnlyDictionary Commands => m_Commands; - public ITimeZoneService() + public ServiceNs() { m_Commands = new Dictionary() { - //... + //{ 1, Function } }; } } diff --git a/Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs rename to Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs b/Ryujinx.Core/OsHle/Services/ObjHelper.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs rename to Ryujinx.Core/OsHle/Services/ObjHelper.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs b/Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs rename to Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs b/Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs rename to Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs b/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs rename to Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs similarity index 90% rename from Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs rename to Ryujinx.Core/OsHle/Services/ServiceFactory.cs index e9613050f..54fa38ab7 100644 --- a/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs @@ -6,6 +6,7 @@ using Ryujinx.Core.OsHle.IpcServices.Friend; using Ryujinx.Core.OsHle.IpcServices.FspSrv; using Ryujinx.Core.OsHle.IpcServices.Hid; using Ryujinx.Core.OsHle.IpcServices.Lm; +using Ryujinx.Core.OsHle.IpcServices.Ns; using Ryujinx.Core.OsHle.IpcServices.NvServices; using Ryujinx.Core.OsHle.IpcServices.Pctl; using Ryujinx.Core.OsHle.IpcServices.Pl; @@ -24,6 +25,7 @@ namespace Ryujinx.Core.OsHle.IpcServices switch (Name) { case "acc:u0": return new ServiceAcc(); + case "aoc:u": return new ServiceNs(); case "apm": return new ServiceApm(); case "apm:p": return new ServiceApm(); case "appletOE": return new ServiceAppletOE(); @@ -42,6 +44,8 @@ namespace Ryujinx.Core.OsHle.IpcServices case "time:s": return new ServiceTime(); case "time:u": return new ServiceTime(); case "vi:m": return new ServiceVi(); + case "vi:s": return new ServiceVi(); + case "vi:u": return new ServiceVi(); } throw new NotImplementedException(Name); diff --git a/Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs b/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs rename to Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs b/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs rename to Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs b/Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs rename to Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs b/Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs rename to Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs diff --git a/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs new file mode 100644 index 000000000..d220824c5 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs @@ -0,0 +1,69 @@ +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Time +{ + class ITimeZoneService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local); + + public ITimeZoneService() + { + m_Commands = new Dictionary() + { + { 101, ToCalendarTimeWithMyRule } + }; + } + + //(nn::time::PosixTime)-> (nn::time::CalendarTime, nn::time::sf::CalendarAdditionalInfo) + public long ToCalendarTimeWithMyRule(ServiceCtx Context) + { + long PosixTime = Context.RequestData.ReadInt64(); + + Epoch = Epoch.AddSeconds(PosixTime).ToLocalTime(); + + /* + struct CalendarTime { + u16_le year; + u8 month; // Starts at 1 + u8 day; // Starts at 1 + u8 hour; + u8 minute; + u8 second; + INSERT_PADDING_BYTES(1); + }; + */ + Context.ResponseData.Write((short)Epoch.Year); + Context.ResponseData.Write((byte)Epoch.Month); + Context.ResponseData.Write((byte)Epoch.Day); + Context.ResponseData.Write((byte)Epoch.Hour); + Context.ResponseData.Write((byte)Epoch.Minute); + Context.ResponseData.Write((byte)Epoch.Second); + Context.ResponseData.Write((byte)0); + + /* Thanks to TuxSH + struct CalendarAdditionalInfo { + u32 tm_wday; //day of week [0,6] (Sunday = 0) + s32 tm_yday; //day of year [0,365] + struct timezone { + char[8] tz_name; + bool isDaylightSavingTime; + s32 utcOffsetSeconds; + }; + }; + */ + Context.ResponseData.Write((int)Epoch.DayOfWeek); + Context.ResponseData.Write(Epoch.DayOfYear); + Context.ResponseData.Write(new byte[8]); + Context.ResponseData.Write(Convert.ToByte(Epoch.IsDaylightSavingTime())); + Context.ResponseData.Write(0); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs b/Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs rename to Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs b/Ryujinx.Core/OsHle/Services/Time/SystemClockType.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs rename to Ryujinx.Core/OsHle/Services/Time/SystemClockType.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs b/Ryujinx.Core/OsHle/Services/Vi/GbpBuffer.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs rename to Ryujinx.Core/OsHle/Services/Vi/GbpBuffer.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs rename to Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs rename to Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs rename to Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs rename to Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs rename to Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs b/Ryujinx.Core/OsHle/Services/Vi/Parcel.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs rename to Ryujinx.Core/OsHle/Services/Vi/Parcel.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs b/Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs rename to Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs diff --git a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs index 60af1e11d..c5b6da04b 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs @@ -30,6 +30,8 @@ namespace Ryujinx.Core.OsHle.Svc { 0x09, SvcStartThread }, { 0x0b, SvcSleepThread }, { 0x0c, SvcGetThreadPriority }, + { 0x0d, SvcSetThreadPriority }, + { 0x0f, SvcSetThreadCoreMask }, { 0x13, SvcMapSharedMemory }, { 0x14, SvcUnmapSharedMemory }, { 0x15, SvcCreateTransferMemory }, @@ -44,6 +46,7 @@ namespace Ryujinx.Core.OsHle.Svc { 0x1f, SvcConnectToNamedPort }, { 0x21, SvcSendSyncRequest }, { 0x22, SvcSendSyncRequestWithUserBuffer }, + { 0x25, SvcGetThreadId }, { 0x26, SvcBreak }, { 0x27, SvcOutputDebugString }, { 0x29, SvcGetInfo } diff --git a/Ryujinx.Core/OsHle/Svc/SvcThread.cs b/Ryujinx.Core/OsHle/Svc/SvcThread.cs index a635edb15..cc0f980be 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcThread.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThread.cs @@ -81,5 +81,44 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Error codes. } + + private void SvcSetThreadPriority(AThreadState ThreadState) + { + int Handle = (int)ThreadState.X1; + int Prio = (int)ThreadState.X0; + + HThread Thread = Ns.Os.Handles.GetData(Handle); + + if (Thread != null) + { + Thread.Priority = Prio; + + ThreadState.X0 = (int)SvcResult.Success; + } + + //TODO: Error codes. + } + + private void SvcSetThreadCoreMask(AThreadState ThreadState) + { + ThreadState.X0 = (int)SvcResult.Success; + + //TODO: Error codes. + } + + private void SvcGetThreadId(AThreadState ThreadState) + { + int Handle = (int)ThreadState.X0; + + HThread Thread = Ns.Os.Handles.GetData(Handle); + + if (Thread != null) + { + ThreadState.X1 = (ulong)Thread.ThreadId; + ThreadState.X0 = (int)SvcResult.Success; + } + + //TODO: Error codes. + } } } \ No newline at end of file diff --git a/Ryujinx/Ryujinx.conf b/Ryujinx/Ryujinx.conf index 7b9af87ac..e8effac1d 100644 --- a/Ryujinx/Ryujinx.conf +++ b/Ryujinx/Ryujinx.conf @@ -16,6 +16,9 @@ Logging_Enable_Error = true #Enabled print fatal logs Logging_Enable_Fatal = true +#Enabled print Ipc logs +Logging_Enable_Ipc = false + #Saved logs into Ryujinx.log Logging_Enable_LogFile = false From 950011c90fe28fe9edd8ebe0d0a771f6adcff7a1 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 25 Feb 2018 22:14:58 -0300 Subject: [PATCH 27/67] Added initial support for function names from symbol table on the cpu with tracing, fix wrong ImageEnd on executables with MOD0, fix issue on the CPU on input elimination for instruction with more than one register store --- ChocolArm64/AThread.cs | 6 +- ChocolArm64/ATranslator.cs | 82 ++++++++++++++----- ChocolArm64/Decoder/ADecoder.cs | 7 +- ChocolArm64/Events/ACpuTraceEventArgs.cs | 17 ++++ ChocolArm64/Events/AInstExceptionEventArgs.cs | 14 ++++ .../AInstUndefinedEventArgs.cs} | 6 +- ChocolArm64/Instruction/AInstEmitCsel.cs | 5 +- ChocolArm64/State/AInstExceptEventArgs.cs | 14 ---- ChocolArm64/State/AThreadState.cs | 13 +-- ChocolArm64/Translation/AILBarrier.cs | 7 ++ ChocolArm64/Translation/AILBlock.cs | 27 ++++-- ChocolArm64/Translation/AILEmitterCtx.cs | 10 ++- ChocolArm64/Translation/AILOpCodeLoad.cs | 6 +- ChocolArm64/Translation/AILOpCodeStore.cs | 4 +- ChocolArm64/Translation/ALocalAlloc.cs | 8 +- Ryujinx.Core/Loaders/ElfSym.cs | 9 +- Ryujinx.Core/Loaders/Executable.cs | 30 +++++-- Ryujinx.Core/OsHle/Process.cs | 39 ++++++++- Ryujinx.Core/OsHle/Svc/SvcHandler.cs | 3 +- Ryujinx.Tests/Cpu/CpuTest.cs | 3 +- 20 files changed, 217 insertions(+), 93 deletions(-) create mode 100644 ChocolArm64/Events/ACpuTraceEventArgs.cs create mode 100644 ChocolArm64/Events/AInstExceptionEventArgs.cs rename ChocolArm64/{State/AInstUndEventArgs.cs => Events/AInstUndefinedEventArgs.cs} (60%) delete mode 100644 ChocolArm64/State/AInstExceptEventArgs.cs create mode 100644 ChocolArm64/Translation/AILBarrier.cs diff --git a/ChocolArm64/AThread.cs b/ChocolArm64/AThread.cs index 5c0322894..6e018db68 100644 --- a/ChocolArm64/AThread.cs +++ b/ChocolArm64/AThread.cs @@ -28,14 +28,14 @@ namespace ChocolArm64 private object ExecuteLock; - public AThread(AMemory Memory, ThreadPriority Priority, long EntryPoint) + public AThread(ATranslator Translator, AMemory Memory, ThreadPriority Priority, long EntryPoint) { + this.Translator = Translator; this.Memory = Memory; this.Priority = Priority; this.EntryPoint = EntryPoint; ThreadState = new AThreadState(); - Translator = new ATranslator(this); ExecuteLock = new object(); } @@ -55,7 +55,7 @@ namespace ChocolArm64 Work = new Thread(delegate() { - Translator.ExecuteSubroutine(EntryPoint); + Translator.ExecuteSubroutine(this, EntryPoint); Memory.RemoveMonitor(ThreadId); diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs index 96bbc89ea..2daf7bbc9 100644 --- a/ChocolArm64/ATranslator.cs +++ b/ChocolArm64/ATranslator.cs @@ -1,47 +1,70 @@ using ChocolArm64.Decoder; +using ChocolArm64.Events; using ChocolArm64.Instruction; +using ChocolArm64.Memory; using ChocolArm64.Translation; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection.Emit; namespace ChocolArm64 { - class ATranslator + public class ATranslator { - public AThread Thread { get; private set; } + private ConcurrentDictionary CachedSubs; - private Dictionary CachedSubs; + private ConcurrentDictionary SymbolTable; + + public event EventHandler CpuTrace; + + public bool EnableCpuTrace { get; set; } private bool KeepRunning; - public ATranslator(AThread Parent) + public ATranslator(IReadOnlyDictionary SymbolTable = null) { - this.Thread = Parent; + CachedSubs = new ConcurrentDictionary(); - CachedSubs = new Dictionary(); + if (SymbolTable != null) + { + this.SymbolTable = new ConcurrentDictionary(SymbolTable); + } + else + { + this.SymbolTable = new ConcurrentDictionary(); + } KeepRunning = true; } public void StopExecution() => KeepRunning = false; - public void ExecuteSubroutine(long Position) + public void ExecuteSubroutine(AThread Thread, long Position) { do { - if (CachedSubs.TryGetValue(Position, out ATranslatedSub Sub) && !Sub.NeedsReJit) + if (EnableCpuTrace) { - Position = Sub.Execute(Thread.ThreadState, Thread.Memory); + if (!SymbolTable.TryGetValue(Position, out string SubName)) + { + SubName = string.Empty; + } + + CpuTrace?.Invoke(this, new ACpuTraceEventArgs(Position, SubName)); } - else + + if (!CachedSubs.TryGetValue(Position, out ATranslatedSub Sub) || Sub.NeedsReJit) { - Position = TranslateSubroutine(Position).Execute(Thread.ThreadState, Thread.Memory); + Sub = TranslateSubroutine(Thread.Memory, Position); } + + Position = Sub.Execute(Thread.ThreadState, Thread.Memory); } while (Position != 0 && KeepRunning); } - public bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) + internal bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) { if (OpCode.Emitter != AInstEmit.Bl) { @@ -53,24 +76,29 @@ namespace ChocolArm64 return TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub); } - public bool TryGetCachedSub(long Position, out ATranslatedSub Sub) + internal bool TryGetCachedSub(long Position, out ATranslatedSub Sub) { return CachedSubs.TryGetValue(Position, out Sub); } - public bool HasCachedSub(long Position) + internal bool HasCachedSub(long Position) { return CachedSubs.ContainsKey(Position); } - private ATranslatedSub TranslateSubroutine(long Position) + private ATranslatedSub TranslateSubroutine(AMemory Memory, long Position) { - (ABlock[] Graph, ABlock Root) Cfg = ADecoder.DecodeSubroutine(this, Position); + (ABlock[] Graph, ABlock Root) Cfg = ADecoder.DecodeSubroutine(this, Memory, Position); + + string SubName = SymbolTable.GetOrAdd(Position, $"Sub{Position:x16}"); + + PropagateName(Cfg.Graph, SubName); AILEmitterCtx Context = new AILEmitterCtx( this, Cfg.Graph, - Cfg.Root); + Cfg.Root, + SubName); if (Context.CurrBlock.Position != Position) { @@ -95,12 +123,24 @@ namespace ChocolArm64 ATranslatedSub Subroutine = Context.GetSubroutine(); - if (!CachedSubs.TryAdd(Position, Subroutine)) - { - CachedSubs[Position] = Subroutine; - } + CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine); return Subroutine; } + + private void PropagateName(ABlock[] Graph, string Name) + { + foreach (ABlock Block in Graph) + { + AOpCode LastOp = Block.GetLastOp(); + + if (LastOp != null && + (LastOp.Emitter == AInstEmit.Bl || + LastOp.Emitter == AInstEmit.Blr)) + { + SymbolTable.TryAdd(LastOp.Position + 4, Name); + } + } + } } } \ No newline at end of file diff --git a/ChocolArm64/Decoder/ADecoder.cs b/ChocolArm64/Decoder/ADecoder.cs index a3f44e470..443022903 100644 --- a/ChocolArm64/Decoder/ADecoder.cs +++ b/ChocolArm64/Decoder/ADecoder.cs @@ -18,7 +18,10 @@ namespace ChocolArm64.Decoder OpActivators = new ConcurrentDictionary(); } - public static (ABlock[] Graph, ABlock Root) DecodeSubroutine(ATranslator Translator, long Start) + public static (ABlock[] Graph, ABlock Root) DecodeSubroutine( + ATranslator Translator, + AMemory Memory, + long Start) { Dictionary Visited = new Dictionary(); Dictionary VisitedEnd = new Dictionary(); @@ -45,7 +48,7 @@ namespace ChocolArm64.Decoder { ABlock Current = Blocks.Dequeue(); - FillBlock(Translator.Thread.Memory, Current); + FillBlock(Memory, Current); //Set child blocks. "Branch" is the block the branch instruction //points to (when taken), "Next" is the block at the next address, diff --git a/ChocolArm64/Events/ACpuTraceEventArgs.cs b/ChocolArm64/Events/ACpuTraceEventArgs.cs new file mode 100644 index 000000000..fedf3865b --- /dev/null +++ b/ChocolArm64/Events/ACpuTraceEventArgs.cs @@ -0,0 +1,17 @@ +using System; + +namespace ChocolArm64.Events +{ + public class ACpuTraceEventArgs : EventArgs + { + public long Position { get; private set; } + + public string SubName { get; private set; } + + public ACpuTraceEventArgs(long Position, string SubName) + { + this.Position = Position; + this.SubName = SubName; + } + } +} \ No newline at end of file diff --git a/ChocolArm64/Events/AInstExceptionEventArgs.cs b/ChocolArm64/Events/AInstExceptionEventArgs.cs new file mode 100644 index 000000000..34f90c8ee --- /dev/null +++ b/ChocolArm64/Events/AInstExceptionEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace ChocolArm64.Events +{ + public class AInstExceptionEventArgs : EventArgs + { + public int Id { get; private set; } + + public AInstExceptionEventArgs(int Id) + { + this.Id = Id; + } + } +} \ No newline at end of file diff --git a/ChocolArm64/State/AInstUndEventArgs.cs b/ChocolArm64/Events/AInstUndefinedEventArgs.cs similarity index 60% rename from ChocolArm64/State/AInstUndEventArgs.cs rename to ChocolArm64/Events/AInstUndefinedEventArgs.cs index 53de65a33..cdc1728bd 100644 --- a/ChocolArm64/State/AInstUndEventArgs.cs +++ b/ChocolArm64/Events/AInstUndefinedEventArgs.cs @@ -1,13 +1,13 @@ using System; -namespace ChocolArm64.State +namespace ChocolArm64.Events { - public class AInstUndEventArgs : EventArgs + public class AInstUndefinedEventArgs : EventArgs { public long Position { get; private set; } public int RawOpCode { get; private set; } - public AInstUndEventArgs(long Position, int RawOpCode) + public AInstUndefinedEventArgs(long Position, int RawOpCode) { this.Position = Position; this.RawOpCode = RawOpCode; diff --git a/ChocolArm64/Instruction/AInstEmitCsel.cs b/ChocolArm64/Instruction/AInstEmitCsel.cs index 330809806..218767524 100644 --- a/ChocolArm64/Instruction/AInstEmitCsel.cs +++ b/ChocolArm64/Instruction/AInstEmitCsel.cs @@ -44,16 +44,15 @@ namespace ChocolArm64.Instruction Context.Emit(OpCodes.Neg); } - Context.EmitStintzr(Op.Rd); - Context.Emit(OpCodes.Br_S, LblEnd); Context.MarkLabel(LblTrue); Context.EmitLdintzr(Op.Rn); - Context.EmitStintzr(Op.Rd); Context.MarkLabel(LblEnd); + + Context.EmitStintzr(Op.Rd); } } } \ No newline at end of file diff --git a/ChocolArm64/State/AInstExceptEventArgs.cs b/ChocolArm64/State/AInstExceptEventArgs.cs deleted file mode 100644 index f2ee039b6..000000000 --- a/ChocolArm64/State/AInstExceptEventArgs.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace ChocolArm64.State -{ - public class AInstExceptEventArgs : EventArgs - { - public int Id { get; private set; } - - public AInstExceptEventArgs(int Id) - { - this.Id = Id; - } - } -} \ No newline at end of file diff --git a/ChocolArm64/State/AThreadState.cs b/ChocolArm64/State/AThreadState.cs index cdab4034e..2d988a653 100644 --- a/ChocolArm64/State/AThreadState.cs +++ b/ChocolArm64/State/AThreadState.cs @@ -1,3 +1,4 @@ +using ChocolArm64.Events; using System; namespace ChocolArm64.State @@ -42,23 +43,23 @@ namespace ChocolArm64.State public long CntpctEl0 => Environment.TickCount * TicksPerMS; - public event EventHandler Break; - public event EventHandler SvcCall; - public event EventHandler Undefined; + public event EventHandler Break; + public event EventHandler SvcCall; + public event EventHandler Undefined; internal void OnBreak(int Imm) { - Break?.Invoke(this, new AInstExceptEventArgs(Imm)); + Break?.Invoke(this, new AInstExceptionEventArgs(Imm)); } internal void OnSvcCall(int Imm) { - SvcCall?.Invoke(this, new AInstExceptEventArgs(Imm)); + SvcCall?.Invoke(this, new AInstExceptionEventArgs(Imm)); } internal void OnUndefined(long Position, int RawOpCode) { - Undefined?.Invoke(this, new AInstUndEventArgs(Position, RawOpCode)); + Undefined?.Invoke(this, new AInstUndefinedEventArgs(Position, RawOpCode)); } } } \ No newline at end of file diff --git a/ChocolArm64/Translation/AILBarrier.cs b/ChocolArm64/Translation/AILBarrier.cs new file mode 100644 index 000000000..25b08de31 --- /dev/null +++ b/ChocolArm64/Translation/AILBarrier.cs @@ -0,0 +1,7 @@ +namespace ChocolArm64.Translation +{ + struct AILBarrier : IAILEmit + { + public void Emit(AILEmitter Context) { } + } +} \ No newline at end of file diff --git a/ChocolArm64/Translation/AILBlock.cs b/ChocolArm64/Translation/AILBlock.cs index bed195aaf..e580e09c9 100644 --- a/ChocolArm64/Translation/AILBlock.cs +++ b/ChocolArm64/Translation/AILBlock.cs @@ -4,11 +4,13 @@ namespace ChocolArm64.Translation { class AILBlock : IAILEmit { - public long IntInputs { get; private set; } - public long IntOutputs { get; private set; } + public long IntInputs { get; private set; } + public long IntOutputs { get; private set; } + public long IntAwOutputs { get; private set; } - public long VecInputs { get; private set; } - public long VecOutputs { get; private set; } + public long VecInputs { get; private set; } + public long VecOutputs { get; private set; } + public long VecAwOutputs { get; private set; } public bool HasStateStore { get; private set; } @@ -24,13 +26,22 @@ namespace ChocolArm64.Translation public void Add(IAILEmit ILEmitter) { - if (ILEmitter is AILOpCodeLoad Ld && AILEmitter.IsRegIndex(Ld.Index)) + if (ILEmitter is AILBarrier) + { + //Those barriers are used to separate the groups of CIL + //opcodes emitted by each ARM instruction. + //We can only consider the new outputs for doing input elimination + //after all the CIL opcodes used by the instruction being emitted. + IntAwOutputs = IntOutputs; + VecAwOutputs = VecOutputs; + } + else if (ILEmitter is AILOpCodeLoad Ld && AILEmitter.IsRegIndex(Ld.Index)) { switch (Ld.IoType) { - case AIoType.Flag: IntInputs |= ((1L << Ld.Index) << 32) & ~IntOutputs; break; - case AIoType.Int: IntInputs |= (1L << Ld.Index) & ~IntOutputs; break; - case AIoType.Vector: VecInputs |= (1L << Ld.Index) & ~VecOutputs; break; + case AIoType.Flag: IntInputs |= ((1L << Ld.Index) << 32) & ~IntAwOutputs; break; + case AIoType.Int: IntInputs |= (1L << Ld.Index) & ~IntAwOutputs; break; + case AIoType.Vector: VecInputs |= (1L << Ld.Index) & ~VecAwOutputs; break; } } else if (ILEmitter is AILOpCodeStore St) diff --git a/ChocolArm64/Translation/AILEmitterCtx.cs b/ChocolArm64/Translation/AILEmitterCtx.cs index 9199eddc6..ffcfa851a 100644 --- a/ChocolArm64/Translation/AILEmitterCtx.cs +++ b/ChocolArm64/Translation/AILEmitterCtx.cs @@ -39,14 +39,16 @@ namespace ChocolArm64.Translation private const int Tmp4Index = -4; private const int Tmp5Index = -5; - public AILEmitterCtx(ATranslator Translator, ABlock[] Graph, ABlock Root) + public AILEmitterCtx( + ATranslator Translator, + ABlock[] Graph, + ABlock Root, + string SubName) { this.Translator = Translator; this.Graph = Graph; this.Root = Root; - string SubName = $"Sub{Root.Position:X16}"; - Labels = new Dictionary(); Emitter = new AILEmitter(Graph, Root, SubName); @@ -92,6 +94,8 @@ namespace ChocolArm64.Translation } CurrOp.Emitter(this); + + ILBlock.Add(new AILBarrier()); } public bool TryOptEmitSubroutineCall() diff --git a/ChocolArm64/Translation/AILOpCodeLoad.cs b/ChocolArm64/Translation/AILOpCodeLoad.cs index 7cb431e2d..d60ce539f 100644 --- a/ChocolArm64/Translation/AILOpCodeLoad.cs +++ b/ChocolArm64/Translation/AILOpCodeLoad.cs @@ -11,12 +11,10 @@ namespace ChocolArm64.Translation public ARegisterSize RegisterSize { get; private set; } - public AILOpCodeLoad(int Index, AIoType IoType) : this(Index, IoType, ARegisterSize.Int64) { } - - public AILOpCodeLoad(int Index, AIoType IoType, ARegisterSize RegisterSize) + public AILOpCodeLoad(int Index, AIoType IoType, ARegisterSize RegisterSize = 0) { - this.IoType = IoType; this.Index = Index; + this.IoType = IoType; this.RegisterSize = RegisterSize; } diff --git a/ChocolArm64/Translation/AILOpCodeStore.cs b/ChocolArm64/Translation/AILOpCodeStore.cs index c4ea53aba..a0feb4377 100644 --- a/ChocolArm64/Translation/AILOpCodeStore.cs +++ b/ChocolArm64/Translation/AILOpCodeStore.cs @@ -11,10 +11,10 @@ namespace ChocolArm64.Translation public ARegisterSize RegisterSize { get; private set; } - public AILOpCodeStore(int Index, AIoType IoType, ARegisterSize RegisterSize = ARegisterSize.Int64) + public AILOpCodeStore(int Index, AIoType IoType, ARegisterSize RegisterSize = 0) { - this.IoType = IoType; this.Index = Index; + this.IoType = IoType; this.RegisterSize = RegisterSize; } diff --git a/ChocolArm64/Translation/ALocalAlloc.cs b/ChocolArm64/Translation/ALocalAlloc.cs index 0661ddc8d..f23af9c76 100644 --- a/ChocolArm64/Translation/ALocalAlloc.cs +++ b/ChocolArm64/Translation/ALocalAlloc.cs @@ -67,7 +67,7 @@ namespace ChocolArm64.Translation public long VecOutputs; } - private const int MaxOptGraphLength = 120; + private const int MaxOptGraphLength = 55; public ALocalAlloc(AILBlock[] Graph, AILBlock Root) { @@ -149,11 +149,7 @@ namespace ChocolArm64.Translation if (RetTarget) { - BlkIO.Entry = Block; - BlkIO.IntInputs = 0; - BlkIO.VecInputs = 0; - BlkIO.IntOutputs = 0; - BlkIO.VecOutputs = 0; + BlkIO.Entry = Block; } else { diff --git a/Ryujinx.Core/Loaders/ElfSym.cs b/Ryujinx.Core/Loaders/ElfSym.cs index 35a45500a..89e7c61f6 100644 --- a/Ryujinx.Core/Loaders/ElfSym.cs +++ b/Ryujinx.Core/Loaders/ElfSym.cs @@ -16,17 +16,15 @@ namespace Ryujinx.Core.Loaders Binding == ElfSymBinding.STB_GLOBAL || Binding == ElfSymBinding.STB_WEAK; - public int SHIdx { get; private set; } - public long ValueAbs { get; private set; } - public long Value { get; private set; } - public long Size { get; private set; } + public int SHIdx { get; private set; } + public long Value { get; private set; } + public long Size { get; private set; } public ElfSym( string Name, int Info, int Other, int SHIdx, - long ImageBase, long Value, long Size) { @@ -35,7 +33,6 @@ namespace Ryujinx.Core.Loaders this.Binding = (ElfSymBinding)(Info >> 4); this.Visibility = (ElfSymVisibility)Other; this.SHIdx = SHIdx; - this.ValueAbs = Value + ImageBase; this.Value = Value; this.Size = Size; } diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index e26608389..c6770c7b3 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -9,13 +9,21 @@ namespace Ryujinx.Core.Loaders { private AMemory Memory; - private ElfDyn[] Dynamic; + private List Dynamic; + + private Dictionary m_SymbolTable; + + public IReadOnlyDictionary SymbolTable => m_SymbolTable; public long ImageBase { get; private set; } public long ImageEnd { get; private set; } public Executable(IExecutable Exe, AMemory Memory, long ImageBase) { + Dynamic = new List(); + + m_SymbolTable = new Dictionary(); + this.Memory = Memory; this.ImageBase = ImageBase; this.ImageEnd = ImageBase; @@ -48,9 +56,7 @@ namespace Ryujinx.Core.Loaders MapBss(BssStartOffset, BssEndOffset - BssStartOffset); - ImageEnd = BssEndOffset; - - List Dynamic = new List(); + ImageEnd = ImageBase + BssEndOffset; while (true) { @@ -69,7 +75,19 @@ namespace Ryujinx.Core.Loaders Dynamic.Add(new ElfDyn(Tag, Value)); } - this.Dynamic = Dynamic.ToArray(); + long StrTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_STRTAB); + long SymTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_SYMTAB); + + long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT); + + while ((ulong)SymTblAddr < (ulong)StrTblAddr) + { + ElfSym Sym = GetSymbol(SymTblAddr, StrTblAddr); + + m_SymbolTable.TryAdd(Sym.Value, Sym.Name); + + SymTblAddr += SymEntSize; + } } private void WriteData( @@ -135,7 +153,7 @@ namespace Ryujinx.Core.Loaders Name += (char)Chr; } - return new ElfSym(Name, Info, Other, SHIdx, ImageBase, Value, Size); + return new ElfSym(Name, Info, Other, SHIdx, Value, Size); } private long GetFirstValue(ElfDynTag Tag) diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index 3e265ed34..60e71ee99 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -1,6 +1,6 @@ using ChocolArm64; +using ChocolArm64.Events; using ChocolArm64.Memory; -using ChocolArm64.State; using Ryujinx.Core.Loaders; using Ryujinx.Core.Loaders.Executables; using Ryujinx.Core.OsHle.Exceptions; @@ -24,6 +24,8 @@ namespace Ryujinx.Core.OsHle private Switch Ns; + private ATranslator Translator; + public int ProcessId { get; private set; } public AMemory Memory { get; private set; } @@ -171,7 +173,7 @@ namespace Ryujinx.Core.OsHle ThreadPrio = ThreadPriority.Lowest; } - AThread Thread = new AThread(Memory, ThreadPrio, EntryPoint); + AThread Thread = new AThread(GetTranslator(), Memory, ThreadPrio, EntryPoint); HThread ThreadHnd = new HThread(Thread, ProcessorId, Priority); @@ -201,16 +203,45 @@ namespace Ryujinx.Core.OsHle return Handle; } - private void BreakHandler(object sender, AInstExceptEventArgs e) + private void BreakHandler(object sender, AInstExceptionEventArgs e) { throw new GuestBrokeExecutionException(); } - private void UndefinedHandler(object sender, AInstUndEventArgs e) + private void UndefinedHandler(object sender, AInstUndefinedEventArgs e) { throw new UndefinedInstructionException(e.Position, e.RawOpCode); } + private ATranslator GetTranslator() + { + if (Translator == null) + { + Dictionary SymbolTable = new Dictionary(); + + foreach (Executable Exe in Executables) + { + foreach (KeyValuePair KV in Exe.SymbolTable) + { + SymbolTable.Add(Exe.ImageBase + KV.Key, KV.Value); + } + } + + Translator = new ATranslator(SymbolTable); + + + + Translator.CpuTrace += CpuTraceHandler; + } + + return Translator; + } + + private void CpuTraceHandler(object sender, ACpuTraceEventArgs e) + { + Logging.Info($"Executing at 0x{e.Position:x16} {e.SubName}"); + } + private int GetFreeTlsSlot(AThread Thread) { for (int Index = 1; Index < TotalTlsSlots; Index++) diff --git a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs index c5b6da04b..ec53f47ff 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs @@ -1,3 +1,4 @@ +using ChocolArm64.Events; using ChocolArm64.Memory; using ChocolArm64.State; using System; @@ -62,7 +63,7 @@ namespace Ryujinx.Core.OsHle.Svc Rng = new Random(); } - public void SvcCall(object sender, AInstExceptEventArgs e) + public void SvcCall(object sender, AInstExceptionEventArgs e) { AThreadState ThreadState = (AThreadState)sender; diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index 7af2d55d0..bf9d90e33 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -30,10 +30,11 @@ namespace Ryujinx.Tests.Cpu EntryPoint = Position; Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); + ATranslator Translator = new ATranslator(); Allocator = new AMemoryAlloc(); Memory = new AMemory(Ram, Allocator); Memory.Manager.MapPhys(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute); - Thread = new AThread(Memory, ThreadPriority.Normal, EntryPoint); + Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint); } [TearDown] From 13214ffa43f65686a9a5a99ca1c78b6c405a34db Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 25 Feb 2018 22:44:30 -0300 Subject: [PATCH 28/67] Fix regression introduced on last commit with wrong ImageEnd --- Ryujinx.Core/Loaders/Executable.cs | 2 +- Ryujinx.Core/OsHle/Homebrew.cs | 21 ++++++++++++++------- Ryujinx.Core/OsHle/Process.cs | 12 ++++++------ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index c6770c7b3..95cb7d6f6 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -56,7 +56,7 @@ namespace Ryujinx.Core.Loaders MapBss(BssStartOffset, BssEndOffset - BssStartOffset); - ImageEnd = ImageBase + BssEndOffset; + ImageEnd = BssEndOffset; while (true) { diff --git a/Ryujinx.Core/OsHle/Homebrew.cs b/Ryujinx.Core/OsHle/Homebrew.cs index b69b31c99..f177b37e3 100644 --- a/Ryujinx.Core/OsHle/Homebrew.cs +++ b/Ryujinx.Core/OsHle/Homebrew.cs @@ -2,26 +2,33 @@ namespace Ryujinx.Core.OsHle { - public class Homebrew + static class Homebrew { //http://switchbrew.org/index.php?title=Homebrew_ABI - public Homebrew(AMemory Memory, long Position, long MainThreadHandle) + public static void WriteHbAbiData(AMemory Memory, long Position, int MainThreadHandle) { - //(NbrKeys * LoaderConfigEntrySize) + 2 buffers for Key2 - long Size = (4 * 0x18) + 0x1000; - Memory.Manager.MapPhys(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW); + Memory.Manager.MapPhys(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW); //MainThreadHandle WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle); + //NextLoadPath - WriteConfigEntry(Memory, ref Position, 2, 0, Position + Size, Position + Size + 0x200); + WriteConfigEntry(Memory, ref Position, 2, 0, Position + 0x200, Position + 0x400); + //AppletType WriteConfigEntry(Memory, ref Position, 7); + //EndOfList WriteConfigEntry(Memory, ref Position, 0); } - private void WriteConfigEntry(AMemory Memory, ref long Position, int Key, int Flags = 0, long Value0 = 0L, long Value1 = 0L) + private static void WriteConfigEntry( + AMemory Memory, + ref long Position, + int Key, + int Flags = 0, + long Value0 = 0, + long Value1 = 0) { Memory.WriteInt32(Position + 0x00, Key); Memory.WriteInt32(Position + 0x04, Flags); diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index 60e71ee99..9ca9a2bd5 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -113,9 +113,11 @@ namespace Ryujinx.Core.OsHle if (UseHbAbi) { - Homebrew Homebrew_ABI = new Homebrew(Memory, Executables[0].ImageEnd, (long)Handle); + long HbAbiDataPosition = (Executables[0].ImageEnd + 0xfff) & ~0xfff; - MainThread.Thread.ThreadState.X0 = (ulong)Executables[0].ImageEnd; + Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle); + + MainThread.Thread.ThreadState.X0 = (ulong)HbAbiDataPosition; MainThread.Thread.ThreadState.X1 = ulong.MaxValue; } @@ -223,14 +225,12 @@ namespace Ryujinx.Core.OsHle { foreach (KeyValuePair KV in Exe.SymbolTable) { - SymbolTable.Add(Exe.ImageBase + KV.Key, KV.Value); + SymbolTable.TryAdd(Exe.ImageBase + KV.Key, KV.Value); } } Translator = new ATranslator(SymbolTable); - - Translator.CpuTrace += CpuTraceHandler; } @@ -239,7 +239,7 @@ namespace Ryujinx.Core.OsHle private void CpuTraceHandler(object sender, ACpuTraceEventArgs e) { - Logging.Info($"Executing at 0x{e.Position:x16} {e.SubName}"); + Logging.Trace($"Executing at 0x{e.Position:x16} {e.SubName}"); } private int GetFreeTlsSlot(AThread Thread) From f6dc86c6a097f305701af32e77a2d8995a4385cc Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 25 Feb 2018 22:53:01 -0300 Subject: [PATCH 29/67] Implement SvcSetMemoryAttribute --- ChocolArm64/Memory/AMemoryMgr.cs | 30 +++++++++++++++++++ .../Services/Am/IApplicationFunctions.cs | 1 - Ryujinx.Core/OsHle/Svc/SvcMemory.cs | 10 ++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/ChocolArm64/Memory/AMemoryMgr.cs b/ChocolArm64/Memory/AMemoryMgr.cs index 05284059e..c8869e03e 100644 --- a/ChocolArm64/Memory/AMemoryMgr.cs +++ b/ChocolArm64/Memory/AMemoryMgr.cs @@ -234,6 +234,36 @@ namespace ChocolArm64.Memory BaseEntry.Perm); } + public void ClearAttrBit(long Position, long Size, int Bit) + { + while (Size > 0) + { + PTEntry Entry = GetPTEntry(Position); + + Entry.Attr &= ~(1 << Bit); + + SetPTEntry(Position, Entry); + + Position += PageSize; + Size -= PageSize; + } + } + + public void SetAttrBit(long Position, long Size, int Bit) + { + while (Size > 0) + { + PTEntry Entry = GetPTEntry(Position); + + Entry.Attr |= (1 << Bit); + + SetPTEntry(Position, Entry); + + Position += PageSize; + Size -= PageSize; + } + } + public bool HasPermission(long Position, AMemoryPerm Perm) { return GetPTEntry(Position).Perm.HasFlag(Perm); diff --git a/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs b/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs index 6c5beeb3e..c989cdd44 100644 --- a/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs +++ b/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs @@ -1,5 +1,4 @@ using Ryujinx.Core.OsHle.Ipc; -using System; using System.Collections.Generic; using System.IO; diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index 7528f4e03..6ca27f16d 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -23,7 +23,15 @@ namespace Ryujinx.Core.OsHle.Svc int State0 = (int)ThreadState.X2; int State1 = (int)ThreadState.X3; - //TODO + if ((State0 == 0 && State1 == 0) || + (State0 == 8 && State1 == 0)) + { + Memory.Manager.ClearAttrBit(Position, Size, 3); + } + else if (State0 == 8 && State1 == 8) + { + Memory.Manager.SetAttrBit(Position, Size, 3); + } ThreadState.X0 = (int)SvcResult.Success; } From 708761963e09ceb4619f8f21fffc7af051a8f020 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 26 Feb 2018 15:56:34 -0300 Subject: [PATCH 30/67] Fix corner cases of ADCS and SBFM --- ChocolArm64/Instruction/AInstEmitAlu.cs | 2 +- ChocolArm64/Instruction/AInstEmitAluHelper.cs | 25 +++++++++++++++++++ ChocolArm64/Instruction/AInstEmitBfm.cs | 9 ------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/ChocolArm64/Instruction/AInstEmitAlu.cs b/ChocolArm64/Instruction/AInstEmitAlu.cs index 71d9a6607..57020364b 100644 --- a/ChocolArm64/Instruction/AInstEmitAlu.cs +++ b/ChocolArm64/Instruction/AInstEmitAlu.cs @@ -39,7 +39,7 @@ namespace ChocolArm64.Instruction { Context.EmitZNFlagCheck(); - EmitAddsCCheck(Context); + EmitAdcsCCheck(Context); EmitAddsVCheck(Context); } diff --git a/ChocolArm64/Instruction/AInstEmitAluHelper.cs b/ChocolArm64/Instruction/AInstEmitAluHelper.cs index b2ea92a65..ef9dd7a7a 100644 --- a/ChocolArm64/Instruction/AInstEmitAluHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitAluHelper.cs @@ -7,6 +7,31 @@ namespace ChocolArm64.Instruction { static class AInstEmitAluHelper { + public static void EmitAdcsCCheck(AILEmitterCtx Context) + { + //C = (Rd == Rn && CIn) || Rd < Rn + Context.EmitSttmp(); + Context.EmitLdtmp(); + Context.EmitLdtmp(); + + EmitDataLoadRn(Context); + + Context.Emit(OpCodes.Ceq); + + Context.EmitLdflg((int)APState.CBit); + + Context.Emit(OpCodes.And); + + Context.EmitLdtmp(); + + EmitDataLoadRn(Context); + + Context.Emit(OpCodes.Clt_Un); + Context.Emit(OpCodes.Or); + + Context.EmitStflg((int)APState.CBit); + } + public static void EmitAddsCCheck(AILEmitterCtx Context) { //C = Rd < Rn diff --git a/ChocolArm64/Instruction/AInstEmitBfm.cs b/ChocolArm64/Instruction/AInstEmitBfm.cs index 823af7385..2e8f25085 100644 --- a/ChocolArm64/Instruction/AInstEmitBfm.cs +++ b/ChocolArm64/Instruction/AInstEmitBfm.cs @@ -54,15 +54,6 @@ namespace ChocolArm64.Instruction { EmitSbfmCast(Context, OpCodes.Conv_I4); } - else if (Op.Shift == 0) - { - Context.EmitLdintzr(Op.Rn); - - Context.EmitLsl(BitsCount - 1 - Op.Pos); - Context.EmitAsr(BitsCount - 1); - - Context.EmitStintzr(Op.Rd); - } else { EmitBfmLoadRn(Context); From f876bd2a805805d9e5dc350b65e8d02fbc5b88b5 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 27 Feb 2018 20:45:07 -0300 Subject: [PATCH 31/67] Change SvcGetInfo 5 to return actual heap size, remove AMemoryAlloc since it is no longer needed with direct memory access, move some memory management logic out of AMemoryMgr, change default virtual filesystem path to AppData --- ChocolArm64/Memory/AMemory.cs | 4 +- ChocolArm64/Memory/AMemoryAlloc.cs | 35 ---- ChocolArm64/Memory/AMemoryMapInfo.cs | 2 +- ChocolArm64/Memory/AMemoryMgr.cs | 198 ++++++++--------------- Ryujinx.Core/Loaders/Executable.cs | 4 +- Ryujinx.Core/OsHle/Handles/HSharedMem.cs | 2 +- Ryujinx.Core/OsHle/Homebrew.cs | 2 +- Ryujinx.Core/OsHle/Horizon.cs | 23 +-- Ryujinx.Core/OsHle/MemoryInfo.cs | 28 ---- Ryujinx.Core/OsHle/MemoryRegions.cs | 21 ++- Ryujinx.Core/OsHle/Process.cs | 52 +++--- Ryujinx.Core/OsHle/Svc/SvcHandler.cs | 3 + Ryujinx.Core/OsHle/Svc/SvcMemory.cs | 65 ++++++-- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 128 +++++++-------- Ryujinx.Core/VirtualFs.cs | 12 +- Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs | 2 +- Ryujinx.Tests/Cpu/CpuTest.cs | 7 +- 17 files changed, 251 insertions(+), 337 deletions(-) delete mode 100644 ChocolArm64/Memory/AMemoryAlloc.cs delete mode 100644 Ryujinx.Core/OsHle/MemoryInfo.cs diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs index f2abffbf4..0d202fed3 100644 --- a/ChocolArm64/Memory/AMemory.cs +++ b/ChocolArm64/Memory/AMemory.cs @@ -41,9 +41,9 @@ namespace ChocolArm64.Memory private byte* RamPtr; - public AMemory(IntPtr Ram, AMemoryAlloc Allocator) + public AMemory(IntPtr Ram) { - Manager = new AMemoryMgr(Allocator); + Manager = new AMemoryMgr(); Monitors = new Dictionary(); diff --git a/ChocolArm64/Memory/AMemoryAlloc.cs b/ChocolArm64/Memory/AMemoryAlloc.cs deleted file mode 100644 index b11e77931..000000000 --- a/ChocolArm64/Memory/AMemoryAlloc.cs +++ /dev/null @@ -1,35 +0,0 @@ -using ChocolArm64.Exceptions; - -namespace ChocolArm64.Memory -{ - public class AMemoryAlloc - { - private long PhysPos; - - public long Alloc(long Size) - { - long Position = PhysPos; - - Size = AMemoryHelper.PageRoundUp(Size); - - PhysPos += Size; - - if (PhysPos > AMemoryMgr.RamSize || PhysPos < 0) - { - throw new VmmOutOfMemoryException(Size); - } - - return Position; - } - - public void Free(long Position) - { - //TODO - } - - public long GetFreeMem() - { - return AMemoryMgr.RamSize - PhysPos; - } - } -} \ No newline at end of file diff --git a/ChocolArm64/Memory/AMemoryMapInfo.cs b/ChocolArm64/Memory/AMemoryMapInfo.cs index 44b2cc079..02dd3055c 100644 --- a/ChocolArm64/Memory/AMemoryMapInfo.cs +++ b/ChocolArm64/Memory/AMemoryMapInfo.cs @@ -1,6 +1,6 @@ namespace ChocolArm64.Memory { - public struct AMemoryMapInfo + public class AMemoryMapInfo { public long Position { get; private set; } public long Size { get; private set; } diff --git a/ChocolArm64/Memory/AMemoryMgr.cs b/ChocolArm64/Memory/AMemoryMgr.cs index c8869e03e..bc3644524 100644 --- a/ChocolArm64/Memory/AMemoryMgr.cs +++ b/ChocolArm64/Memory/AMemoryMgr.cs @@ -1,3 +1,5 @@ +using System; + namespace ChocolArm64.Memory { public class AMemoryMgr @@ -5,22 +7,20 @@ namespace ChocolArm64.Memory public const long AddrSize = RamSize; public const long RamSize = 4L * 1024 * 1024 * 1024; - private const int PTLvl0Bits = 11; - private const int PTLvl1Bits = 13; - private const int PTPageBits = 12; + private const int PTLvl0Bits = 10; + private const int PTLvl1Bits = 10; + private const int PTPageBits = 12; - private const int PTLvl0Size = 1 << PTLvl0Bits; - private const int PTLvl1Size = 1 << PTLvl1Bits; - public const int PageSize = 1 << PTPageBits; + private const int PTLvl0Size = 1 << PTLvl0Bits; + private const int PTLvl1Size = 1 << PTLvl1Bits; + public const int PageSize = 1 << PTPageBits; - private const int PTLvl0Mask = PTLvl0Size - 1; - private const int PTLvl1Mask = PTLvl1Size - 1; - public const int PageMask = PageSize - 1; + private const int PTLvl0Mask = PTLvl0Size - 1; + private const int PTLvl1Mask = PTLvl1Size - 1; + public const int PageMask = PageSize - 1; - private const int PTLvl0Bit = PTPageBits + PTLvl0Bits; - private const int PTLvl1Bit = PTPageBits; - - private AMemoryAlloc Allocator; + private const int PTLvl0Bit = PTPageBits + PTLvl1Bits; + private const int PTLvl1Bit = PTPageBits; private enum PTMap { @@ -47,132 +47,24 @@ namespace ChocolArm64.Memory private PTEntry[][] PageTable; - private bool IsHeapInitialized; - - public long HeapAddr { get; private set; } - public long HeapSize { get; private set; } - - public AMemoryMgr(AMemoryAlloc Allocator) + public AMemoryMgr() { - this.Allocator = Allocator; - PageTable = new PTEntry[PTLvl0Size][]; } - public long GetTotalMemorySize() + public void Map(long Position, long Size, int Type, AMemoryPerm Perm) { - return Allocator.GetFreeMem() + GetUsedMemorySize(); + SetPTEntry(Position, Size, new PTEntry(PTMap.Mapped, Perm, Type, 0)); } - public long GetUsedMemorySize() + public void Unmap(long Position, long Size) { - long Size = 0; - - for (int L0 = 0; L0 < PageTable.Length; L0++) - { - if (PageTable[L0] == null) - { - continue; - } - - for (int L1 = 0; L1 < PageTable[L0].Length; L1++) - { - Size += PageTable[L0][L1].Map != PTMap.Unmapped ? PageSize : 0; - } - } - - return Size; + SetPTEntry(Position, Size, new PTEntry(PTMap.Unmapped, 0, 0, 0)); } - public bool SetHeapAddr(long Position) + public void Unmap(long Position, long Size, int Type) { - if (!IsHeapInitialized) - { - HeapAddr = Position; - - IsHeapInitialized = true; - - return true; - } - - return false; - } - - public void SetHeapSize(long Size, int Type) - { - //TODO: Return error when theres no enough space to allocate heap. - Size = AMemoryHelper.PageRoundUp(Size); - - long Position = HeapAddr; - - if ((ulong)Size < (ulong)HeapSize) - { - //Try to free now free area if size is smaller than old size. - Position += Size; - - while ((ulong)Size < (ulong)HeapSize) - { - Allocator.Free(Position); - - Position += PageSize; - } - } - else - { - //Allocate extra needed size. - Position += HeapSize; - Size -= HeapSize; - - MapPhys(Position, Size, Type, AMemoryPerm.RW); - } - - HeapSize = Size; - } - - public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm) - { - while (Size > 0) - { - if (!IsMapped(Position)) - { - SetPTEntry(Position, new PTEntry(PTMap.Mapped, Perm, Type, 0)); - } - - long CPgSize = PageSize - (Position & PageMask); - - Position += CPgSize; - Size -= CPgSize; - } - } - - public void MapMirror(long Src, long Dst, long Size, int Type) - { - Src = AMemoryHelper.PageRoundDown(Src); - Dst = AMemoryHelper.PageRoundDown(Dst); - - Size = AMemoryHelper.PageRoundUp(Size); - - long PagesCount = Size / PageSize; - - while (PagesCount-- > 0) - { - PTEntry SrcEntry = GetPTEntry(Src); - PTEntry DstEntry = GetPTEntry(Dst); - - DstEntry.Map = PTMap.Mapped; - DstEntry.Type = Type; - DstEntry.Perm = SrcEntry.Perm; - - SrcEntry.Perm = AMemoryPerm.None; - - SrcEntry.Attr |= 1; - - SetPTEntry(Src, SrcEntry); - SetPTEntry(Dst, DstEntry); - - Src += PageSize; - Dst += PageSize; - } + SetPTEntry(Position, Size, Type, new PTEntry(PTMap.Unmapped, 0, 0, 0)); } public void Reprotect(long Position, long Size, AMemoryPerm Perm) @@ -197,12 +89,22 @@ namespace ChocolArm64.Memory public AMemoryMapInfo GetMapInfo(long Position) { + if (!IsValidPosition(Position)) + { + return null; + } + Position = AMemoryHelper.PageRoundDown(Position); PTEntry BaseEntry = GetPTEntry(Position); bool IsSameSegment(long Pos) { + if (!IsValidPosition(Pos)) + { + return false; + } + PTEntry Entry = GetPTEntry(Pos); return Entry.Map == BaseEntry.Map && @@ -269,6 +171,16 @@ namespace ChocolArm64.Memory return GetPTEntry(Position).Perm.HasFlag(Perm); } + public bool IsValidPosition(long Position) + { + if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0) + { + return false; + } + + return true; + } + public bool IsMapped(long Position) { if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0) @@ -300,8 +212,38 @@ namespace ChocolArm64.Memory return PageTable[L0][L1]; } + private void SetPTEntry(long Position, long Size, PTEntry Entry) + { + while (Size > 0) + { + SetPTEntry(Position, Entry); + + Position += PageSize; + Size -= PageSize; + } + } + + private void SetPTEntry(long Position, long Size, int Type, PTEntry Entry) + { + while (Size > 0) + { + if (GetPTEntry(Position).Type == Type) + { + SetPTEntry(Position, Entry); + } + + Position += PageSize; + Size -= PageSize; + } + } + private void SetPTEntry(long Position, PTEntry Entry) { + if (!IsValidPosition(Position)) + { + throw new ArgumentOutOfRangeException(nameof(Position)); + } + long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask; diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index 95cb7d6f6..fa204460f 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -96,7 +96,7 @@ namespace Ryujinx.Core.Loaders MemoryType Type, AMemoryPerm Perm) { - Memory.Manager.MapPhys(Position, Data.Count, (int)Type, AMemoryPerm.Write); + Memory.Manager.Map(Position, Data.Count, (int)Type, AMemoryPerm.Write); for (int Index = 0; Index < Data.Count; Index++) { @@ -108,7 +108,7 @@ namespace Ryujinx.Core.Loaders private void MapBss(long Position, long Size) { - Memory.Manager.MapPhys(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW); + Memory.Manager.Map(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW); } private ElfRel GetRelocation(long Position) diff --git a/Ryujinx.Core/OsHle/Handles/HSharedMem.cs b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs index 3d56ff920..9cd0a0d47 100644 --- a/Ryujinx.Core/OsHle/Handles/HSharedMem.cs +++ b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Core.OsHle.Handles public EventHandler MemoryMapped; public EventHandler MemoryUnmapped; - public HSharedMem(long PhysPos) + public HSharedMem() { Positions = new List(); } diff --git a/Ryujinx.Core/OsHle/Homebrew.cs b/Ryujinx.Core/OsHle/Homebrew.cs index f177b37e3..e2e95e4d4 100644 --- a/Ryujinx.Core/OsHle/Homebrew.cs +++ b/Ryujinx.Core/OsHle/Homebrew.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle //http://switchbrew.org/index.php?title=Homebrew_ABI public static void WriteHbAbiData(AMemory Memory, long Position, int MainThreadHandle) { - Memory.Manager.MapPhys(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW); + Memory.Manager.Map(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW); //MainThreadHandle WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle); diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs index 9929102d6..c23891439 100644 --- a/Ryujinx.Core/OsHle/Horizon.cs +++ b/Ryujinx.Core/OsHle/Horizon.cs @@ -1,4 +1,3 @@ -using ChocolArm64.Memory; using Ryujinx.Core.Loaders.Executables; using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Utilities; @@ -16,9 +15,6 @@ namespace Ryujinx.Core.OsHle internal int HidHandle { get; private set; } internal int FontHandle { get; private set; } - public long HidOffset { get; private set; } - public long FontOffset { get; private set; } - internal IdPool IdGen { get; private set; } internal IdPool NvMapIds { get; private set; } @@ -33,8 +29,6 @@ namespace Ryujinx.Core.OsHle private HSharedMem HidSharedMem; - private AMemoryAlloc Allocator; - private Switch Ns; public Horizon(Switch Ns) @@ -53,18 +47,13 @@ namespace Ryujinx.Core.OsHle Processes = new ConcurrentDictionary(); - Allocator = new AMemoryAlloc(); - - HidOffset = Allocator.Alloc(HidSize); - FontOffset = Allocator.Alloc(FontSize); - - HidSharedMem = new HSharedMem(HidOffset); + HidSharedMem = new HSharedMem(); HidSharedMem.MemoryMapped += HidInit; HidHandle = Handles.GenerateId(HidSharedMem); - FontHandle = Handles.GenerateId(new HSharedMem(FontOffset)); + FontHandle = Handles.GenerateId(new HSharedMem()); } public void LoadCart(string ExeFsDir, string RomFsFile = null) @@ -76,7 +65,7 @@ namespace Ryujinx.Core.OsHle int ProcessId = IdGen.GenerateId(); - Process MainProcess = new Process(Ns, Allocator, ProcessId); + Process MainProcess = new Process(Ns, ProcessId); void LoadNso(string FileName) { @@ -106,7 +95,6 @@ namespace Ryujinx.Core.OsHle LoadNso("subsdk*"); LoadNso("sdk"); - MainProcess.InitializeHeap(); MainProcess.Run(); Processes.TryAdd(ProcessId, MainProcess); @@ -118,7 +106,7 @@ namespace Ryujinx.Core.OsHle int ProcessId = IdGen.GenerateId(); - Process MainProcess = new Process(Ns, Allocator, ProcessId); + Process MainProcess = new Process(Ns, ProcessId); using (FileStream Input = new FileStream(FileName, FileMode.Open)) { @@ -128,7 +116,6 @@ namespace Ryujinx.Core.OsHle } MainProcess.SetEmptyArgs(); - MainProcess.InitializeHeap(); MainProcess.Run(IsNro); Processes.TryAdd(ProcessId, MainProcess); @@ -186,7 +173,7 @@ namespace Ryujinx.Core.OsHle if (SharedMem.TryGetLastVirtualPosition(out long Position)) { - Logging.Info($"HID shared memory successfully mapped to {Position:x16}!"); + Logging.Info($"HID shared memory successfully mapped to 0x{Position:x16}!"); Ns.Hid.Init(Position); } diff --git a/Ryujinx.Core/OsHle/MemoryInfo.cs b/Ryujinx.Core/OsHle/MemoryInfo.cs deleted file mode 100644 index 76a4bef3b..000000000 --- a/Ryujinx.Core/OsHle/MemoryInfo.cs +++ /dev/null @@ -1,28 +0,0 @@ -using ChocolArm64.Memory; - -namespace Ryujinx.Core.OsHle -{ - struct MemoryInfo - { - public long BaseAddress; - public long Size; - public int MemType; - public int MemAttr; - public int MemPerm; - public int IpcRefCount; - public int DeviceRefCount; - public int Padding; //SBZ - - public MemoryInfo(AMemoryMapInfo MapInfo) - { - BaseAddress = MapInfo.Position; - Size = MapInfo.Size; - MemType = MapInfo.Type; - MemAttr = MapInfo.Attr; - MemPerm = (int)MapInfo.Perm; - IpcRefCount = 0; - DeviceRefCount = 0; - Padding = 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/MemoryRegions.cs b/Ryujinx.Core/OsHle/MemoryRegions.cs index 86d266f60..3b6904260 100644 --- a/Ryujinx.Core/OsHle/MemoryRegions.cs +++ b/Ryujinx.Core/OsHle/MemoryRegions.cs @@ -1,11 +1,28 @@ +using ChocolArm64.Memory; + namespace Ryujinx.Core.OsHle { static class MemoryRegions { - public const long MapRegionAddress = 0x80000000; + public const long AddrSpaceStart = 0x08000000; + + public const long MapRegionAddress = 0x10000000; public const long MapRegionSize = 0x40000000; + public const long MainStackSize = 0x100000; + + public const long MainStackAddress = AMemoryMgr.AddrSize - MainStackSize; + + public const long TlsPagesSize = 0x4000; + + public const long TlsPagesAddress = MainStackAddress - TlsPagesSize; + public const long HeapRegionAddress = MapRegionAddress + MapRegionSize; - public const long HeapRegionSize = 0x40000000; + + public const long TotalMemoryUsed = HeapRegionAddress + TlsPagesSize + MainStackSize; + + public const long TotalMemoryAvailable = AMemoryMgr.RamSize - AddrSpaceStart; + + public const long AddrSpaceSize = AMemoryMgr.AddrSize - AddrSpaceStart; } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index 9ca9a2bd5..f0b568c8c 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -15,19 +15,15 @@ namespace Ryujinx.Core.OsHle { public class Process : IDisposable { - private const int MaxStackSize = 8 * 1024 * 1024; - private const int TlsSize = 0x200; private const int TotalTlsSlots = 32; - private const int TlsTotalSize = TotalTlsSlots * TlsSize; - private const long TlsPageAddr = (AMemoryMgr.AddrSize - TlsTotalSize) & ~AMemoryMgr.PageMask; private Switch Ns; - private ATranslator Translator; - public int ProcessId { get; private set; } + private ATranslator Translator; + public AMemory Memory { get; private set; } public KProcessScheduler Scheduler { get; private set; } @@ -44,12 +40,12 @@ namespace Ryujinx.Core.OsHle private long ImageBase; - public Process(Switch Ns, AMemoryAlloc Allocator, int ProcessId) + public Process(Switch Ns, int ProcessId) { this.Ns = Ns; this.ProcessId = ProcessId; - Memory = new AMemory(Ns.Ram, Allocator); + Memory = new AMemory(Ns.Ram); Scheduler = new KProcessScheduler(); @@ -61,13 +57,12 @@ namespace Ryujinx.Core.OsHle Executables = new List(); - ImageBase = 0x8000000; + ImageBase = MemoryRegions.AddrSpaceStart; - Memory.Manager.MapPhys( - TlsPageAddr, - TlsTotalSize, - (int)MemoryType.ThreadLocal, - AMemoryPerm.RW); + MapRWMemRegion( + MemoryRegions.TlsPagesAddress, + MemoryRegions.TlsPagesSize, + MemoryType.ThreadLocal); } public void LoadProgram(IExecutable Program) @@ -86,11 +81,6 @@ namespace Ryujinx.Core.OsHle ImageBase += AMemoryMgr.PageSize; } - public void InitializeHeap() - { - Memory.Manager.SetHeapAddr(MemoryRegions.HeapRegionAddress); - } - public bool Run(bool UseHbAbi = false) { if (Executables.Count == 0) @@ -98,11 +88,14 @@ namespace Ryujinx.Core.OsHle return false; } - long StackBot = TlsPageAddr - MaxStackSize; + MapRWMemRegion( + MemoryRegions.MainStackAddress, + MemoryRegions.MainStackSize, + MemoryType.Normal); + + long StackTop = MemoryRegions.MainStackAddress + MemoryRegions.MainStackSize; - Memory.Manager.MapPhys(StackBot, MaxStackSize, (int)MemoryType.Normal, AMemoryPerm.RW); - - int Handle = MakeThread(Executables[0].ImageBase, TlsPageAddr, 0, 0, 0); + int Handle = MakeThread(Executables[0].ImageBase, StackTop, 0, 0, 0); if (Handle == -1) { @@ -113,7 +106,7 @@ namespace Ryujinx.Core.OsHle if (UseHbAbi) { - long HbAbiDataPosition = (Executables[0].ImageEnd + 0xfff) & ~0xfff; + long HbAbiDataPosition = AMemoryHelper.PageRoundUp(Executables[0].ImageEnd); Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle); @@ -126,6 +119,11 @@ namespace Ryujinx.Core.OsHle return true; } + private void MapRWMemRegion(long Position, long Size, MemoryType Type) + { + Memory.Manager.Map(Position, Size, (int)Type, AMemoryPerm.RW); + } + public void StopAllThreads() { if (MainThread != null) @@ -188,12 +186,14 @@ namespace Ryujinx.Core.OsHle return -1; } + long Tpidr = MemoryRegions.TlsPagesAddress + TlsSlot * TlsSize; + Thread.ThreadState.Break += BreakHandler; Thread.ThreadState.SvcCall += SvcHandler.SvcCall; Thread.ThreadState.Undefined += UndefinedHandler; Thread.ThreadState.ProcessId = ProcessId; Thread.ThreadState.ThreadId = Ns.Os.IdGen.GenerateId(); - Thread.ThreadState.Tpidr = TlsPageAddr + TlsSlot * TlsSize; + Thread.ThreadState.Tpidr = Tpidr; Thread.ThreadState.X0 = (ulong)ArgsPtr; Thread.ThreadState.X1 = (ulong)Handle; Thread.ThreadState.X31 = (ulong)StackTop; @@ -267,7 +267,7 @@ namespace Ryujinx.Core.OsHle private int GetTlsSlot(long Position) { - return (int)((Position - TlsPageAddr) / TlsSize); + return (int)((Position - MemoryRegions.TlsPagesAddress) / TlsSize); } public HThread GetThread(long Tpidr) diff --git a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs index ec53f47ff..212d30a6c 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs @@ -17,6 +17,8 @@ namespace Ryujinx.Core.OsHle.Svc private AMemory Memory; private static Random Rng; + + private ulong CurrentHeapSize; public SvcHandler(Switch Ns, Process Process) { @@ -25,6 +27,7 @@ namespace Ryujinx.Core.OsHle.Svc { 0x01, SvcSetHeapSize }, { 0x03, SvcSetMemoryAttribute }, { 0x04, SvcMapMemory }, + { 0x05, SvcUnmapMemory }, { 0x06, SvcQueryMemory }, { 0x07, SvcExitProcess }, { 0x08, SvcCreateThread }, diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index 6ca27f16d..e7559a140 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -10,10 +10,21 @@ namespace Ryujinx.Core.OsHle.Svc { uint Size = (uint)ThreadState.X1; - Memory.Manager.SetHeapSize(Size, (int)MemoryType.Heap); + long Position = MemoryRegions.HeapRegionAddress; + + if (Size > CurrentHeapSize) + { + Memory.Manager.Map(Position, Size, (int)MemoryType.Heap, AMemoryPerm.RW); + } + else + { + Memory.Manager.Unmap(Position + Size, (long)CurrentHeapSize - Size); + } + + CurrentHeapSize = Size; ThreadState.X0 = (int)SvcResult.Success; - ThreadState.X1 = (ulong)Memory.Manager.HeapAddr; + ThreadState.X1 = (ulong)Position; } private void SvcSetMemoryAttribute(AThreadState ThreadState) @@ -42,7 +53,30 @@ namespace Ryujinx.Core.OsHle.Svc long Src = (long)ThreadState.X1; long Size = (long)ThreadState.X2; - Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory); + AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src); + + Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm); + + Memory.Manager.Reprotect(Src, Size, AMemoryPerm.None); + + Memory.Manager.SetAttrBit(Src, Size, 0); + + ThreadState.X0 = (int)SvcResult.Success; + } + + private void SvcUnmapMemory(AThreadState ThreadState) + { + long Dst = (long)ThreadState.X0; + long Src = (long)ThreadState.X1; + long Size = (long)ThreadState.X2; + + AMemoryMapInfo DstInfo = Memory.Manager.GetMapInfo(Dst); + + Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory); + + Memory.Manager.Reprotect(Src, Size, DstInfo.Perm); + + Memory.Manager.ClearAttrBit(Src, Size, 0); ThreadState.X0 = (int)SvcResult.Success; } @@ -54,17 +88,22 @@ namespace Ryujinx.Core.OsHle.Svc AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position); - MemoryInfo Info = new MemoryInfo(MapInfo); + if (MapInfo == null) + { + //TODO: Correct error code. + ThreadState.X0 = ulong.MaxValue; - Memory.WriteInt64(InfoPtr + 0x00, Info.BaseAddress); - Memory.WriteInt64(InfoPtr + 0x08, Info.Size); - Memory.WriteInt32(InfoPtr + 0x10, Info.MemType); - Memory.WriteInt32(InfoPtr + 0x14, Info.MemAttr); - Memory.WriteInt32(InfoPtr + 0x18, Info.MemPerm); - Memory.WriteInt32(InfoPtr + 0x1c, Info.IpcRefCount); - Memory.WriteInt32(InfoPtr + 0x20, Info.DeviceRefCount); - Memory.WriteInt32(InfoPtr + 0x24, Info.Padding); + return; + } + Memory.WriteInt64(InfoPtr + 0x00, MapInfo.Position); + Memory.WriteInt64(InfoPtr + 0x08, MapInfo.Size); + Memory.WriteInt32(InfoPtr + 0x10, MapInfo.Type); + Memory.WriteInt32(InfoPtr + 0x14, MapInfo.Attr); + Memory.WriteInt32(InfoPtr + 0x18, (int)MapInfo.Perm); + Memory.WriteInt32(InfoPtr + 0x1c, 0); + Memory.WriteInt32(InfoPtr + 0x20, 0); + Memory.WriteInt32(InfoPtr + 0x24, 0); //TODO: X1. ThreadState.X0 = (int)SvcResult.Success; @@ -84,7 +123,7 @@ namespace Ryujinx.Core.OsHle.Svc { SharedMem.AddVirtualPosition(Src); - Memory.Manager.MapPhys(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm); + Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm); ThreadState.X0 = (int)SvcResult.Success; } diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index 3b9142c78..51b2e26c6 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -11,7 +11,14 @@ namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler { - private void SvcExitProcess(AThreadState ThreadState) => Ns.Os.ExitProcess(ThreadState.ProcessId); + private const int AllowedCpuIdBitmask = 0b1111; + + private const bool EnableProcessDebugging = false; + + private void SvcExitProcess(AThreadState ThreadState) + { + Ns.Os.ExitProcess(ThreadState.ProcessId); + } private void SvcCloseHandle(AThreadState ThreadState) { @@ -162,79 +169,62 @@ namespace Ryujinx.Core.OsHle.Svc switch (InfoType) { - case 0: ThreadState.X1 = AllowedCpuIdBitmask(); break; - case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break; - case 3: ThreadState.X1 = GetMapRegionSize(); break; - case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break; - case 5: ThreadState.X1 = GetHeapRegionSize(); break; - case 6: ThreadState.X1 = GetTotalMem(); break; - case 7: ThreadState.X1 = GetUsedMem(); break; - case 8: ThreadState.X1 = IsCurrentProcessBeingDebugged(); break; - case 11: ThreadState.X1 = GetRnd64(); break; - case 12: ThreadState.X1 = GetAddrSpaceBaseAddr(); break; - case 13: ThreadState.X1 = GetAddrSpaceSize(); break; - case 14: ThreadState.X1 = GetMapRegionBaseAddr(); break; - case 15: ThreadState.X1 = GetMapRegionSize(); break; + case 0: + ThreadState.X1 = AllowedCpuIdBitmask; + break; + + case 2: + ThreadState.X1 = MemoryRegions.MapRegionAddress; + break; + + case 3: + ThreadState.X1 = MemoryRegions.MapRegionSize; + break; + + case 4: + ThreadState.X1 = MemoryRegions.HeapRegionAddress; + break; + + case 5: + ThreadState.X1 = CurrentHeapSize; + break; + + case 6: + ThreadState.X1 = MemoryRegions.TotalMemoryAvailable; + break; + + case 7: + ThreadState.X1 = MemoryRegions.TotalMemoryUsed + CurrentHeapSize; + break; + + case 8: + ThreadState.X1 = EnableProcessDebugging ? 1 : 0; + break; + + case 11: + ThreadState.X1 = (ulong)Rng.Next() + ((ulong)Rng.Next() << 32); + break; + + case 12: + ThreadState.X1 = MemoryRegions.AddrSpaceStart; + break; + + case 13: + ThreadState.X1 = MemoryRegions.AddrSpaceSize; + break; + + case 14: + ThreadState.X1 = MemoryRegions.MapRegionAddress; + break; + + case 15: + ThreadState.X1 = MemoryRegions.MapRegionSize; + break; default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}"); } ThreadState.X0 = (int)SvcResult.Success; } - - private ulong AllowedCpuIdBitmask() - { - return 0xF; //Mephisto value. - } - - private ulong GetMapRegionBaseAddr() - { - return MemoryRegions.MapRegionAddress; - } - - private ulong GetMapRegionSize() - { - return MemoryRegions.MapRegionSize; - } - - private ulong GetHeapRegionBaseAddr() - { - return MemoryRegions.HeapRegionAddress; - } - - private ulong GetHeapRegionSize() - { - return MemoryRegions.HeapRegionSize; - } - - private ulong GetTotalMem() - { - return (ulong)Memory.Manager.GetTotalMemorySize(); - } - - private ulong GetUsedMem() - { - return (ulong)Memory.Manager.GetUsedMemorySize(); - } - - private ulong IsCurrentProcessBeingDebugged() - { - return (ulong)0; - } - - private ulong GetRnd64() - { - return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32); - } - - private ulong GetAddrSpaceBaseAddr() - { - return 0x08000000; - } - - private ulong GetAddrSpaceSize() - { - return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr(); - } } } diff --git a/Ryujinx.Core/VirtualFs.cs b/Ryujinx.Core/VirtualFs.cs index 0c9111165..195fb6a3c 100644 --- a/Ryujinx.Core/VirtualFs.cs +++ b/Ryujinx.Core/VirtualFs.cs @@ -5,9 +5,9 @@ namespace Ryujinx.Core { class VirtualFs : IDisposable { - private const string BasePath = "Fs"; - private const string SavesPath = "Saves"; - private const string SdCardPath = "SdCard"; + private const string BasePath = "RyuFs"; + private const string NandPath = "nand"; + private const string SdCardPath = "sdmc"; public Stream RomFs { get; private set; } @@ -35,7 +35,7 @@ namespace Ryujinx.Core public string GetSdCardPath() => MakeDirAndGetFullPath(SdCardPath); - public string GetGameSavesPath() => MakeDirAndGetFullPath(SavesPath); + public string GetGameSavesPath() => MakeDirAndGetFullPath(NandPath); private string MakeDirAndGetFullPath(string Dir) { @@ -56,7 +56,9 @@ namespace Ryujinx.Core public string GetBasePath() { - return Path.Combine(Directory.GetCurrentDirectory(), BasePath); + string AppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + + return Path.Combine(AppDataPath, BasePath); } public void Dispose() diff --git a/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs b/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs index 54fabc671..7f50640d5 100644 --- a/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Gpu private const int PTLvl1Mask = PTLvl1Size - 1; private const int PageMask = PageSize - 1; - private const int PTLvl0Bit = PTPageBits + PTLvl0Bits; + private const int PTLvl0Bit = PTPageBits + PTLvl1Bits; private const int PTLvl1Bit = PTPageBits; private const long PteUnmapped = -1; diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index bf9d90e33..a56eeb728 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -17,7 +17,6 @@ namespace Ryujinx.Tests.Cpu private long EntryPoint; private IntPtr Ram; - private AMemoryAlloc Allocator; private AMemory Memory; private AThread Thread; @@ -31,9 +30,8 @@ namespace Ryujinx.Tests.Cpu Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); ATranslator Translator = new ATranslator(); - Allocator = new AMemoryAlloc(); - Memory = new AMemory(Ram, Allocator); - Memory.Manager.MapPhys(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute); + Memory = new AMemory(Ram); + Memory.Manager.Map(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute); Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint); } @@ -42,7 +40,6 @@ namespace Ryujinx.Tests.Cpu { Thread = null; Memory = null; - Allocator = null; Marshal.FreeHGlobal(Ram); } From 7f0bee2ff8d6eca1f10a29d5c9e5e7663cb34143 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Wed, 28 Feb 2018 04:31:52 +0100 Subject: [PATCH 32/67] Stubs implementations (#45) Services Bsd, Nifm & SSL stubs implementations Objects IGeneralService, IRequest stubs implementations. Fake-Fix GetAvailableLanguageCodes stub too ^^! --- Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs | 60 +++++++++++++++++++ .../OsHle/Services/Nifm/IGeneralService.cs | 34 +++++++++++ Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs | 49 +++++++++++++++ .../OsHle/Services/Nifm/ServiceNifm.cs | 29 +++++++++ Ryujinx.Core/OsHle/Services/ServiceFactory.cs | 6 ++ Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs | 11 ++-- Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs | 20 +++++++ 7 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs create mode 100644 Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs create mode 100644 Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs create mode 100644 Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs create mode 100644 Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs diff --git a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs new file mode 100644 index 000000000..fa47d9445 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs @@ -0,0 +1,60 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Bsd +{ + class ServiceBsd : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceBsd() + { + m_Commands = new Dictionary() + { + { 0, Initialize }, + { 1, StartMonitoring } + }; + } + + //Initialize(u32, u32, u32, u32, u32, u32, u32, u32, u64 pid, u64 transferMemorySize, pid, KObject) -> u32 bsd_errno + public long Initialize(ServiceCtx Context) + { + /* + typedef struct { + u32 version; // Observed 1 on 2.0 LibAppletWeb, 2 on 3.0. + + u32 tcp_tx_buf_size; // Size of the TCP transfer (send) buffer (initial or fixed). + u32 tcp_rx_buf_size; // Size of the TCP recieve buffer (initial or fixed). + u32 tcp_tx_buf_max_size; // Maximum size of the TCP transfer (send) buffer. If it is 0, the size of the buffer is fixed to its initial value. + u32 tcp_rx_buf_max_size; // Maximum size of the TCP receive buffer. If it is 0, the size of the buffer is fixed to its initial value. + + u32 udp_tx_buf_size; // Size of the UDP transfer (send) buffer (typically 0x2400 bytes). + u32 udp_rx_buf_size; // Size of the UDP receive buffer (typically 0xA500 bytes). + + u32 sb_efficiency; // Number of buffers for each socket (standard values range from 1 to 8). + } BsdBufferConfig; + */ + + long Pid = Context.RequestData.ReadInt64(); + long TransferMemorySize = Context.RequestData.ReadInt64(); + + // Two other args are unknown! + + Context.ResponseData.Write(0); + + //Todo: Stub + + return 0; + } + + //StartMonitoring(u64, pid) + public long StartMonitoring(ServiceCtx Context) + { + //Todo: Stub + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs b/Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs new file mode 100644 index 000000000..c31ee36b2 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Nifm/IGeneralService.cs @@ -0,0 +1,34 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Nifm +{ + class IGeneralService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IGeneralService() + { + m_Commands = new Dictionary() + { + { 4, CreateRequest } + }; + } + + //CreateRequest(i32) + public long CreateRequest(ServiceCtx Context) + { + int Unknown = Context.RequestData.ReadInt32(); + + MakeObject(Context, new IRequest()); + + //Todo: Stub + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs b/Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs new file mode 100644 index 000000000..6110e5fbe --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Nifm/IRequest.cs @@ -0,0 +1,49 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Nifm +{ + class IRequest : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public IRequest() + { + m_Commands = new Dictionary() + { + { 0, GetRequestState }, + { 1, GetResult }, + { 2, GetSystemEventReadableHandles } + }; + } + + // -> i32 + public long GetRequestState(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + //Todo: Stub + + return 0; + } + + public long GetResult(ServiceCtx Context) + { + //Todo: Stub + + return 0; + } + + //GetSystemEventReadableHandles() -> (KObject, KObject) + public long GetSystemEventReadableHandles(ServiceCtx Context) + { + Context.Response.HandleDesc = IpcHandleDesc.MakeMove(0xbadcafe); + + //Todo: Stub + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs b/Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs new file mode 100644 index 000000000..7e183389b --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Nifm/ServiceNifm.cs @@ -0,0 +1,29 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + +namespace Ryujinx.Core.OsHle.IpcServices.Nifm +{ + class ServiceNifm : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceNifm() + { + m_Commands = new Dictionary() + { + { 4, CreateGeneralServiceOld } + }; + } + + public long CreateGeneralServiceOld(ServiceCtx Context) + { + MakeObject(Context, new IGeneralService()); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs index 54fa38ab7..aae624534 100644 --- a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs @@ -2,16 +2,19 @@ using Ryujinx.Core.OsHle.IpcServices.Acc; using Ryujinx.Core.OsHle.IpcServices.Am; using Ryujinx.Core.OsHle.IpcServices.Apm; using Ryujinx.Core.OsHle.IpcServices.Aud; +using Ryujinx.Core.OsHle.IpcServices.Bsd; using Ryujinx.Core.OsHle.IpcServices.Friend; using Ryujinx.Core.OsHle.IpcServices.FspSrv; using Ryujinx.Core.OsHle.IpcServices.Hid; using Ryujinx.Core.OsHle.IpcServices.Lm; +using Ryujinx.Core.OsHle.IpcServices.Nifm; using Ryujinx.Core.OsHle.IpcServices.Ns; using Ryujinx.Core.OsHle.IpcServices.NvServices; using Ryujinx.Core.OsHle.IpcServices.Pctl; using Ryujinx.Core.OsHle.IpcServices.Pl; using Ryujinx.Core.OsHle.IpcServices.Set; using Ryujinx.Core.OsHle.IpcServices.Sm; +using Ryujinx.Core.OsHle.IpcServices.Ssl; using Ryujinx.Core.OsHle.IpcServices.Time; using Ryujinx.Core.OsHle.IpcServices.Vi; using System; @@ -31,16 +34,19 @@ namespace Ryujinx.Core.OsHle.IpcServices case "appletOE": return new ServiceAppletOE(); case "audout:u": return new ServiceAudOut(); case "audren:u": return new ServiceAudRen(); + case "bsd:u": return new ServiceBsd(); case "friend:a": return new ServiceFriend(); case "fsp-srv": return new ServiceFspSrv(); case "hid": return new ServiceHid(); case "lm": return new ServiceLm(); + case "nifm:u": return new ServiceNifm(); case "nvdrv": return new ServiceNvDrv(); case "nvdrv:a": return new ServiceNvDrv(); case "pctl:a": return new ServicePctl(); case "pl:u": return new ServicePl(); case "set": return new ServiceSet(); case "sm:": return new ServiceSm(); + case "ssl": return new ServiceSsl(); case "time:s": return new ServiceTime(); case "time:u": return new ServiceTime(); case "vi:m": return new ServiceVi(); diff --git a/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs b/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs index 05e409b0d..c60e1712a 100644 --- a/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs +++ b/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs @@ -1,5 +1,6 @@ using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Ipc; +using System; using System.Collections.Generic; namespace Ryujinx.Core.OsHle.IpcServices.Set @@ -30,12 +31,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.Set short Size = Context.Request.RecvListBuff[0].Size; //This should return an array of ints with values matching the LanguageCode enum. - byte[] Data = new byte[Size]; - - Data[0] = 0; - Data[1] = 1; - - AMemoryHelper.WriteBytes(Context.Memory, Position, Data); + foreach (long value in new long[] { 0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L }) + { + AMemoryHelper.WriteBytes(Context.Memory, Position += 8, BitConverter.GetBytes(value)); + } } Context.ResponseData.Write(LangCodesCount); diff --git a/Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs b/Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs new file mode 100644 index 000000000..23934b140 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Ssl/ServiceSsl.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Ssl +{ + class ServiceSsl : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceSsl() + { + m_Commands = new Dictionary() + { + //{ 0, Function } + }; + } + } +} \ No newline at end of file From 424e0459403fd7ffeb8980b16a6a9e3a1201c5e6 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Wed, 28 Feb 2018 21:58:04 +0100 Subject: [PATCH 33/67] More stubs (#47) * Stubs implementations Services Bsd, Nifm & SSL stubs implementations Objects IGeneralService, IRequest stubs implementations. Fake-Fix GetAvailableLanguageCodes stub too ^^! * More stubs - Fix SvcGetInfo loops by gdkchan. - Implement stub for Sfdnsres service. - Add more stubs for Bsd service. * Update ServiceSfdnsres.cs --- Ryujinx.Core/OsHle/MemoryRegions.cs | 2 +- Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs | 40 ++++++++++++++++++- Ryujinx.Core/OsHle/Services/ServiceFactory.cs | 2 + .../Services/Sfdnsres/ServiceSfdnsres.cs | 20 ++++++++++ 4 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs diff --git a/Ryujinx.Core/OsHle/MemoryRegions.cs b/Ryujinx.Core/OsHle/MemoryRegions.cs index 3b6904260..e362ba9fd 100644 --- a/Ryujinx.Core/OsHle/MemoryRegions.cs +++ b/Ryujinx.Core/OsHle/MemoryRegions.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle public const long AddrSpaceStart = 0x08000000; public const long MapRegionAddress = 0x10000000; - public const long MapRegionSize = 0x40000000; + public const long MapRegionSize = 0x10000000; public const long MainStackSize = 0x100000; diff --git a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs index fa47d9445..b59444127 100644 --- a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs +++ b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs @@ -13,8 +13,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd { m_Commands = new Dictionary() { - { 0, Initialize }, - { 1, StartMonitoring } + { 0, Initialize }, + { 1, StartMonitoring }, + { 2, Socket }, + { 10, Send }, + { 14, Connect } }; } @@ -56,5 +59,38 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd return 0; } + + //Socket(u32 domain, u32 type, u32 protocol) -> (i32 ret, u32 bsd_errno) + public long Socket(ServiceCtx Context) + { + Context.ResponseData.Write(0); + Context.ResponseData.Write(0); + + //Todo: Stub + + return 0; + } + + //Connect(u32 socket, buffer) -> (i32 ret, u32 bsd_errno) + public long Connect(ServiceCtx Context) + { + Context.ResponseData.Write(0); + Context.ResponseData.Write(0); + + //Todo: Stub + + return 0; + } + + //Send(u32 socket, u32 flags, buffer) -> (i32 ret, u32 bsd_errno) + public long Send(ServiceCtx Context) + { + Context.ResponseData.Write(0); + Context.ResponseData.Write(0); + + //Todo: Stub + + return 0; + } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs index aae624534..c5da717e7 100644 --- a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs @@ -13,6 +13,7 @@ using Ryujinx.Core.OsHle.IpcServices.NvServices; using Ryujinx.Core.OsHle.IpcServices.Pctl; using Ryujinx.Core.OsHle.IpcServices.Pl; using Ryujinx.Core.OsHle.IpcServices.Set; +using Ryujinx.Core.OsHle.IpcServices.Sfdnsres; using Ryujinx.Core.OsHle.IpcServices.Sm; using Ryujinx.Core.OsHle.IpcServices.Ssl; using Ryujinx.Core.OsHle.IpcServices.Time; @@ -45,6 +46,7 @@ namespace Ryujinx.Core.OsHle.IpcServices case "pctl:a": return new ServicePctl(); case "pl:u": return new ServicePl(); case "set": return new ServiceSet(); + case "sfdnsres": return new ServiceSfdnsres(); case "sm:": return new ServiceSm(); case "ssl": return new ServiceSsl(); case "time:s": return new ServiceTime(); diff --git a/Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs b/Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs new file mode 100644 index 000000000..f110ae736 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Sfdnsres/ServiceSfdnsres.cs @@ -0,0 +1,20 @@ +using Ryujinx.Core.OsHle.Ipc; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Sfdnsres +{ + class ServiceSfdnsres : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceSfdnsres() + { + m_Commands = new Dictionary() + { + //{ 0, Function } + }; + } + } +} From eacd432387677dc0513255f8c3661f5c3ef05d65 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 28 Feb 2018 19:21:04 -0300 Subject: [PATCH 34/67] Fix wrong rotation direction on nvflinger --- Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 85a06cea4..3e45c4419 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -274,7 +274,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90)) { - Rotate = MathF.PI * 0.5f; + Rotate = -MathF.PI * 0.5f; } byte* Fb = (byte*)Context.Ns.Ram + NvMap.Address; From 5d8a615c21eff7888ff4e36c122123560bcb0886 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 28 Feb 2018 23:37:40 -0300 Subject: [PATCH 35/67] Enable hardware frame buffer texture scaling --- Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 47 +++++++++++++++++-- Ryujinx.Graphics/Gal/IGalRenderer.cs | 13 ++++- Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl | 6 ++- Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs | 6 ++- Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 15 ++++-- 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 3e45c4419..b745867e9 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -35,12 +35,22 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android Acquired } + private struct Rect + { + public int Top; + public int Left; + public int Right; + public int Bottom; + } + private struct BufferEntry { public BufferState State; public HalTransform Transform; + public Rect Crop; + public GbpBuffer Data; } @@ -168,6 +178,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android BufferQueue[Slot].Transform = (HalTransform)Transform; + BufferQueue[Slot].Crop.Top = CropTop; + BufferQueue[Slot].Crop.Left = CropLeft; + BufferQueue[Slot].Crop.Right = CropRight; + BufferQueue[Slot].Crop.Bottom = CropBottom; + BufferQueue[Slot].State = BufferState.Queued; SendFrameBuffer(Context, Slot); @@ -256,20 +271,44 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android return; } - BufferQueue[Slot].State = BufferState.Acquired; + BufferQueue[Slot].State = BufferState.Acquired; + + Rect Crop = BufferQueue[Slot].Crop; + + int RealWidth = FbWidth; + int RealHeight = FbHeight; float ScaleX = 1; float ScaleY = 1; + float OffsX = 0; + float OffsY = 0; + + if (Crop.Right != 0 && + Crop.Bottom != 0) + { + RealWidth = Crop.Right - Crop.Left; + RealHeight = Crop.Bottom - Crop.Top; + + ScaleX = (float)FbWidth / RealWidth; + ScaleY = (float)FbHeight / RealHeight; + + OffsX = -(float)Crop.Left / Crop.Right; + OffsY = -(float)Crop.Top / Crop.Bottom; + + OffsX += ScaleX - 1; + OffsY += ScaleY - 1; + } + float Rotate = 0; if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX)) { - ScaleX = -1; + ScaleX = -ScaleX; } if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY)) { - ScaleY = -1; + ScaleY = -ScaleY; } if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90)) @@ -287,6 +326,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android FbHeight, ScaleX, ScaleY, + OffsX, + OffsY, Rotate); BufferQueue[Slot].State = BufferState.Free; diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index 5854c54a6..83d2c699f 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -10,9 +10,20 @@ namespace Ryujinx.Graphics.Gal void InitializeFrameBuffer(); void Render(); void SetWindowSize(int Width, int Height); - void SetFrameBuffer(byte* Fb, int Width, int Height, float SX, float SY, float R); + void SetFrameBuffer( + byte* Fb, + int Width, + int Height, + float ScaleX, + float ScaleY, + float OffsX, + float OffsY, + float Rotate); + void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs); + void SendR8G8B8A8Texture(int Index, byte[] Buffer, int Width, int Height); + void BindTexture(int Index); } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl b/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl index 933fa6aa9..35d560c09 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl +++ b/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl @@ -2,8 +2,9 @@ precision highp float; -uniform vec2 window_size; uniform mat2 transform; +uniform vec2 window_size; +uniform vec2 offset; layout(location = 0) in vec2 in_position; layout(location = 1) in vec2 in_tex_coord; @@ -22,5 +23,6 @@ vec2 get_scale_ratio(void) { void main(void) { tex_coord = in_tex_coord; - gl_Position = vec4((transform * in_position) * get_scale_ratio(), 0, 1); + vec2 t_pos = (transform * in_position) + offset; + gl_Position = vec4(t_pos * get_scale_ratio(), 0, 1); } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs index c66c0cb75..7dc4bffe3 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs @@ -135,7 +135,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.BindVertexArray(0); } - public unsafe void Set(byte* Fb, int Width, int Height, Matrix2 Transform) + public unsafe void Set(byte* Fb, int Width, int Height, Matrix2 Transform, Vector2 Offs) { if (Fb == null) { @@ -172,6 +172,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL int WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size"); GL.Uniform2(WindowSizeUniformLocation, new Vector2(WindowWidth, WindowHeight)); + + int OffsetUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "offset"); + + GL.Uniform2(OffsetUniformLocation, Offs); } public void Render() diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index 5ae5e2259..bdedfc1a8 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -1,6 +1,7 @@ using OpenTK; using OpenTK.Graphics.OpenGL; using System; +using System.Collections.Concurrent; using System.Collections.Generic; namespace Ryujinx.Graphics.Gal.OpenGL @@ -24,7 +25,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL private Texture[] Textures; - private Queue ActionsQueue; + private ConcurrentQueue ActionsQueue; private FrameBuffer FbRenderer; @@ -34,7 +35,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL Textures = new Texture[8]; - ActionsQueue = new Queue(); + ActionsQueue = new ConcurrentQueue(); } public void InitializeFrameBuffer() @@ -51,9 +52,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL { int Count = ActionsQueue.Count; - while (Count-- > 0) + while (Count-- > 0 && ActionsQueue.TryDequeue(out Action RenderAction)) { - ActionsQueue.Dequeue()(); + RenderAction(); } } @@ -86,6 +87,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL int Height, float ScaleX, float ScaleY, + float OffsX, + float OffsY, float Rotate) { Matrix2 Transform; @@ -93,7 +96,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL Transform = Matrix2.CreateScale(ScaleX, ScaleY); Transform *= Matrix2.CreateRotation(Rotate); - FbRenderer.Set(Fb, Width, Height, Transform); + Vector2 Offs = new Vector2(OffsX, OffsY); + + FbRenderer.Set(Fb, Width, Height, Transform, Offs); } public void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs) From 65e04e9854fd5d7292ba235b05f80cecd89abec2 Mon Sep 17 00:00:00 2001 From: emmauss Date: Thu, 1 Mar 2018 22:23:55 +0200 Subject: [PATCH 36/67] stub set_sys (#49) --- Ryujinx.Core/OsHle/Services/ServiceFactory.cs | 1 + .../OsHle/Services/Set/ServiceSetSys.cs | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs diff --git a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs index c5da717e7..31c8aa2c8 100644 --- a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs @@ -46,6 +46,7 @@ namespace Ryujinx.Core.OsHle.IpcServices case "pctl:a": return new ServicePctl(); case "pl:u": return new ServicePl(); case "set": return new ServiceSet(); + case "set:sys": return new ServiceSetSys(); case "sfdnsres": return new ServiceSfdnsres(); case "sm:": return new ServiceSm(); case "ssl": return new ServiceSsl(); diff --git a/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs b/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs new file mode 100644 index 000000000..68b303542 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs @@ -0,0 +1,35 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Set +{ + class ServiceSetSys : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ServiceSetSys() + { + m_Commands = new Dictionary() + { + { 23, GetColorSetId }, + { 24, SetColorSetId } + }; + } + + public static long GetColorSetId(ServiceCtx Context) + { + //Use white system theme + Context.ResponseData.Write(1); + return 0; + } + + public static long SetColorSetId(ServiceCtx Context) + { + return 0; + } + } +} \ No newline at end of file From 1d71e33171f78fb40b097108fbd5915f18c608c4 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Fri, 2 Mar 2018 05:06:05 +0100 Subject: [PATCH 37/67] Update IAudioOut.cs (#51) Little improvements, sound looks a little better... --- Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs | 66 +++++++++++--------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs index a45b23ccd..0562d4b9a 100644 --- a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs +++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs @@ -1,4 +1,4 @@ -using ChocolArm64.Memory; +using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; using OpenTK.Audio; @@ -39,7 +39,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud //IAudioOut private AudioOutState State = AudioOutState.Stopped; - private Queue KeysQueue = new Queue(); + private Queue BufferIdQueue = new Queue(); //OpenAL private bool OpenALInstalled = true; @@ -71,7 +71,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud OpenALInstalled = false; } - if (OpenALInstalled) AL.Listener(ALListenerf.Gain, (float)8.0); //Add more gain to it + if (OpenALInstalled) AL.Listener(ALListenerf.Gain, 8.0f); //Add more gain to it } return 0; @@ -88,6 +88,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud AL.SourceStop(Source); AL.DeleteSource(Source); + AL.DeleteBuffers(1, ref Buffer); } State = AudioOutState.Stopped; } @@ -99,9 +100,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud { long BufferId = Context.RequestData.ReadInt64(); - KeysQueue.Enqueue(BufferId); - byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, sizeof(long) * 5); + using (MemoryStream MS = new MemoryStream(AudioOutBuffer)) { BinaryReader Reader = new BinaryReader(MS); @@ -111,18 +111,34 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud long SizeDataInSampleBuffer = Reader.ReadInt64(); long OffsetDataInSampleBuffer = Reader.ReadInt64(); - byte[] AudioSampleBuffer = AMemoryHelper.ReadBytes(Context.Memory, PointerSampleBuffer + OffsetDataInSampleBuffer, (int)SizeDataInSampleBuffer); - - if (OpenALInstalled) + if (SizeDataInSampleBuffer > 0) { - if (AudioCtx == null) //Needed to call the instance of AudioContext() - return 0; + BufferIdQueue.Enqueue(BufferId); - Buffer = AL.GenBuffer(); - AL.BufferData(Buffer, ALFormat.Stereo16, AudioSampleBuffer, AudioSampleBuffer.Length, 48000); + byte[] AudioSampleBuffer = AMemoryHelper.ReadBytes(Context.Memory, PointerSampleBuffer + OffsetDataInSampleBuffer, (int)SizeDataInSampleBuffer); - Source = AL.GenSource(); - AL.SourceQueueBuffer(Source, Buffer); + if (OpenALInstalled) + { + if (AudioCtx == null) //Needed to call the instance of AudioContext() + return 0; + + Source = AL.GenSource(); + Buffer = AL.GenBuffer(); + + AL.BufferData(Buffer, ALFormat.Stereo16, AudioSampleBuffer, AudioSampleBuffer.Length, 48000); + AL.SourceQueueBuffer(Source, Buffer); + AL.SourcePlay(Source); + + int State; + + do AL.GetSource(Source, ALGetSourcei.SourceState, out State); + while ((ALSourceState)State == ALSourceState.Playing); + + AL.SourceStop(Source); + AL.SourceUnqueueBuffer(Buffer); + AL.DeleteSource(Source); + AL.DeleteBuffers(1, ref Buffer); + } } } @@ -140,25 +156,19 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud public long GetReleasedAudioOutBuffer(ServiceCtx Context) { - long TempKey = 0; + int ReleasedBuffersCount = 0; - if (KeysQueue.Count > 0) TempKey = KeysQueue.Dequeue(); - - AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, BitConverter.GetBytes(TempKey)); - - int ReleasedBuffersCount = 1; - Context.ResponseData.Write(ReleasedBuffersCount); - - if (OpenALInstalled) + for(int i = 0; i < BufferIdQueue.Count; i++) { - if (AudioCtx == null) //Needed to call the instance of AudioContext() - return 0; + long BufferId = BufferIdQueue.Dequeue(); - AL.SourcePlay(Source); - int[] FreeBuffers = AL.SourceUnqueueBuffers(Source, 1); - AL.DeleteBuffers(FreeBuffers); + AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position + (8 * i), BitConverter.GetBytes(BufferId)); + + ReleasedBuffersCount++; } + Context.ResponseData.Write(ReleasedBuffersCount); + return 0; } From f39a864050589ac7e757a9d72b46ac693125b382 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 2 Mar 2018 19:21:54 -0300 Subject: [PATCH 38/67] Add EXT, CMTST (vector) and UMULL (vector) instructions --- ChocolArm64/AOpCodeTable.cs | 3 ++ ChocolArm64/Decoder/AOpCodeSimdExt.cs | 14 +++++++ .../Instruction/AInstEmitSimdArithmetic.cs | 5 +++ ChocolArm64/Instruction/AInstEmitSimdCmp.cs | 39 +++++++++++++++++++ ChocolArm64/Instruction/AInstEmitSimdMove.cs | 25 ++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 ChocolArm64/Decoder/AOpCodeSimdExt.cs diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 14ca231ba..470b70e04 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -142,11 +142,13 @@ namespace ChocolArm64 Set("0>101110<<1xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_V, typeof(AOpCodeSimdReg)); Set("0>101110<<100000100110xxxxxxxxxx", AInstEmit.Cmle_V, typeof(AOpCodeSimd)); Set("0>001110<<100000101010xxxxxxxxxx", AInstEmit.Cmlt_V, typeof(AOpCodeSimd)); + Set("0>001110<<1xxxxx100011xxxxxxxxxx", AInstEmit.Cmtst_V, typeof(AOpCodeSimdReg)); Set("0x00111000100000010110xxxxxxxxxx", AInstEmit.Cnt_V, typeof(AOpCodeSimd)); Set("0x001110000xxxxx000011xxxxxxxxxx", AInstEmit.Dup_Gp, typeof(AOpCodeSimdIns)); Set("01011110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_S, typeof(AOpCodeSimdIns)); Set("0x001110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_V, typeof(AOpCodeSimdIns)); Set("0x101110001xxxxx000111xxxxxxxxxx", AInstEmit.Eor_V, typeof(AOpCodeSimdReg)); + Set("0>101110000xxxxx0101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg)); Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm)); Set("011111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_S, typeof(AOpCodeSimdShImm)); diff --git a/ChocolArm64/Decoder/AOpCodeSimdExt.cs b/ChocolArm64/Decoder/AOpCodeSimdExt.cs new file mode 100644 index 000000000..cf22d6546 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdExt.cs @@ -0,0 +1,14 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdExt : AOpCodeSimdReg + { + public int Imm4 { get; private set; } + + public AOpCodeSimdExt(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int Imm4 = (OpCode >> 11) & 0xf; + } + } +} \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index e790d6786..9c1bc2862 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -406,5 +406,10 @@ namespace ChocolArm64.Instruction { EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add)); } + + public static void Umull_V(AILEmitterCtx Context) + { + EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul)); + } } } \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs index 97ccf0ab4..76861b73b 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs @@ -46,6 +46,45 @@ namespace ChocolArm64.Instruction EmitVectorCmp(Context, OpCodes.Blt_S); } + public static void Cmtst_V(AILEmitterCtx Context) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size)); + + for (int Index = 0; Index < (Bytes >> Op.Size); Index++) + { + EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size); + EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size); + + AILLabel LblTrue = new AILLabel(); + AILLabel LblEnd = new AILLabel(); + + Context.Emit(OpCodes.And); + + Context.EmitLdc_I4(0); + + Context.Emit(OpCodes.Bne_Un_S, LblTrue); + + EmitVectorInsert(Context, Op.Rd, Index, Op.Size, 0); + + Context.Emit(OpCodes.Br_S, LblEnd); + + Context.MarkLabel(LblTrue); + + EmitVectorInsert(Context, Op.Rd, Index, Op.Size, (long)SzMask); + + Context.MarkLabel(LblEnd); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + public static void Fccmp_S(AILEmitterCtx Context) { AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp; diff --git a/ChocolArm64/Instruction/AInstEmitSimdMove.cs b/ChocolArm64/Instruction/AInstEmitSimdMove.cs index aabb8f347..a4e533709 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdMove.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdMove.cs @@ -57,6 +57,31 @@ namespace ChocolArm64.Instruction } } + public static void Ext_V(AILEmitterCtx Context) + { + AOpCodeSimdExt Op = (AOpCodeSimdExt)Context.CurrOp; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + for (int Index = 0; Index < Bytes; Index++) + { + int Position = Op.Imm4 + Index; + + int Reg = Position < Bytes ? Op.Rn : Op.Rm; + + Position &= Bytes - 1; + + EmitVectorExtractZx(Context, Reg, Position, 0); + + EmitVectorInsert(Context, Op.Rd, Index, 0); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + public static void Fcsel_S(AILEmitterCtx Context) { AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp; From 829b1b1cc0a7dced1946500c1f27b4a7277ddb26 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 2 Mar 2018 20:03:28 -0300 Subject: [PATCH 39/67] Add REV64 (vector) instruction --- ChocolArm64/AOpCodeTable.cs | 1 + ChocolArm64/Instruction/AInstEmitSimdLogical.cs | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 470b70e04..13df4d986 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -230,6 +230,7 @@ namespace ChocolArm64 Set("0x10111000100000010110xxxxxxxxxx", AInstEmit.Not_V, typeof(AOpCodeSimd)); Set("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg)); Set("0x00111100000xxx< Context.Emit(OpCodes.Or)); } + + public static void Rev64_V(AILEmitterCtx Context) + { + Action Emit = () => + { + ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBits64)); + }; + + EmitVectorUnaryOpZx(Context, Emit); + } } } \ No newline at end of file From efef605b260119642fa023c8488fb3ff4501cafd Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 2 Mar 2018 20:24:16 -0300 Subject: [PATCH 40/67] Fix REV64 (vector) instruction --- ChocolArm64/AOpCodeTable.cs | 2 +- .../Instruction/AInstEmitSimdLogical.cs | 26 ++++++++++++++----- ChocolArm64/Instruction/ASoftFallback.cs | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 13df4d986..e192f5ec5 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -230,7 +230,7 @@ namespace ChocolArm64 Set("0x10111000100000010110xxxxxxxxxx", AInstEmit.Not_V, typeof(AOpCodeSimd)); Set("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg)); Set("0x00111100000xxx< + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + int Elems = Bytes >> Op.Size; + + int RevIndex = Elems - 1; + + for (int Index = 0; Index < (Bytes >> Op.Size); Index++) { - ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBits64)); - }; - - EmitVectorUnaryOpZx(Context, Emit); + EmitVectorExtractZx(Context, Op.Rn, RevIndex--, Op.Size); + + EmitVectorInsert(Context, Op.Rd, Index, Op.Size); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } } } } \ No newline at end of file diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs index 5127182dd..797d81573 100644 --- a/ChocolArm64/Instruction/ASoftFallback.cs +++ b/ChocolArm64/Instruction/ASoftFallback.cs @@ -75,7 +75,7 @@ namespace ChocolArm64.Instruction private static ulong ReverseBytes(ulong Value, RevSize Size) { - Value = ((Value & 0xff00ff00ff00ff00) >> 8) | ((Value & 0x00ff00ff00ff00ff) << 8); + Value = ((Value & 0xff00ff00ff00ff00) >> 8) | ((Value & 0x00ff00ff00ff00ff) << 8); if (Size == RevSize.Rev16) { From c14c69a10c936f485a4420c93499bd4c3efa8b09 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 2 Mar 2018 22:49:17 -0300 Subject: [PATCH 41/67] Refactor HID, fix issues (#48) * Refactor HID, fix issues * Fix on touch screen code with wrong offset * Don't use magic values * Replace more magic values with actual variables, fix touch screen coordinates on different window sizes --- Ryujinx.Core/Config.cs | 3 +- Ryujinx.Core/Hid.cs | 225 -------------------- Ryujinx.Core/Hid/Hid.cs | 235 +++++++++++++++++++++ Ryujinx.Core/Hid/HidController.cs | 188 ----------------- Ryujinx.Core/Hid/HidControllerButtons.cs | 35 +++ Ryujinx.Core/Hid/HidControllerColorDesc.cs | 10 + Ryujinx.Core/Hid/HidControllerConnState.cs | 11 + Ryujinx.Core/Hid/HidControllerId.cs | 16 ++ Ryujinx.Core/Hid/HidControllerLayouts.cs | 13 ++ Ryujinx.Core/Hid/HidControllerType.cs | 14 ++ Ryujinx.Core/Hid/HidJoystickPosition.cs | 8 + Ryujinx.Core/Hid/HidKeyboard.cs | 33 --- Ryujinx.Core/Hid/HidMouse.cs | 37 ---- Ryujinx.Core/Hid/HidTouchPoint.cs | 11 + Ryujinx.Core/Hid/HidTouchScreen.cs | 55 ----- Ryujinx.Core/Hid/HidUnknown.cs | 81 ------- Ryujinx.Core/Hid/JoyCon.cs | 25 +-- Ryujinx.Core/Hid/JoyConColor.cs | 23 ++ Ryujinx.Core/OsHle/Process.cs | 10 + Ryujinx.Core/OsHle/Svc/SvcMemory.cs | 2 + Ryujinx.Core/Switch.cs | 17 +- Ryujinx/Ui/GLScreen.cs | 148 ++++++++----- 22 files changed, 491 insertions(+), 709 deletions(-) delete mode 100644 Ryujinx.Core/Hid.cs create mode 100644 Ryujinx.Core/Hid/Hid.cs delete mode 100644 Ryujinx.Core/Hid/HidController.cs create mode 100644 Ryujinx.Core/Hid/HidControllerButtons.cs create mode 100644 Ryujinx.Core/Hid/HidControllerColorDesc.cs create mode 100644 Ryujinx.Core/Hid/HidControllerConnState.cs create mode 100644 Ryujinx.Core/Hid/HidControllerId.cs create mode 100644 Ryujinx.Core/Hid/HidControllerLayouts.cs create mode 100644 Ryujinx.Core/Hid/HidControllerType.cs create mode 100644 Ryujinx.Core/Hid/HidJoystickPosition.cs delete mode 100644 Ryujinx.Core/Hid/HidKeyboard.cs delete mode 100644 Ryujinx.Core/Hid/HidMouse.cs create mode 100644 Ryujinx.Core/Hid/HidTouchPoint.cs delete mode 100644 Ryujinx.Core/Hid/HidTouchScreen.cs delete mode 100644 Ryujinx.Core/Hid/HidUnknown.cs create mode 100644 Ryujinx.Core/Hid/JoyConColor.cs diff --git a/Ryujinx.Core/Config.cs b/Ryujinx.Core/Config.cs index 7db49319c..c9a76de34 100644 --- a/Ryujinx.Core/Config.cs +++ b/Ryujinx.Core/Config.cs @@ -1,4 +1,5 @@ -using System; +using Ryujinx.Core.Input; +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/Ryujinx.Core/Hid.cs b/Ryujinx.Core/Hid.cs deleted file mode 100644 index bd83e92d4..000000000 --- a/Ryujinx.Core/Hid.cs +++ /dev/null @@ -1,225 +0,0 @@ -using Ryujinx.Core.OsHle; -using System; -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - public class Hid - { - /* - Thanks to: - https://github.com/reswitched/libtransistor/blob/development/lib/hid.c - https://github.com/reswitched/libtransistor/blob/development/include/libtransistor/hid.h - https://github.com/switchbrew/libnx/blob/master/nx/source/services/hid.c - https://github.com/switchbrew/libnx/blob/master/nx/include/switch/services/hid.h - - struct HidSharedMemory - { - header[0x400]; - touchscreen[0x3000]; - mouse[0x400]; - keyboard[0x400]; - unkSection1[0x400]; - unkSection2[0x400]; - unkSection3[0x400]; - unkSection4[0x400]; - unkSection5[0x200]; - unkSection6[0x200]; - unkSection7[0x200]; - unkSection8[0x800]; - controllerSerials[0x4000]; - controllers[0x5000 * 10]; - unkSection9[0x4600]; - } - */ - - private const int Hid_Num_Entries = 17; - private Switch Ns; - private long SharedMemOffset; - - public Hid(Switch Ns) - { - this.Ns = Ns; - } - - public void Init(long HidOffset) - { - unsafe - { - if (HidOffset == 0 || HidOffset + Horizon.HidSize > uint.MaxValue) - { - return; - } - - SharedMemOffset = HidOffset; - - uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader)); - - IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidTouchScreen TouchScreen = new HidTouchScreen(); - TouchScreen.Header.TimestampTicks = (ulong)Environment.TickCount; - TouchScreen.Header.NumEntries = (ulong)Hid_Num_Entries; - TouchScreen.Header.LatestEntry = 0; - TouchScreen.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1; - TouchScreen.Header.Timestamp = (ulong)Environment.TickCount; - - Marshal.StructureToPtr(TouchScreen, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidTouchScreen)); - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidMouse Mouse = new HidMouse(); - Mouse.Header.TimestampTicks = (ulong)Environment.TickCount; - Mouse.Header.NumEntries = (ulong)Hid_Num_Entries; - Mouse.Header.LatestEntry = 0; - Mouse.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1; - - //TODO: Write this structure when the input is implemented - //Marshal.StructureToPtr(Mouse, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidMouse)); - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidKeyboard Keyboard = new HidKeyboard(); - Keyboard.Header.TimestampTicks = (ulong)Environment.TickCount; - Keyboard.Header.NumEntries = (ulong)Hid_Num_Entries; - Keyboard.Header.LatestEntry = 0; - Keyboard.Header.MaxEntryIndex = (ulong)Hid_Num_Entries - 1; - - //TODO: Write this structure when the input is implemented - //Marshal.StructureToPtr(Keyboard, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidKeyboard)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection1)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection2)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection3)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection4)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection5)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection6)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection7)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection8)) + - (uint)Marshal.SizeOf(typeof(HidControllerSerials)); - - //Increase the loop to initialize more controller. - for (int i = 8; i < Enum.GetNames(typeof(HidControllerID)).Length - 1; i++) - { - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset + (uint)(Marshal.SizeOf(typeof(HidController)) * i)); - - HidController Controller = new HidController(); - Controller.Header.Type = (uint)(HidControllerType.ControllerType_Handheld | HidControllerType.ControllerType_JoyconPair); - Controller.Header.IsHalf = 0; - Controller.Header.SingleColorsDescriptor = (uint)(HidControllerColorDescription.ColorDesc_ColorsNonexistent); - Controller.Header.SingleColorBody = 0; - Controller.Header.SingleColorButtons = 0; - Controller.Header.SplitColorsDescriptor = 0; - Controller.Header.LeftColorBody = (uint)JoyConColor.Body_Neon_Red; - Controller.Header.LeftColorButtons = (uint)JoyConColor.Buttons_Neon_Red; - Controller.Header.RightColorBody = (uint)JoyConColor.Body_Neon_Blue; - Controller.Header.RightColorButtons = (uint)JoyConColor.Buttons_Neon_Blue; - - Controller.Layouts = new HidControllerLayout[Enum.GetNames(typeof(HidControllerLayouts)).Length]; - Controller.Layouts[(int)HidControllerLayouts.Main] = new HidControllerLayout(); - Controller.Layouts[(int)HidControllerLayouts.Main].Header.LatestEntry = (ulong)Hid_Num_Entries; - - Marshal.StructureToPtr(Controller, HidPtr, false); - } - - Logging.Info("HID Initialized!"); - } - } - - public void SendControllerButtons(HidControllerID ControllerId, - HidControllerLayouts Layout, - HidControllerKeys Buttons, - JoystickPosition LeftJoystick, - JoystickPosition RightJoystick) - { - uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader)) + - (uint)Marshal.SizeOf(typeof(HidTouchScreen)) + - (uint)Marshal.SizeOf(typeof(HidMouse)) + - (uint)Marshal.SizeOf(typeof(HidKeyboard)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection1)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection2)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection3)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection4)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection5)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection6)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection7)) + - (uint)Marshal.SizeOf(typeof(HidUnknownSection8)) + - (uint)Marshal.SizeOf(typeof(HidControllerSerials)) + - ((uint)(Marshal.SizeOf(typeof(HidController)) * (int)ControllerId)) + - (uint)Marshal.SizeOf(typeof(HidControllerHeader)) + - (uint)Layout * (uint)Marshal.SizeOf(typeof(HidControllerLayout)); - - IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidControllerLayoutHeader OldControllerHeaderLayout = (HidControllerLayoutHeader)Marshal.PtrToStructure(HidPtr, typeof(HidControllerLayoutHeader)); - - HidControllerLayoutHeader ControllerLayoutHeader = new HidControllerLayoutHeader - { - TimestampTicks = (ulong)Environment.TickCount, - NumEntries = (ulong)Hid_Num_Entries, - MaxEntryIndex = (ulong)Hid_Num_Entries - 1, - LatestEntry = (OldControllerHeaderLayout.LatestEntry < (ulong)Hid_Num_Entries ? OldControllerHeaderLayout.LatestEntry + 1 : 0) - }; - - Marshal.StructureToPtr(ControllerLayoutHeader, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidControllerLayoutHeader)) + (uint)((uint)(ControllerLayoutHeader.LatestEntry) * Marshal.SizeOf(typeof(HidControllerInputEntry))); - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidControllerInputEntry ControllerInputEntry = new HidControllerInputEntry - { - Timestamp = (ulong)Environment.TickCount, - Timestamp_2 = (ulong)Environment.TickCount, - Buttons = (ulong)Buttons, - Joysticks = new JoystickPosition[(int)HidControllerJoystick.Joystick_Num_Sticks] - }; - ControllerInputEntry.Joysticks[(int)HidControllerJoystick.Joystick_Left] = LeftJoystick; - ControllerInputEntry.Joysticks[(int)HidControllerJoystick.Joystick_Right] = RightJoystick; - ControllerInputEntry.ConnectionState = (ulong)(HidControllerConnectionState.Controller_State_Connected | HidControllerConnectionState.Controller_State_Wired); - - Marshal.StructureToPtr(ControllerInputEntry, HidPtr, false); - } - - public void SendTouchPoint(HidTouchScreenEntryTouch TouchPoint) - { - uint InnerOffset = (uint)Marshal.SizeOf(typeof(HidSharedMemHeader)); - - IntPtr HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidTouchScreenHeader OldTouchScreenHeader = (HidTouchScreenHeader)Marshal.PtrToStructure(HidPtr,typeof(HidTouchScreenHeader)); - - HidTouchScreenHeader TouchScreenHeader = new HidTouchScreenHeader() - { - TimestampTicks = (ulong)Environment.TickCount, - NumEntries = (ulong)Hid_Num_Entries, - MaxEntryIndex = (ulong)Hid_Num_Entries - 1, - Timestamp = (ulong)Environment.TickCount, - LatestEntry = OldTouchScreenHeader.LatestEntry < Hid_Num_Entries-1 ? OldTouchScreenHeader.LatestEntry + 1 : 0 - }; - - Marshal.StructureToPtr(TouchScreenHeader, HidPtr, false); - - InnerOffset += (uint)Marshal.SizeOf(typeof(HidTouchScreenHeader)) - + (uint)((uint)(OldTouchScreenHeader.LatestEntry) * Marshal.SizeOf(typeof(HidTouchScreenEntry))); - HidPtr = new IntPtr(Ns.Ram.ToInt64() + (uint)SharedMemOffset + InnerOffset); - - HidTouchScreenEntry hidTouchScreenEntry = new HidTouchScreenEntry() - { - Header = new HidTouchScreenEntryHeader() - { - Timestamp = (ulong)Environment.TickCount, - NumTouches = 1 - }, - Touches = new HidTouchScreenEntryTouch[16] - }; - - //Only supports single touch - hidTouchScreenEntry.Touches[0] = TouchPoint; - - Marshal.StructureToPtr(hidTouchScreenEntry, HidPtr, false); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs new file mode 100644 index 000000000..4dbac40cb --- /dev/null +++ b/Ryujinx.Core/Hid/Hid.cs @@ -0,0 +1,235 @@ +using ChocolArm64.Memory; +using System.Diagnostics; + +namespace Ryujinx.Core.Input +{ + public class Hid + { + /* + * Reference: + * https://github.com/reswitched/libtransistor/blob/development/lib/hid.c + * https://github.com/reswitched/libtransistor/blob/development/include/libtransistor/hid.h + * https://github.com/switchbrew/libnx/blob/master/nx/source/services/hid.c + * https://github.com/switchbrew/libnx/blob/master/nx/include/switch/services/hid.h + */ + + private const int HidHeaderSize = 0x400; + private const int HidTouchScreenSize = 0x3000; + private const int HidMouseSize = 0x400; + private const int HidKeyboardSize = 0x400; + private const int HidUnkSection1Size = 0x400; + private const int HidUnkSection2Size = 0x400; + private const int HidUnkSection3Size = 0x400; + private const int HidUnkSection4Size = 0x400; + private const int HidUnkSection5Size = 0x200; + private const int HidUnkSection6Size = 0x200; + private const int HidUnkSection7Size = 0x200; + private const int HidUnkSection8Size = 0x800; + private const int HidControllerSerialsSize = 0x4000; + private const int HidControllersSize = 0x32000; + private const int HidUnkSection9Size = 0x800; + + private const int HidTouchHeaderSize = 0x28; + private const int HidTouchEntrySize = 0x298; + + private const int HidTouchEntryHeaderSize = 0x10; + private const int HidTouchEntryTouchSize = 0x28; + + private const int HidControllerSize = 0x5000; + private const int HidControllerHeaderSize = 0x28; + private const int HidControllerLayoutsSize = 0x350; + + private const int HidControllersLayoutHeaderSize = 0x20; + private const int HidControllersInputEntrySize = 0x30; + + private const int HidHeaderOffset = 0; + private const int HidTouchScreenOffset = HidHeaderOffset + HidHeaderSize; + private const int HidMouseOffset = HidTouchScreenOffset + HidTouchScreenSize; + private const int HidKeyboardOffset = HidMouseOffset + HidMouseSize; + private const int HidUnkSection1Offset = HidKeyboardOffset + HidKeyboardSize; + private const int HidUnkSection2Offset = HidUnkSection1Offset + HidUnkSection1Size; + private const int HidUnkSection3Offset = HidUnkSection2Offset + HidUnkSection2Size; + private const int HidUnkSection4Offset = HidUnkSection3Offset + HidUnkSection3Size; + private const int HidUnkSection5Offset = HidUnkSection4Offset + HidUnkSection4Size; + private const int HidUnkSection6Offset = HidUnkSection5Offset + HidUnkSection5Size; + private const int HidUnkSection7Offset = HidUnkSection6Offset + HidUnkSection6Size; + private const int HidUnkSection8Offset = HidUnkSection7Offset + HidUnkSection7Size; + private const int HidControllerSerialsOffset = HidUnkSection8Offset + HidUnkSection8Size; + private const int HidControllersOffset = HidControllerSerialsOffset + HidControllerSerialsSize; + private const int HidUnkSection9Offset = HidControllersOffset + HidControllersSize; + + private const int HidEntryCount = 17; + + private long SharedMemOffset; + + private Switch Ns; + + public Hid(Switch Ns) + { + this.Ns = Ns; + } + + public void Init(long HidOffset) + { + SharedMemOffset = HidOffset; + + InitializeJoyconPair( + JoyConColor.Body_Neon_Red, + JoyConColor.Buttons_Neon_Red, + JoyConColor.Body_Neon_Blue, + JoyConColor.Buttons_Neon_Blue); + } + + public void InitializeJoyconPair( + JoyConColor LeftColorBody, + JoyConColor LeftColorButtons, + JoyConColor RightColorBody, + JoyConColor RightColorButtons) + { + long BaseControllerOffset = HidControllersOffset + 8 * HidControllerSize; + + HidControllerType Type = + HidControllerType.ControllerType_Handheld | + HidControllerType.ControllerType_JoyconPair; + + bool IsHalf = false; + + HidControllerColorDesc SingleColorDesc = + HidControllerColorDesc.ColorDesc_ColorsNonexistent; + + JoyConColor SingleColorBody = JoyConColor.Black; + JoyConColor SingleColorButtons = JoyConColor.Black; + + HidControllerColorDesc SplitColorDesc = 0; + + WriteInt32(BaseControllerOffset + 0x0, (int)Type); + + WriteInt32(BaseControllerOffset + 0x4, IsHalf ? 1 : 0); + + WriteInt32(BaseControllerOffset + 0x8, (int)SingleColorDesc); + WriteInt32(BaseControllerOffset + 0xc, (int)SingleColorBody); + WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons); + WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc); + + WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody); + WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons); + + WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody); + WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons); + } + + public void SetJoyconButton( + HidControllerId ControllerId, + HidControllerLayouts ControllerLayout, + HidControllerButtons Buttons, + HidJoystickPosition LeftStick, + HidJoystickPosition RightStick) + { + long ControllerOffset = HidControllersOffset + (int)ControllerId * HidControllerSize; + + ControllerOffset += HidControllerHeaderSize; + + ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; + + long LastEntry = ReadInt64(ControllerOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = Stopwatch.GetTimestamp(); + + WriteInt64(ControllerOffset + 0x0, Timestamp); + WriteInt64(ControllerOffset + 0x8, HidEntryCount); + WriteInt64(ControllerOffset + 0x10, CurrEntry); + WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1); + + ControllerOffset += HidControllersLayoutHeaderSize; + + ControllerOffset += CurrEntry * HidControllersInputEntrySize; + + WriteInt64(ControllerOffset + 0x0, Timestamp); + WriteInt64(ControllerOffset + 0x8, Timestamp); + + WriteInt64(ControllerOffset + 0x10, (uint)Buttons); + + WriteInt32(ControllerOffset + 0x18, LeftStick.DX); + WriteInt32(ControllerOffset + 0x1c, LeftStick.DY); + + WriteInt64(ControllerOffset + 0x20, RightStick.DX); + WriteInt64(ControllerOffset + 0x24, RightStick.DY); + + WriteInt64(ControllerOffset + 0x28, + (uint)HidControllerConnState.Controller_State_Connected | + (uint)HidControllerConnState.Controller_State_Wired); + } + + public void SetTouchPoints(params HidTouchPoint[] Points) + { + long LastEntry = ReadInt64(HidTouchScreenOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = Stopwatch.GetTimestamp(); + + WriteInt64(HidTouchScreenOffset + 0x0, Timestamp); + WriteInt64(HidTouchScreenOffset + 0x8, HidEntryCount); + WriteInt64(HidTouchScreenOffset + 0x10, CurrEntry); + WriteInt64(HidTouchScreenOffset + 0x18, HidEntryCount - 1); + WriteInt64(HidTouchScreenOffset + 0x20, Timestamp); + + long TouchEntryOffset = HidTouchScreenOffset + HidTouchHeaderSize; + + TouchEntryOffset += CurrEntry * HidTouchEntrySize; + + WriteInt64(TouchEntryOffset + 0x0, Timestamp); + WriteInt64(TouchEntryOffset + 0x8, Points.Length); + + TouchEntryOffset += HidTouchEntryHeaderSize; + + const int Padding = 0; + + int Index = 0; + + foreach (HidTouchPoint Point in Points) + { + WriteInt64(TouchEntryOffset + 0x0, Timestamp); + WriteInt32(TouchEntryOffset + 0x8, Padding); + WriteInt32(TouchEntryOffset + 0xc, Index++); + WriteInt32(TouchEntryOffset + 0x10, Point.X); + WriteInt32(TouchEntryOffset + 0x14, Point.Y); + WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX); + WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY); + WriteInt32(TouchEntryOffset + 0x20, Point.Angle); + WriteInt32(TouchEntryOffset + 0x24, Padding); + + TouchEntryOffset += HidTouchEntryTouchSize; + } + } + + private unsafe long ReadInt64(long Position) + { + Position += SharedMemOffset; + + if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return 0; + + return *((long*)((byte*)Ns.Ram + Position)); + } + + private unsafe void WriteInt32(long Position, int Value) + { + Position += SharedMemOffset; + + if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return; + + *((int*)((byte*)Ns.Ram + Position)) = Value; + } + + private unsafe void WriteInt64(long Position, long Value) + { + Position += SharedMemOffset; + + if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return; + + *((long*)((byte*)Ns.Ram + Position)) = Value; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidController.cs b/Ryujinx.Core/Hid/HidController.cs deleted file mode 100644 index 641bc5569..000000000 --- a/Ryujinx.Core/Hid/HidController.cs +++ /dev/null @@ -1,188 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [Flags] - public enum HidControllerKeys - { - KEY_A = (1 << 0), - KEY_B = (1 << 1), - KEY_X = (1 << 2), - KEY_Y = (1 << 3), - KEY_LSTICK = (1 << 4), - KEY_RSTICK = (1 << 5), - KEY_L = (1 << 6), - KEY_R = (1 << 7), - KEY_ZL = (1 << 8), - KEY_ZR = (1 << 9), - KEY_PLUS = (1 << 10), - KEY_MINUS = (1 << 11), - KEY_DLEFT = (1 << 12), - KEY_DUP = (1 << 13), - KEY_DRIGHT = (1 << 14), - KEY_DDOWN = (1 << 15), - KEY_LSTICK_LEFT = (1 << 16), - KEY_LSTICK_UP = (1 << 17), - KEY_LSTICK_RIGHT = (1 << 18), - KEY_LSTICK_DOWN = (1 << 19), - KEY_RSTICK_LEFT = (1 << 20), - KEY_RSTICK_UP = (1 << 21), - KEY_RSTICK_RIGHT = (1 << 22), - KEY_RSTICK_DOWN = (1 << 23), - KEY_SL = (1 << 24), - KEY_SR = (1 << 25), - - // Pseudo-key for at least one finger on the touch screen - KEY_TOUCH = (1 << 26), - - // Buttons by orientation (for single Joy-Con), also works with Joy-Con pairs, Pro Controller - KEY_JOYCON_RIGHT = (1 << 0), - KEY_JOYCON_DOWN = (1 << 1), - KEY_JOYCON_UP = (1 << 2), - KEY_JOYCON_LEFT = (1 << 3), - - // Generic catch-all directions, also works for single Joy-Con - KEY_UP = KEY_DUP | KEY_LSTICK_UP | KEY_RSTICK_UP, - KEY_DOWN = KEY_DDOWN | KEY_LSTICK_DOWN | KEY_RSTICK_DOWN, - KEY_LEFT = KEY_DLEFT | KEY_LSTICK_LEFT | KEY_RSTICK_LEFT, - KEY_RIGHT = KEY_DRIGHT | KEY_LSTICK_RIGHT | KEY_RSTICK_RIGHT, - } - - public enum HidControllerID - { - CONTROLLER_PLAYER_1 = 0, - CONTROLLER_PLAYER_2 = 1, - CONTROLLER_PLAYER_3 = 2, - CONTROLLER_PLAYER_4 = 3, - CONTROLLER_PLAYER_5 = 4, - CONTROLLER_PLAYER_6 = 5, - CONTROLLER_PLAYER_7 = 6, - CONTROLLER_PLAYER_8 = 7, - CONTROLLER_HANDHELD = 8, - CONTROLLER_UNKNOWN = 9 - } - - public enum HidControllerJoystick - { - Joystick_Left = 0, - Joystick_Right = 1, - Joystick_Num_Sticks = 2 - } - - public enum HidControllerLayouts - { - Pro_Controller, - Handheld_Joined, - Joined, - Left, - Right, - Main_No_Analog, - Main - } - - [Flags] - public enum HidControllerConnectionState - { - Controller_State_Connected = (1 << 0), - Controller_State_Wired = (1 << 1) - } - - [Flags] - public enum HidControllerType - { - ControllerType_ProController = (1 << 0), - ControllerType_Handheld = (1 << 1), - ControllerType_JoyconPair = (1 << 2), - ControllerType_JoyconLeft = (1 << 3), - ControllerType_JoyconRight = (1 << 4) - } - - public enum HidControllerColorDescription - { - ColorDesc_ColorsNonexistent = (1 << 1), - } - - [StructLayout(LayoutKind.Sequential, Size = 0x8)] - public struct JoystickPosition - { - public int DX; - public int DY; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x20)] - public struct HidControllerMAC - { - public ulong Timestamp; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public byte[] MAC; - public ulong Unknown; - public ulong Timestamp_2; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x28)] - public struct HidControllerHeader - { - public uint Type; - public uint IsHalf; - public uint SingleColorsDescriptor; - public uint SingleColorBody; - public uint SingleColorButtons; - public uint SplitColorsDescriptor; - public uint LeftColorBody; - public uint LeftColorButtons; - public uint RightColorBody; - public uint RightColorButtons; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x20)] - public struct HidControllerLayoutHeader - { - public ulong TimestampTicks; - public ulong NumEntries; - public ulong LatestEntry; - public ulong MaxEntryIndex; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x30)] - public struct HidControllerInputEntry - { - public ulong Timestamp; - public ulong Timestamp_2; - public ulong Buttons; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)HidControllerJoystick.Joystick_Num_Sticks)] - public JoystickPosition[] Joysticks; - public ulong ConnectionState; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x350)] - public struct HidControllerLayout - { - public HidControllerLayoutHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] - public HidControllerInputEntry[] Entries; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x5000)] - public struct HidController - { - public HidControllerHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] - public HidControllerLayout[] Layouts; - /* - pro_controller - handheld_joined - joined - left - right - main_no_analog - main - */ - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x2A70)] - public byte[] Unknown_1; - public HidControllerMAC MacLeft; - public HidControllerMAC MacRight; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xDF8)] - public byte[] Unknown_2; - } -} diff --git a/Ryujinx.Core/Hid/HidControllerButtons.cs b/Ryujinx.Core/Hid/HidControllerButtons.cs new file mode 100644 index 000000000..65eb3f82f --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerButtons.cs @@ -0,0 +1,35 @@ +using System; + +namespace Ryujinx.Core.Input +{ + [Flags] + public enum HidControllerButtons + { + KEY_A = (1 << 0), + KEY_B = (1 << 1), + KEY_X = (1 << 2), + KEY_Y = (1 << 3), + KEY_LSTICK = (1 << 4), + KEY_RSTICK = (1 << 5), + KEY_L = (1 << 6), + KEY_R = (1 << 7), + KEY_ZL = (1 << 8), + KEY_ZR = (1 << 9), + KEY_PLUS = (1 << 10), + KEY_MINUS = (1 << 11), + KEY_DLEFT = (1 << 12), + KEY_DUP = (1 << 13), + KEY_DRIGHT = (1 << 14), + KEY_DDOWN = (1 << 15), + KEY_LSTICK_LEFT = (1 << 16), + KEY_LSTICK_UP = (1 << 17), + KEY_LSTICK_RIGHT = (1 << 18), + KEY_LSTICK_DOWN = (1 << 19), + KEY_RSTICK_LEFT = (1 << 20), + KEY_RSTICK_UP = (1 << 21), + KEY_RSTICK_RIGHT = (1 << 22), + KEY_RSTICK_DOWN = (1 << 23), + KEY_SL = (1 << 24), + KEY_SR = (1 << 25) + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidControllerColorDesc.cs b/Ryujinx.Core/Hid/HidControllerColorDesc.cs new file mode 100644 index 000000000..fc7fa2178 --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerColorDesc.cs @@ -0,0 +1,10 @@ +using System; + +namespace Ryujinx.Core.Input +{ + [Flags] + public enum HidControllerColorDesc + { + ColorDesc_ColorsNonexistent = (1 << 1) + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidControllerConnState.cs b/Ryujinx.Core/Hid/HidControllerConnState.cs new file mode 100644 index 000000000..7f47a7f92 --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerConnState.cs @@ -0,0 +1,11 @@ +using System; + +namespace Ryujinx.Core.Input +{ + [Flags] + public enum HidControllerConnState + { + Controller_State_Connected = (1 << 0), + Controller_State_Wired = (1 << 1) + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidControllerId.cs b/Ryujinx.Core/Hid/HidControllerId.cs new file mode 100644 index 000000000..84b68d27e --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerId.cs @@ -0,0 +1,16 @@ +namespace Ryujinx.Core.Input +{ + public enum HidControllerId + { + CONTROLLER_PLAYER_1 = 0, + CONTROLLER_PLAYER_2 = 1, + CONTROLLER_PLAYER_3 = 2, + CONTROLLER_PLAYER_4 = 3, + CONTROLLER_PLAYER_5 = 4, + CONTROLLER_PLAYER_6 = 5, + CONTROLLER_PLAYER_7 = 6, + CONTROLLER_PLAYER_8 = 7, + CONTROLLER_HANDHELD = 8, + CONTROLLER_UNKNOWN = 9 + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidControllerLayouts.cs b/Ryujinx.Core/Hid/HidControllerLayouts.cs new file mode 100644 index 000000000..e04c40b2d --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerLayouts.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.Core.Input +{ + public enum HidControllerLayouts + { + Pro_Controller = 0, + Handheld_Joined = 1, + Joined = 2, + Left = 3, + Right = 4, + Main_No_Analog = 5, + Main = 6 + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidControllerType.cs b/Ryujinx.Core/Hid/HidControllerType.cs new file mode 100644 index 000000000..a4eb674c8 --- /dev/null +++ b/Ryujinx.Core/Hid/HidControllerType.cs @@ -0,0 +1,14 @@ +using System; + +namespace Ryujinx.Core.Input +{ + [Flags] + public enum HidControllerType + { + ControllerType_ProController = (1 << 0), + ControllerType_Handheld = (1 << 1), + ControllerType_JoyconPair = (1 << 2), + ControllerType_JoyconLeft = (1 << 3), + ControllerType_JoyconRight = (1 << 4) + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidJoystickPosition.cs b/Ryujinx.Core/Hid/HidJoystickPosition.cs new file mode 100644 index 000000000..61f8189f4 --- /dev/null +++ b/Ryujinx.Core/Hid/HidJoystickPosition.cs @@ -0,0 +1,8 @@ +namespace Ryujinx.Core.Input +{ + public struct HidJoystickPosition + { + public int DX; + public int DY; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidKeyboard.cs b/Ryujinx.Core/Hid/HidKeyboard.cs deleted file mode 100644 index f9987f68b..000000000 --- a/Ryujinx.Core/Hid/HidKeyboard.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [StructLayout(LayoutKind.Sequential, Size = 0x20)] - public struct HidKeyboardHeader - { - public ulong TimestampTicks; - public ulong NumEntries; - public ulong LatestEntry; - public ulong MaxEntryIndex; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x38)] - public struct HidKeyboardEntry - { - public ulong Timestamp; - public ulong Timestamp_2; - public ulong Modifier; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public uint[] Keys; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidKeyboard - { - public HidKeyboardHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] - public HidKeyboardEntry[] Entries; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x28)] - public byte[] Padding; - } -} diff --git a/Ryujinx.Core/Hid/HidMouse.cs b/Ryujinx.Core/Hid/HidMouse.cs deleted file mode 100644 index 9a019dd5f..000000000 --- a/Ryujinx.Core/Hid/HidMouse.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [StructLayout(LayoutKind.Sequential, Size = 0x20)] - public struct HidMouseHeader - { - public ulong TimestampTicks; - public ulong NumEntries; - public ulong LatestEntry; - public ulong MaxEntryIndex; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x30)] - public struct HidMouseEntry - { - public ulong Timestamp; - public ulong Timestamp_2; - public uint X; - public uint Y; - public uint VelocityX; - public uint VelocityY; - public uint ScrollVelocityX; - public uint ScrollVelocityY; - public ulong Buttons; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidMouse - { - public HidMouseHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] - public HidMouseEntry[] Entries; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xB0)] - public byte[] Padding; - } -} diff --git a/Ryujinx.Core/Hid/HidTouchPoint.cs b/Ryujinx.Core/Hid/HidTouchPoint.cs new file mode 100644 index 000000000..1207e1d53 --- /dev/null +++ b/Ryujinx.Core/Hid/HidTouchPoint.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.Core.Input +{ + public struct HidTouchPoint + { + public int X; + public int Y; + public int DiameterX; + public int DiameterY; + public int Angle; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidTouchScreen.cs b/Ryujinx.Core/Hid/HidTouchScreen.cs deleted file mode 100644 index 755ebadca..000000000 --- a/Ryujinx.Core/Hid/HidTouchScreen.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [StructLayout(LayoutKind.Sequential, Size = 0x28)] - public struct HidTouchScreenHeader - { - public ulong TimestampTicks; - public ulong NumEntries; - public ulong LatestEntry; - public ulong MaxEntryIndex; - public ulong Timestamp; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x10)] - public struct HidTouchScreenEntryHeader - { - public ulong Timestamp; - public ulong NumTouches; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x28)] - public struct HidTouchScreenEntryTouch - { - public ulong Timestamp; - public uint Padding; - public uint TouchIndex; - public uint X; - public uint Y; - public uint DiameterX; - public uint DiameterY; - public uint Angle; - public uint Padding_2; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x298)] - public struct HidTouchScreenEntry - { - public HidTouchScreenEntryHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] - public HidTouchScreenEntryTouch[] Touches; - public ulong Unknown; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x3000)] - public struct HidTouchScreen - { - public HidTouchScreenHeader Header; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] - public HidTouchScreenEntry[] Entries; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x3C0)] - public byte[] Padding; - } - -} \ No newline at end of file diff --git a/Ryujinx.Core/Hid/HidUnknown.cs b/Ryujinx.Core/Hid/HidUnknown.cs deleted file mode 100644 index c3fe68a83..000000000 --- a/Ryujinx.Core/Hid/HidUnknown.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Ryujinx.Core -{ - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidSharedMemHeader - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidUnknownSection1 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidUnknownSection2 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidUnknownSection3 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x400)] - public struct HidUnknownSection4 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x400)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x200)] - public struct HidUnknownSection5 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x200)] - public struct HidUnknownSection6 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x200)] - public struct HidUnknownSection7 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x200)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x800)] - public struct HidUnknownSection8 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x800)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x4000)] - public struct HidControllerSerials - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x4000)] - public byte[] Padding; - } - - [StructLayout(LayoutKind.Sequential, Size = 0x4600)] - public struct HidUnknownSection9 - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x4600)] - public byte[] Padding; - } -} diff --git a/Ryujinx.Core/Hid/JoyCon.cs b/Ryujinx.Core/Hid/JoyCon.cs index 8c9518e58..1aef82fe0 100644 --- a/Ryujinx.Core/Hid/JoyCon.cs +++ b/Ryujinx.Core/Hid/JoyCon.cs @@ -1,27 +1,6 @@ -namespace Ryujinx +//TODO: This is only used by Config, it doesn't belong to Core. +namespace Ryujinx.Core.Input { - /// - /// Common RGB color hex codes for JoyCon coloring. - /// - public enum JoyConColor //Thanks to CTCaer - { - Body_Grey = 0x828282, - Body_Neon_Blue = 0x0AB9E6, - Body_Neon_Red = 0xFF3C28, - Body_Neon_Yellow = 0xE6FF00, - Body_Neon_Pink = 0xFF3278, - Body_Neon_Green = 0x1EDC00, - Body_Red = 0xE10F00, - - Buttons_Grey = 0x0F0F0F, - Buttons_Neon_Blue = 0x001E1E, - Buttons_Neon_Red = 0x1E0A0A, - Buttons_Neon_Yellow = 0x142800, - Buttons_Neon_Pink = 0x28001E, - Buttons_Neon_Green = 0x002800, - Buttons_Red = 0x280A0A - } - public struct JoyConLeft { public int StickUp; diff --git a/Ryujinx.Core/Hid/JoyConColor.cs b/Ryujinx.Core/Hid/JoyConColor.cs new file mode 100644 index 000000000..21d89fe42 --- /dev/null +++ b/Ryujinx.Core/Hid/JoyConColor.cs @@ -0,0 +1,23 @@ +namespace Ryujinx.Core.Input +{ + public enum JoyConColor //Thanks to CTCaer + { + Black = 0, + + Body_Grey = 0x828282, + Body_Neon_Blue = 0x0AB9E6, + Body_Neon_Red = 0xFF3C28, + Body_Neon_Yellow = 0xE6FF00, + Body_Neon_Pink = 0xFF3278, + Body_Neon_Green = 0x1EDC00, + Body_Red = 0xE10F00, + + Buttons_Grey = 0x0F0F0F, + Buttons_Neon_Blue = 0x001E1E, + Buttons_Neon_Red = 0x1E0A0A, + Buttons_Neon_Yellow = 0x142800, + Buttons_Neon_Pink = 0x28001E, + Buttons_Neon_Green = 0x002800, + Buttons_Red = 0x280A0A + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index f0b568c8c..84a21a8c1 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -242,6 +242,16 @@ namespace Ryujinx.Core.OsHle Logging.Trace($"Executing at 0x{e.Position:x16} {e.SubName}"); } + public void EnableCpuTracing() + { + Translator.EnableCpuTrace = true; + } + + public void DisableCpuTracing() + { + Translator.EnableCpuTrace = false; + } + private int GetFreeTlsSlot(AThread Thread) { for (int Index = 1; Index < TotalTlsSlots; Index++) diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index e7559a140..6969d3793 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -121,6 +121,8 @@ namespace Ryujinx.Core.OsHle.Svc if (SharedMem != null) { + AMemoryHelper.FillWithZeros(Memory, Src, (int)Size); + SharedMem.AddVirtualPosition(Src); Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm); diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index 8fd7979e4..0d5f8e72f 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -1,4 +1,5 @@ using ChocolArm64.Memory; +using Ryujinx.Core.Input; using Ryujinx.Core.OsHle; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gpu; @@ -14,7 +15,7 @@ namespace Ryujinx.Core internal NsGpu Gpu { get; private set; } internal Horizon Os { get; private set; } internal VirtualFs VFs { get; private set; } - internal Hid Hid { get; private set; } + public Hid Hid { get; private set; } public event EventHandler Finish; @@ -43,20 +44,6 @@ namespace Ryujinx.Core Os.LoadProgram(FileName); } - public void SendControllerButtons(HidControllerID ControllerId, - HidControllerLayouts Layout, - HidControllerKeys Buttons, - JoystickPosition LeftJoystick, - JoystickPosition RightJoystick) - { - Hid.SendControllerButtons(ControllerId, Layout, Buttons, LeftJoystick, RightJoystick); - } - - public void SendTouchScreenEntry(HidTouchScreenEntryTouch TouchPoint) - { - Hid.SendTouchPoint(TouchPoint); - } - internal virtual void OnFinish(EventArgs e) { Finish?.Invoke(this, e); diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 3219303eb..be49d1fc9 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -1,7 +1,9 @@ using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using OpenTK.Input; using Ryujinx.Core; +using Ryujinx.Core.Input; using Ryujinx.Graphics.Gal; using System; @@ -9,6 +11,12 @@ namespace Ryujinx { public class GLScreen : GameWindow { + private const int TouchScreenWidth = 1280; + private const int TouchScreenHeight = 720; + + private const float TouchScreenRatioX = (float)TouchScreenWidth / TouchScreenHeight; + private const float TouchScreenRatioY = (float)TouchScreenHeight / TouchScreenWidth; + private Switch Ns; private IGalRenderer Renderer; @@ -32,86 +40,124 @@ namespace Ryujinx protected override void OnUpdateFrame(FrameEventArgs e) { - HidControllerKeys CurrentButton = 0; - JoystickPosition LeftJoystick; - JoystickPosition RightJoystick; - + HidControllerButtons CurrentButton = 0; + HidJoystickPosition LeftJoystick; + HidJoystickPosition RightJoystick; if (Keyboard[OpenTK.Input.Key.Escape]) this.Exit(); - //RightJoystick int LeftJoystickDX = 0; int LeftJoystickDY = 0; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickUp]) LeftJoystickDY = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickDown]) LeftJoystickDY = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickLeft]) LeftJoystickDX = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickRight]) LeftJoystickDX = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.StickButton]) CurrentButton |= HidControllerKeys.KEY_LSTICK; - - //LeftButtons - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadUp]) CurrentButton |= HidControllerKeys.KEY_DUP; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadDown]) CurrentButton |= HidControllerKeys.KEY_DDOWN; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadLeft]) CurrentButton |= HidControllerKeys.KEY_DLEFT; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.DPadRight]) CurrentButton |= HidControllerKeys.KEY_DRIGHT; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonMinus]) CurrentButton |= HidControllerKeys.KEY_MINUS; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonL]) CurrentButton |= HidControllerKeys.KEY_L; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Left.ButtonZL]) CurrentButton |= HidControllerKeys.KEY_ZL; - - //RightJoystick int RightJoystickDX = 0; int RightJoystickDY = 0; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickUp]) RightJoystickDY = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickDown]) RightJoystickDY = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickLeft]) RightJoystickDX = -short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickRight]) RightJoystickDX = short.MaxValue; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.StickButton]) CurrentButton |= HidControllerKeys.KEY_RSTICK; + + //RightJoystick + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickUp]) LeftJoystickDY = short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickDown]) LeftJoystickDY = -short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickLeft]) LeftJoystickDX = -short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickRight]) LeftJoystickDX = short.MaxValue; + + //LeftButtons + if (Keyboard[(Key)Config.FakeJoyCon.Left.StickButton]) CurrentButton |= HidControllerButtons.KEY_LSTICK; + if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadUp]) CurrentButton |= HidControllerButtons.KEY_DUP; + if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadDown]) CurrentButton |= HidControllerButtons.KEY_DDOWN; + if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadLeft]) CurrentButton |= HidControllerButtons.KEY_DLEFT; + if (Keyboard[(Key)Config.FakeJoyCon.Left.DPadRight]) CurrentButton |= HidControllerButtons.KEY_DRIGHT; + if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonMinus]) CurrentButton |= HidControllerButtons.KEY_MINUS; + if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonL]) CurrentButton |= HidControllerButtons.KEY_L; + if (Keyboard[(Key)Config.FakeJoyCon.Left.ButtonZL]) CurrentButton |= HidControllerButtons.KEY_ZL; + + //RightJoystick + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickUp]) RightJoystickDY = short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickDown]) RightJoystickDY = -short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickLeft]) RightJoystickDX = -short.MaxValue; + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickRight]) RightJoystickDX = short.MaxValue; //RightButtons - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonA]) CurrentButton |= HidControllerKeys.KEY_A; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonB]) CurrentButton |= HidControllerKeys.KEY_B; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonX]) CurrentButton |= HidControllerKeys.KEY_X; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonY]) CurrentButton |= HidControllerKeys.KEY_Y; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonPlus]) CurrentButton |= HidControllerKeys.KEY_PLUS; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonR]) CurrentButton |= HidControllerKeys.KEY_R; - if (Keyboard[(OpenTK.Input.Key)Config.FakeJoyCon.Right.ButtonZR]) CurrentButton |= HidControllerKeys.KEY_ZR; + if (Keyboard[(Key)Config.FakeJoyCon.Right.StickButton]) CurrentButton |= HidControllerButtons.KEY_RSTICK; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonA]) CurrentButton |= HidControllerButtons.KEY_A; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonB]) CurrentButton |= HidControllerButtons.KEY_B; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonX]) CurrentButton |= HidControllerButtons.KEY_X; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonY]) CurrentButton |= HidControllerButtons.KEY_Y; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonPlus]) CurrentButton |= HidControllerButtons.KEY_PLUS; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonR]) CurrentButton |= HidControllerButtons.KEY_R; + if (Keyboard[(Key)Config.FakeJoyCon.Right.ButtonZR]) CurrentButton |= HidControllerButtons.KEY_ZR; - LeftJoystick = new JoystickPosition + LeftJoystick = new HidJoystickPosition { DX = LeftJoystickDX, DY = LeftJoystickDY }; - RightJoystick = new JoystickPosition + RightJoystick = new HidJoystickPosition { DX = RightJoystickDX, DY = RightJoystickDY }; + bool HasTouch = false; + //Get screen touch position from left mouse click - //Opentk always captures mouse events, even if out of focus, so check if window is focused. - if (Mouse != null && Focused) - if (Mouse.GetState().LeftButton == OpenTK.Input.ButtonState.Pressed) + //OpenTK always captures mouse events, even if out of focus, so check if window is focused. + if (Focused && Mouse?.GetState().LeftButton == OpenTK.Input.ButtonState.Pressed) + { + int ScrnWidth = Width; + int ScrnHeight = Height; + + if (Width > Height * TouchScreenRatioX) { - HidTouchScreenEntryTouch CurrentPoint = new HidTouchScreenEntryTouch + ScrnWidth = (int)(Height * TouchScreenRatioX); + } + else + { + ScrnHeight = (int)(Width * TouchScreenRatioY); + } + + int StartX = (Width - ScrnWidth) >> 1; + int StartY = (Height - ScrnHeight) >> 1; + + int EndX = StartX + ScrnWidth; + int EndY = StartY + ScrnHeight; + + if (Mouse.X >= StartX && + Mouse.Y >= StartY && + Mouse.X < EndX && + Mouse.Y < EndY) + { + int ScrnMouseX = Mouse.X - StartX; + int ScrnMouseY = Mouse.Y - StartY; + + int MX = (int)(((float)ScrnMouseX / ScrnWidth) * TouchScreenWidth); + int MY = (int)(((float)ScrnMouseY / ScrnHeight) * TouchScreenHeight); + + HidTouchPoint CurrentPoint = new HidTouchPoint { - Timestamp = (uint)Environment.TickCount, - X = (uint)Mouse.X, - Y = (uint)Mouse.Y, + X = MX, + Y = MY, //Placeholder values till more data is acquired DiameterX = 10, DiameterY = 10, - Angle = 90, - - //Only support single touch - TouchIndex = 0, + Angle = 90 }; - if (Mouse.X > -1 && Mouse.Y > -1) - Ns.SendTouchScreenEntry(CurrentPoint); - } - //We just need one pair of JoyCon because it's emulate by the keyboard. - Ns.SendControllerButtons(HidControllerID.CONTROLLER_HANDHELD, HidControllerLayouts.Main, CurrentButton, LeftJoystick, RightJoystick); + HasTouch = true; + + Ns.Hid.SetTouchPoints(CurrentPoint); + } + } + + if (!HasTouch) + { + Ns.Hid.SetTouchPoints(); + } + + Ns.Hid.SetJoyconButton( + HidControllerId.CONTROLLER_HANDHELD, + HidControllerLayouts.Main, + CurrentButton, + LeftJoystick, + RightJoystick); } protected override void OnRenderFrame(FrameEventArgs e) From 646af2498c8ef74546f73ed993f9037e4882493b Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 3 Mar 2018 02:24:04 -0300 Subject: [PATCH 42/67] Fix paths using ascii instead of utf8 on IFileSystem --- .../OsHle/Services/FspSrv/IFileSystem.cs | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs index ee9de8bc8..7db081548 100644 --- a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs @@ -3,6 +3,7 @@ using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; using System.IO; +using System.Text; using static Ryujinx.Core.OsHle.IpcServices.ErrorCode; using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; @@ -49,7 +50,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); long Mode = Context.RequestData.ReadInt64(); int Size = Context.RequestData.ReadInt32(); @@ -83,7 +84,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); string FileName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -106,7 +107,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); string DirName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -144,7 +145,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); string DirName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -168,8 +169,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv long OldPosition = Context.Request.PtrBuff[0].Position; long NewPosition = Context.Request.PtrBuff[0].Position; - string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); - string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + string OldName = ReadUtf8String(Context.Memory, OldPosition); + string NewName = ReadUtf8String(Context.Memory, NewPosition); string OldFileName = Context.Ns.VFs.GetFullPath(Path, OldName); string NewFileName = Context.Ns.VFs.GetFullPath(Path, NewName); @@ -199,8 +200,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv long OldPosition = Context.Request.PtrBuff[0].Position; long NewPosition = Context.Request.PtrBuff[0].Position; - string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); - string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + string OldName = ReadUtf8String(Context.Memory, OldPosition); + string NewName = ReadUtf8String(Context.Memory, NewPosition); string OldDirName = Context.Ns.VFs.GetFullPath(Path, OldName); string NewDirName = Context.Ns.VFs.GetFullPath(Path, NewName); @@ -229,7 +230,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); string FileName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -257,7 +258,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv int FilterFlags = Context.RequestData.ReadInt32(); - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); string FileName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -293,7 +294,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv int FilterFlags = Context.RequestData.ReadInt32(); - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); string DirName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -330,7 +331,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); Context.ResponseData.Write(Context.Ns.VFs.GetDrive().AvailableFreeSpace); @@ -341,7 +342,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string Name = ReadUtf8String(Context.Memory, Position); Context.ResponseData.Write(Context.Ns.VFs.GetDrive().TotalSize); @@ -379,5 +380,25 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv OpenPaths.Remove(DirInterface.HostPath); } } + + private string ReadUtf8String(AMemory Memory, long Position) + { + using (MemoryStream MS = new MemoryStream()) + { + while (true) + { + byte Value = Memory.ReadByte(Position++); + + if (Value == 0) + { + break; + } + + MS.WriteByte(Value); + } + + return Encoding.UTF8.GetString(MS.ToArray()); + } + } } } \ No newline at end of file From 7d48886750dadf839eb2bb37e3a81314b5497c36 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 3 Mar 2018 14:04:58 -0300 Subject: [PATCH 43/67] Fix Rename* functions on FspSrv, add a separate class do hold system settings on Switch --- .../OsHle/Services/FspSrv/IFileSystem.cs | 41 +++++++++---------- .../OsHle/Services/Set/ServiceSetSys.cs | 4 +- Ryujinx.Core/Settings/ColorSet.cs | 8 ++++ Ryujinx.Core/Settings/SetSys.cs | 7 ++++ Ryujinx.Core/Switch.cs | 11 +++-- 5 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 Ryujinx.Core/Settings/ColorSet.cs create mode 100644 Ryujinx.Core/Settings/SetSys.cs diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs index 7db081548..3593bafbb 100644 --- a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs @@ -50,7 +50,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); long Mode = Context.RequestData.ReadInt64(); int Size = Context.RequestData.ReadInt32(); @@ -84,7 +84,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); string FileName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -107,7 +107,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); string DirName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -145,7 +145,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); string DirName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -166,11 +166,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv public long RenameFile(ServiceCtx Context) { - long OldPosition = Context.Request.PtrBuff[0].Position; - long NewPosition = Context.Request.PtrBuff[0].Position; - - string OldName = ReadUtf8String(Context.Memory, OldPosition); - string NewName = ReadUtf8String(Context.Memory, NewPosition); + string OldName = ReadUtf8String(Context, 0); + string NewName = ReadUtf8String(Context, 1); string OldFileName = Context.Ns.VFs.GetFullPath(Path, OldName); string NewFileName = Context.Ns.VFs.GetFullPath(Path, NewName); @@ -197,11 +194,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv public long RenameDirectory(ServiceCtx Context) { - long OldPosition = Context.Request.PtrBuff[0].Position; - long NewPosition = Context.Request.PtrBuff[0].Position; - - string OldName = ReadUtf8String(Context.Memory, OldPosition); - string NewName = ReadUtf8String(Context.Memory, NewPosition); + string OldName = ReadUtf8String(Context, 0); + string NewName = ReadUtf8String(Context, 1); string OldDirName = Context.Ns.VFs.GetFullPath(Path, OldName); string NewDirName = Context.Ns.VFs.GetFullPath(Path, NewName); @@ -230,7 +224,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); string FileName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -258,7 +252,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv int FilterFlags = Context.RequestData.ReadInt32(); - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); string FileName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -294,7 +288,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv int FilterFlags = Context.RequestData.ReadInt32(); - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); string DirName = Context.Ns.VFs.GetFullPath(Path, Name); @@ -331,7 +325,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); Context.ResponseData.Write(Context.Ns.VFs.GetDrive().AvailableFreeSpace); @@ -342,7 +336,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv { long Position = Context.Request.PtrBuff[0].Position; - string Name = ReadUtf8String(Context.Memory, Position); + string Name = ReadUtf8String(Context); Context.ResponseData.Write(Context.Ns.VFs.GetDrive().TotalSize); @@ -381,13 +375,16 @@ namespace Ryujinx.Core.OsHle.IpcServices.FspSrv } } - private string ReadUtf8String(AMemory Memory, long Position) + private string ReadUtf8String(ServiceCtx Context, int Index = 0) { + long Position = Context.Request.PtrBuff[Index].Position; + long Size = Context.Request.PtrBuff[Index].Size; + using (MemoryStream MS = new MemoryStream()) { - while (true) + while (Size-- > 0) { - byte Value = Memory.ReadByte(Position++); + byte Value = Context.Memory.ReadByte(Position++); if (Value == 0) { diff --git a/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs b/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs index 68b303542..41c5d8b3b 100644 --- a/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs +++ b/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs @@ -22,8 +22,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Set public static long GetColorSetId(ServiceCtx Context) { - //Use white system theme - Context.ResponseData.Write(1); + Context.ResponseData.Write((int)Context.Ns.Settings.ThemeColor); + return 0; } diff --git a/Ryujinx.Core/Settings/ColorSet.cs b/Ryujinx.Core/Settings/ColorSet.cs new file mode 100644 index 000000000..43483363f --- /dev/null +++ b/Ryujinx.Core/Settings/ColorSet.cs @@ -0,0 +1,8 @@ +namespace Ryujinx.Core.Settings +{ + public enum ColorSet + { + BasicWhite = 0, + BasicBlack = 1 + } +} diff --git a/Ryujinx.Core/Settings/SetSys.cs b/Ryujinx.Core/Settings/SetSys.cs new file mode 100644 index 000000000..d8b6eb6ef --- /dev/null +++ b/Ryujinx.Core/Settings/SetSys.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.Core.Settings +{ + public class SetSys + { + public ColorSet ThemeColor; + } +} diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index 0d5f8e72f..6f41da814 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -1,6 +1,7 @@ using ChocolArm64.Memory; using Ryujinx.Core.Input; using Ryujinx.Core.OsHle; +using Ryujinx.Core.Settings; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gpu; using System; @@ -15,7 +16,9 @@ namespace Ryujinx.Core internal NsGpu Gpu { get; private set; } internal Horizon Os { get; private set; } internal VirtualFs VFs { get; private set; } - public Hid Hid { get; private set; } + + public Hid Hid { get; private set; } + public SetSys Settings { get; private set; } public event EventHandler Finish; @@ -24,9 +27,11 @@ namespace Ryujinx.Core Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); Gpu = new NsGpu(Renderer); - Os = new Horizon(this); VFs = new VirtualFs(); - Hid = new Hid(this); + + Hid = new Hid(this); + Os = new Horizon(this); + Settings = new SetSys(); } public void FinalizeAllProcesses() From 8dcffe6a5103920ab63e46f93029b27e311335f3 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 4 Mar 2018 00:06:44 -0300 Subject: [PATCH 44/67] Fix hid touch screen timestamp, add more log info --- Ryujinx.Core/Hid/Hid.cs | 14 ++++++++++++-- Ryujinx.Core/OsHle/Process.cs | 14 +++++++++++++- Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs | 1 - Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs | 6 ++++++ Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs | 4 +++- Ryujinx/Ui/GLScreen.cs | 4 ++-- 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs index 4dbac40cb..c76782cff 100644 --- a/Ryujinx.Core/Hid/Hid.cs +++ b/Ryujinx.Core/Hid/Hid.cs @@ -164,6 +164,8 @@ namespace Ryujinx.Core.Input public void SetTouchPoints(params HidTouchPoint[] Points) { + Logging.Debug("hid touch"); + long LastEntry = ReadInt64(HidTouchScreenOffset + 0x10); long CurrEntry = (LastEntry + 1) % HidEntryCount; @@ -178,9 +180,13 @@ namespace Ryujinx.Core.Input long TouchEntryOffset = HidTouchScreenOffset + HidTouchHeaderSize; - TouchEntryOffset += CurrEntry * HidTouchEntrySize; + long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize; - WriteInt64(TouchEntryOffset + 0x0, Timestamp); + long LastTimestamp = ReadInt64(LastEntryOffset); + + TouchEntryOffset += CurrEntry * HidTouchEntrySize; + + WriteInt64(TouchEntryOffset + 0x0, LastTimestamp + 1); WriteInt64(TouchEntryOffset + 0x8, Points.Length); TouchEntryOffset += HidTouchEntryHeaderSize; @@ -220,6 +226,8 @@ namespace Ryujinx.Core.Input if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return; + Logging.Debug($"hid wr32 {Position:x8} {Value:x8}"); + *((int*)((byte*)Ns.Ram + Position)) = Value; } @@ -229,6 +237,8 @@ namespace Ryujinx.Core.Input if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return; + Logging.Debug($"hid wr64 {Position:x8} {Value:x16}"); + *((long*)((byte*)Ns.Ram + Position)) = Value; } } diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index 84a21a8c1..f549b0279 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -239,7 +239,19 @@ namespace Ryujinx.Core.OsHle private void CpuTraceHandler(object sender, ACpuTraceEventArgs e) { - Logging.Trace($"Executing at 0x{e.Position:x16} {e.SubName}"); + string NsoName = string.Empty; + + for (int Index = Executables.Count - 1; Index >= 0; Index--) + { + if (e.Position >= Executables[Index].ImageBase) + { + NsoName = $"{(e.Position - Executables[Index].ImageBase):x16}"; + + break; + } + } + + Logging.Trace($"Executing at 0x{e.Position:x16} {e.SubName} {NsoName}"); } public void EnableCpuTracing() diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs index 3593bafbb..569a7dd6b 100644 --- a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs @@ -1,4 +1,3 @@ -using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Ipc; using System; using System.Collections.Generic; diff --git a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs index b0e5f44e2..cc30a771e 100644 --- a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs @@ -26,6 +26,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid { 121, GetNpadJoyHoldType }, { 200, GetVibrationDeviceInfo }, { 203, CreateActiveVibrationDeviceList }, + { 206, SendVibrationValues } }; } @@ -104,5 +105,10 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid return 0; } + + public long SendVibrationValues(ServiceCtx Context) + { + return 0; + } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs index 1de0ab706..2f2238914 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs @@ -532,6 +532,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices Context.Memory.WriteInt32(Position + 4, Handle); + Logging.Info($"NvMap {Id} created with size {Size:x8}!"); + return 0; } @@ -580,7 +582,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices NvMap.Kind = Kind; } - Logging.Debug($"NvMapIocAlloc at {NvMap.Address:x16}"); + Logging.Debug($"{NvMap.Address:x16}"); return 0; } diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index be49d1fc9..1e48b2805 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -44,7 +44,7 @@ namespace Ryujinx HidJoystickPosition LeftJoystick; HidJoystickPosition RightJoystick; - if (Keyboard[OpenTK.Input.Key.Escape]) this.Exit(); + if (Keyboard[Key.Escape]) this.Exit(); int LeftJoystickDX = 0; int LeftJoystickDY = 0; @@ -99,7 +99,7 @@ namespace Ryujinx //Get screen touch position from left mouse click //OpenTK always captures mouse events, even if out of focus, so check if window is focused. - if (Focused && Mouse?.GetState().LeftButton == OpenTK.Input.ButtonState.Pressed) + if (Focused && Mouse?.GetState().LeftButton == ButtonState.Pressed) { int ScrnWidth = Width; int ScrnHeight = Height; From 479443564c5372ec9c768a9d41b1ffbdbbd5dd41 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 4 Mar 2018 00:09:16 -0300 Subject: [PATCH 45/67] Remove unneeded log messages --- Ryujinx.Core/Hid/Hid.cs | 6 ------ Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs | 2 -- 2 files changed, 8 deletions(-) diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs index c76782cff..d7227889a 100644 --- a/Ryujinx.Core/Hid/Hid.cs +++ b/Ryujinx.Core/Hid/Hid.cs @@ -164,8 +164,6 @@ namespace Ryujinx.Core.Input public void SetTouchPoints(params HidTouchPoint[] Points) { - Logging.Debug("hid touch"); - long LastEntry = ReadInt64(HidTouchScreenOffset + 0x10); long CurrEntry = (LastEntry + 1) % HidEntryCount; @@ -226,8 +224,6 @@ namespace Ryujinx.Core.Input if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return; - Logging.Debug($"hid wr32 {Position:x8} {Value:x8}"); - *((int*)((byte*)Ns.Ram + Position)) = Value; } @@ -237,8 +233,6 @@ namespace Ryujinx.Core.Input if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return; - Logging.Debug($"hid wr64 {Position:x8} {Value:x16}"); - *((long*)((byte*)Ns.Ram + Position)) = Value; } } diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs index 2f2238914..0ea1d2ac0 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs @@ -582,8 +582,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices NvMap.Kind = Kind; } - Logging.Debug($"{NvMap.Address:x16}"); - return 0; } From ee9df32e3e13fe982c8154a6454566c8edfa13d3 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 4 Mar 2018 01:41:35 -0300 Subject: [PATCH 46/67] Do not block execution on audout append buffer --- Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs | 42 +++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs index 0562d4b9a..c58d9e804 100644 --- a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs +++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs @@ -9,7 +9,7 @@ using System.IO; namespace Ryujinx.Core.OsHle.IpcServices.Aud { - class IAudioOut : IIpcService + class IAudioOut : IIpcService, IDisposable { private Dictionary m_Commands; @@ -121,6 +121,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud { if (AudioCtx == null) //Needed to call the instance of AudioContext() return 0; + + EnsureAudioFinalized(); Source = AL.GenSource(); Buffer = AL.GenBuffer(); @@ -128,16 +130,6 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud AL.BufferData(Buffer, ALFormat.Stereo16, AudioSampleBuffer, AudioSampleBuffer.Length, 48000); AL.SourceQueueBuffer(Source, Buffer); AL.SourcePlay(Source); - - int State; - - do AL.GetSource(Source, ALGetSourcei.SourceState, out State); - while ((ALSourceState)State == ALSourceState.Playing); - - AL.SourceStop(Source); - AL.SourceUnqueueBuffer(Buffer); - AL.DeleteSource(Source); - AL.DeleteBuffers(1, ref Buffer); } } } @@ -186,5 +178,33 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud { return 0; } + + private void EnsureAudioFinalized() + { + if (Source != 0 || + Buffer != 0) + { + AL.SourceStop(Source); + AL.SourceUnqueueBuffer(Buffer); + AL.DeleteSource(Source); + AL.DeleteBuffers(1, ref Buffer); + + Source = 0; + Buffer = 0; + } + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + EnsureAudioFinalized(); + } + } } } From 3edb66f389ac279bdcde26c5682aa39b9bf5f853 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 4 Mar 2018 14:09:59 -0300 Subject: [PATCH 47/67] Improve CPU initial translation speeds (#50) * Add background translation to the CPU * Do not use a separate thread for translation, implement 2 tiers translation * Remove unnecessary usings * Lower MinCallCountForReJit * Remove unused variable --- ChocolArm64/ATranslatedSub.cs | 104 +++++++++++------- ChocolArm64/ATranslatedSubType.cs | 9 ++ ChocolArm64/ATranslator.cs | 81 +++++++++++--- ChocolArm64/Decoder/ADecoder.cs | 16 ++- ChocolArm64/Instruction/AInstEmitException.cs | 13 +++ ChocolArm64/Instruction/AInstEmitFlow.cs | 81 ++++++++++++-- ChocolArm64/Translation/AILEmitter.cs | 42 +++---- ChocolArm64/Translation/AILEmitterCtx.cs | 58 +++++++--- ChocolArm64/Translation/ALocalAlloc.cs | 18 +-- .../OsHle/Services/Set/ServiceSetSys.cs | 4 +- 10 files changed, 319 insertions(+), 107 deletions(-) create mode 100644 ChocolArm64/ATranslatedSubType.cs diff --git a/ChocolArm64/ATranslatedSub.cs b/ChocolArm64/ATranslatedSub.cs index 71a6793a2..414038ab6 100644 --- a/ChocolArm64/ATranslatedSub.cs +++ b/ChocolArm64/ATranslatedSub.cs @@ -2,6 +2,7 @@ using ChocolArm64.Memory; using ChocolArm64.State; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Reflection; using System.Reflection.Emit; @@ -13,35 +14,47 @@ namespace ChocolArm64 private AA64Subroutine ExecDelegate; - private bool HasDelegate; - - public static Type[] FixedArgTypes { get; private set; } - public static int StateArgIdx { get; private set; } public static int MemoryArgIdx { get; private set; } + public static Type[] FixedArgTypes { get; private set; } + public DynamicMethod Method { get; private set; } - public HashSet SubCalls { get; private set; } + public ReadOnlyCollection Params { get; private set; } - public List Params { get; private set; } + private HashSet Callees; - public bool NeedsReJit { get; private set; } + private ATranslatedSubType Type; - public ATranslatedSub() + private int CallCount; + + private bool NeedsReJit; + + private int MinCallCountForReJit = 250; + + public ATranslatedSub(DynamicMethod Method, List Params, HashSet Callees) { - SubCalls = new HashSet(); - } + if (Method == null) + { + throw new ArgumentNullException(nameof(Method)); + } - public ATranslatedSub(DynamicMethod Method, List Params) : this() - { if (Params == null) { throw new ArgumentNullException(nameof(Params)); } - this.Method = Method; - this.Params = Params; + if (Callees == null) + { + throw new ArgumentNullException(nameof(Callees)); + } + + this.Method = Method; + this.Params = Params.AsReadOnly(); + this.Callees = Callees; + + PrepareDelegate(); } static ATranslatedSub() @@ -69,36 +82,53 @@ namespace ChocolArm64 } } - public long Execute(AThreadState ThreadState, AMemory Memory) + private void PrepareDelegate() { - if (!HasDelegate) + string Name = $"{Method.Name}_Dispatch"; + + DynamicMethod Mthd = new DynamicMethod(Name, typeof(long), FixedArgTypes); + + ILGenerator Generator = Mthd.GetILGenerator(); + + Generator.EmitLdargSeq(FixedArgTypes.Length); + + foreach (ARegister Reg in Params) { - string Name = $"{Method.Name}_Dispatch"; + Generator.EmitLdarg(StateArgIdx); - DynamicMethod Mthd = new DynamicMethod(Name, typeof(long), FixedArgTypes); - - ILGenerator Generator = Mthd.GetILGenerator(); - - Generator.EmitLdargSeq(FixedArgTypes.Length); - - foreach (ARegister Reg in Params) - { - Generator.EmitLdarg(StateArgIdx); - - Generator.Emit(OpCodes.Ldfld, Reg.GetField()); - } - - Generator.Emit(OpCodes.Call, Method); - Generator.Emit(OpCodes.Ret); - - ExecDelegate = (AA64Subroutine)Mthd.CreateDelegate(typeof(AA64Subroutine)); - - HasDelegate = true; + Generator.Emit(OpCodes.Ldfld, Reg.GetField()); } + Generator.Emit(OpCodes.Call, Method); + Generator.Emit(OpCodes.Ret); + + ExecDelegate = (AA64Subroutine)Mthd.CreateDelegate(typeof(AA64Subroutine)); + } + + public bool ShouldReJit() + { + if (Type == ATranslatedSubType.SubTier0) + { + if (CallCount < MinCallCountForReJit) + { + CallCount++; + } + + return CallCount == MinCallCountForReJit; + } + + return Type == ATranslatedSubType.SubTier1 && NeedsReJit; + } + + public long Execute(AThreadState ThreadState, AMemory Memory) + { return ExecDelegate(ThreadState, Memory); } - public void MarkForReJit() => NeedsReJit = true; + public void SetType(ATranslatedSubType Type) => this.Type = Type; + + public bool HasCallee(long Position) => Callees.Contains(Position); + + public void MarkForReJit() => NeedsReJit = true; } } \ No newline at end of file diff --git a/ChocolArm64/ATranslatedSubType.cs b/ChocolArm64/ATranslatedSubType.cs new file mode 100644 index 000000000..e9f3e0bf0 --- /dev/null +++ b/ChocolArm64/ATranslatedSubType.cs @@ -0,0 +1,9 @@ +namespace ChocolArm64 +{ + enum ATranslatedSubType + { + SubBlock, + SubTier0, + SubTier1 + } +} \ No newline at end of file diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs index 2daf7bbc9..ab434e226 100644 --- a/ChocolArm64/ATranslator.cs +++ b/ChocolArm64/ATranslator.cs @@ -7,11 +7,14 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection.Emit; +using System.Threading; namespace ChocolArm64 { public class ATranslator { + private HashSet SubBlocks; + private ConcurrentDictionary CachedSubs; private ConcurrentDictionary SymbolTable; @@ -24,6 +27,8 @@ namespace ChocolArm64 public ATranslator(IReadOnlyDictionary SymbolTable = null) { + SubBlocks = new HashSet(); + CachedSubs = new ConcurrentDictionary(); if (SymbolTable != null) @@ -38,9 +43,9 @@ namespace ChocolArm64 KeepRunning = true; } - public void StopExecution() => KeepRunning = false; + internal void StopExecution() => KeepRunning = false; - public void ExecuteSubroutine(AThread Thread, long Position) + internal void ExecuteSubroutine(AThread Thread, long Position) { do { @@ -54,9 +59,14 @@ namespace ChocolArm64 CpuTrace?.Invoke(this, new ACpuTraceEventArgs(Position, SubName)); } - if (!CachedSubs.TryGetValue(Position, out ATranslatedSub Sub) || Sub.NeedsReJit) + if (!CachedSubs.TryGetValue(Position, out ATranslatedSub Sub)) { - Sub = TranslateSubroutine(Thread.Memory, Position); + Sub = TranslateTier0(Thread.Memory, Position); + } + + if (Sub.ShouldReJit()) + { + TranslateTier1(Thread.Memory, Position); } Position = Sub.Execute(Thread.ThreadState, Thread.Memory); @@ -86,19 +96,57 @@ namespace ChocolArm64 return CachedSubs.ContainsKey(Position); } - private ATranslatedSub TranslateSubroutine(AMemory Memory, long Position) + private ATranslatedSub TranslateTier0(AMemory Memory, long Position) + { + ABlock Block = ADecoder.DecodeBasicBlock(this, Memory, Position); + + ABlock[] Graph = new ABlock[] { Block }; + + string SubName = GetSubName(Position); + + AILEmitterCtx Context = new AILEmitterCtx(this, Graph, Block, SubName); + + do + { + Context.EmitOpCode(); + } + while (Context.AdvanceOpCode()); + + ATranslatedSub Subroutine = Context.GetSubroutine(); + + if (SubBlocks.Contains(Position)) + { + SubBlocks.Remove(Position); + + Subroutine.SetType(ATranslatedSubType.SubBlock); + } + else + { + Subroutine.SetType(ATranslatedSubType.SubTier0); + } + + CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine); + + AOpCode LastOp = Block.GetLastOp(); + + if (LastOp.Emitter != AInstEmit.Ret && + LastOp.Emitter != AInstEmit.Br) + { + SubBlocks.Add(LastOp.Position + 4); + } + + return Subroutine; + } + + private void TranslateTier1(AMemory Memory, long Position) { (ABlock[] Graph, ABlock Root) Cfg = ADecoder.DecodeSubroutine(this, Memory, Position); - string SubName = SymbolTable.GetOrAdd(Position, $"Sub{Position:x16}"); + string SubName = GetSubName(Position); PropagateName(Cfg.Graph, SubName); - AILEmitterCtx Context = new AILEmitterCtx( - this, - Cfg.Graph, - Cfg.Root, - SubName); + AILEmitterCtx Context = new AILEmitterCtx(this, Cfg.Graph, Cfg.Root, SubName); if (Context.CurrBlock.Position != Position) { @@ -115,7 +163,7 @@ namespace ChocolArm64 //since we can now call it directly which is faster. foreach (ATranslatedSub TS in CachedSubs.Values) { - if (TS.SubCalls.Contains(Position)) + if (TS.HasCallee(Position)) { TS.MarkForReJit(); } @@ -123,9 +171,14 @@ namespace ChocolArm64 ATranslatedSub Subroutine = Context.GetSubroutine(); - CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine); + Subroutine.SetType(ATranslatedSubType.SubTier1); - return Subroutine; + CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine); + } + + private string GetSubName(long Position) + { + return SymbolTable.GetOrAdd(Position, $"Sub{Position:x16}"); } private void PropagateName(ABlock[] Graph, string Name) diff --git a/ChocolArm64/Decoder/ADecoder.cs b/ChocolArm64/Decoder/ADecoder.cs index 443022903..2375c1857 100644 --- a/ChocolArm64/Decoder/ADecoder.cs +++ b/ChocolArm64/Decoder/ADecoder.cs @@ -18,6 +18,18 @@ namespace ChocolArm64.Decoder OpActivators = new ConcurrentDictionary(); } + public static ABlock DecodeBasicBlock( + ATranslator Translator, + AMemory Memory, + long Start) + { + ABlock Block = new ABlock(Start); + + FillBlock(Memory, Block); + + return Block; + } + public static (ABlock[] Graph, ABlock Root) DecodeSubroutine( ATranslator Translator, AMemory Memory, @@ -72,8 +84,8 @@ namespace ChocolArm64.Decoder } } - if ((!(LastOp is AOpCodeBImmAl) && - !(LastOp is AOpCodeBReg)) || HasCachedSub) + if (!((LastOp is AOpCodeBImmAl) || + (LastOp is AOpCodeBReg)) || HasCachedSub) { Current.Next = Enqueue(Current.EndPosition); } diff --git a/ChocolArm64/Instruction/AInstEmitException.cs b/ChocolArm64/Instruction/AInstEmitException.cs index 209ba56f5..fe348edd1 100644 --- a/ChocolArm64/Instruction/AInstEmitException.cs +++ b/ChocolArm64/Instruction/AInstEmitException.cs @@ -2,6 +2,7 @@ using ChocolArm64.Decoder; using ChocolArm64.State; using ChocolArm64.Translation; using System.Reflection; +using System.Reflection.Emit; namespace ChocolArm64.Instruction { @@ -37,6 +38,12 @@ namespace ChocolArm64.Instruction { Context.EmitLoadState(Context.CurrBlock.Next); } + else + { + Context.EmitLdc_I8(Op.Position + 4); + + Context.Emit(OpCodes.Ret); + } } public static void Und(AILEmitterCtx Context) @@ -60,6 +67,12 @@ namespace ChocolArm64.Instruction { Context.EmitLoadState(Context.CurrBlock.Next); } + else + { + Context.EmitLdc_I8(Op.Position + 4); + + Context.Emit(OpCodes.Ret); + } } } } \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitFlow.cs b/ChocolArm64/Instruction/AInstEmitFlow.cs index be68aa6c9..91262834f 100644 --- a/ChocolArm64/Instruction/AInstEmitFlow.cs +++ b/ChocolArm64/Instruction/AInstEmitFlow.cs @@ -11,14 +11,24 @@ namespace ChocolArm64.Instruction { AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp; - Context.Emit(OpCodes.Br, Context.GetLabel(Op.Imm)); + if (Context.CurrBlock.Branch != null) + { + Context.Emit(OpCodes.Br, Context.GetLabel(Op.Imm)); + } + else + { + Context.EmitStoreState(); + Context.EmitLdc_I8(Op.Imm); + + Context.Emit(OpCodes.Ret); + } } public static void B_Cond(AILEmitterCtx Context) { AOpCodeBImmCond Op = (AOpCodeBImmCond)Context.CurrOp; - Context.EmitCondBranch(Context.GetLabel(Op.Imm), Op.Cond); + EmitBranch(Context, Op.Cond); } public static void Bl(AILEmitterCtx Context) @@ -48,10 +58,7 @@ namespace ChocolArm64.Instruction Context.Emit(OpCodes.Pop); - if (Context.CurrBlock.Next != null) - { - Context.EmitLoadState(Context.CurrBlock.Next); - } + Context.EmitLoadState(Context.CurrBlock.Next); } else { @@ -93,7 +100,7 @@ namespace ChocolArm64.Instruction Context.EmitLdintzr(Op.Rt); Context.EmitLdc_I(0); - Context.Emit(ILOp, Context.GetLabel(Op.Imm)); + EmitBranch(Context, ILOp); } public static void Ret(AILEmitterCtx Context) @@ -118,7 +125,65 @@ namespace ChocolArm64.Instruction Context.EmitLdc_I(0); - Context.Emit(ILOp, Context.GetLabel(Op.Imm)); + EmitBranch(Context, ILOp); + } + + private static void EmitBranch(AILEmitterCtx Context, ACond Cond) + { + AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp; + + if (Context.CurrBlock.Next != null && + Context.CurrBlock.Branch != null) + { + Context.EmitCondBranch(Context.GetLabel(Op.Imm), Cond); + } + else + { + Context.EmitStoreState(); + + AILLabel LblTaken = new AILLabel(); + + Context.EmitCondBranch(LblTaken, Cond); + + Context.EmitLdc_I8(Op.Position + 4); + + Context.Emit(OpCodes.Ret); + + Context.MarkLabel(LblTaken); + + Context.EmitLdc_I8(Op.Imm); + + Context.Emit(OpCodes.Ret); + } + } + + private static void EmitBranch(AILEmitterCtx Context, OpCode ILOp) + { + AOpCodeBImm Op = (AOpCodeBImm)Context.CurrOp; + + if (Context.CurrBlock.Next != null && + Context.CurrBlock.Branch != null) + { + Context.Emit(ILOp, Context.GetLabel(Op.Imm)); + } + else + { + Context.EmitStoreState(); + + AILLabel LblTaken = new AILLabel(); + + Context.Emit(ILOp, LblTaken); + + Context.EmitLdc_I8(Op.Position + 4); + + Context.Emit(OpCodes.Ret); + + Context.MarkLabel(LblTaken); + + Context.EmitLdc_I8(Op.Imm); + + Context.Emit(OpCodes.Ret); + } } } } \ No newline at end of file diff --git a/ChocolArm64/Translation/AILEmitter.cs b/ChocolArm64/Translation/AILEmitter.cs index 8f6e1210f..af37a6c75 100644 --- a/ChocolArm64/Translation/AILEmitter.cs +++ b/ChocolArm64/Translation/AILEmitter.cs @@ -58,11 +58,13 @@ namespace ChocolArm64.Translation this.Root = ILBlocks[Array.IndexOf(Graph, Root)]; } - public ATranslatedSub GetSubroutine() + public AILBlock GetILBlock(int Index) => ILBlocks[Index]; + + public ATranslatedSub GetSubroutine(HashSet Callees) { LocalAlloc = new ALocalAlloc(ILBlocks, Root); - InitSubroutine(); + InitSubroutine(Callees); InitLocals(); foreach (AILBlock ILBlock in ILBlocks) @@ -73,24 +75,7 @@ namespace ChocolArm64.Translation return Subroutine; } - public AILBlock GetILBlock(int Index) => ILBlocks[Index]; - - private void InitLocals() - { - int ParamsStart = ATranslatedSub.FixedArgTypes.Length; - - Locals = new Dictionary(); - - for (int Index = 0; Index < Subroutine.Params.Count; Index++) - { - ARegister Reg = Subroutine.Params[Index]; - - Generator.EmitLdarg(Index + ParamsStart); - Generator.EmitStloc(GetLocalIndex(Reg)); - } - } - - private void InitSubroutine() + private void InitSubroutine(HashSet Callees) { List Params = new List(); @@ -114,9 +99,24 @@ namespace ChocolArm64.Translation Generator = Mthd.GetILGenerator(); - Subroutine = new ATranslatedSub(Mthd, Params); + Subroutine = new ATranslatedSub(Mthd, Params, Callees); } + private void InitLocals() + { + int ParamsStart = ATranslatedSub.FixedArgTypes.Length; + + Locals = new Dictionary(); + + for (int Index = 0; Index < Subroutine.Params.Count; Index++) + { + ARegister Reg = Subroutine.Params[Index]; + + Generator.EmitLdarg(Index + ParamsStart); + Generator.EmitStloc(GetLocalIndex(Reg)); + } + } + private Type[] GetParamTypes(IList Params) { Type[] FixedArgs = ATranslatedSub.FixedArgTypes; diff --git a/ChocolArm64/Translation/AILEmitterCtx.cs b/ChocolArm64/Translation/AILEmitterCtx.cs index ffcfa851a..466594694 100644 --- a/ChocolArm64/Translation/AILEmitterCtx.cs +++ b/ChocolArm64/Translation/AILEmitterCtx.cs @@ -12,14 +12,9 @@ namespace ChocolArm64.Translation { private ATranslator Translator; - private Dictionary Labels; + private HashSet Callees; - private AILEmitter Emitter; - - private AILBlock ILBlock; - - private AOpCode OptOpLastCompare; - private AOpCode OptOpLastFlagSet; + private Dictionary Labels; private int BlkIndex; private int OpcIndex; @@ -29,6 +24,13 @@ namespace ChocolArm64.Translation public ABlock CurrBlock => Graph[BlkIndex]; public AOpCode CurrOp => Graph[BlkIndex].OpCodes[OpcIndex]; + private AILEmitter Emitter; + + private AILBlock ILBlock; + + private AOpCode OptOpLastCompare; + private AOpCode OptOpLastFlagSet; + //This is the index of the temporary register, used to store temporary //values needed by some functions, since IL doesn't have a swap instruction. //You can use any value here as long it doesn't conflict with the indices @@ -45,10 +47,27 @@ namespace ChocolArm64.Translation ABlock Root, string SubName) { + if (Translator == null) + { + throw new ArgumentNullException(nameof(Translator)); + } + + if (Graph == null) + { + throw new ArgumentNullException(nameof(Graph)); + } + + if (Root == null) + { + throw new ArgumentNullException(nameof(Root)); + } + this.Translator = Translator; this.Graph = Graph; this.Root = Root; + Callees = new HashSet(); + Labels = new Dictionary(); Emitter = new AILEmitter(Graph, Root, SubName); @@ -57,23 +76,27 @@ namespace ChocolArm64.Translation OpcIndex = -1; - if (!AdvanceOpCode()) + if (Graph.Length == 0 || !AdvanceOpCode()) { throw new ArgumentException(nameof(Graph)); } } - public ATranslatedSub GetSubroutine() => Emitter.GetSubroutine(); + public ATranslatedSub GetSubroutine() + { + return Emitter.GetSubroutine(Callees); + } public bool AdvanceOpCode() { + if (OpcIndex + 1 == CurrBlock.OpCodes.Count && + BlkIndex + 1 == Graph.Length) + { + return false; + } + while (++OpcIndex >= (CurrBlock?.OpCodes.Count ?? 0)) { - if (BlkIndex + 1 >= Graph.Length) - { - return false; - } - BlkIndex++; OpcIndex = -1; @@ -100,6 +123,13 @@ namespace ChocolArm64.Translation public bool TryOptEmitSubroutineCall() { + Callees.Add(((AOpCodeBImm)CurrOp).Imm); + + if (CurrBlock.Next == null) + { + return false; + } + if (!Translator.TryGetCachedSub(CurrOp, out ATranslatedSub Sub)) { return false; diff --git a/ChocolArm64/Translation/ALocalAlloc.cs b/ChocolArm64/Translation/ALocalAlloc.cs index f23af9c76..8e9047804 100644 --- a/ChocolArm64/Translation/ALocalAlloc.cs +++ b/ChocolArm64/Translation/ALocalAlloc.cs @@ -67,14 +67,15 @@ namespace ChocolArm64.Translation public long VecOutputs; } - private const int MaxOptGraphLength = 55; + private const int MaxOptGraphLength = 40; public ALocalAlloc(AILBlock[] Graph, AILBlock Root) { IntPaths = new Dictionary(); VecPaths = new Dictionary(); - if (Graph.Length < MaxOptGraphLength) + if (Graph.Length > 1 && + Graph.Length < MaxOptGraphLength) { InitializeOptimal(Graph, Root); } @@ -179,10 +180,8 @@ namespace ChocolArm64.Translation { //This is WAY faster than InitializeOptimal, but results in //uneeded loads and stores, so the resulting code will be slower. - long IntInputs = 0; - long IntOutputs = 0; - long VecInputs = 0; - long VecOutputs = 0; + long IntInputs = 0, IntOutputs = 0; + long VecInputs = 0, VecOutputs = 0; foreach (AILBlock Block in Graph) { @@ -196,8 +195,11 @@ namespace ChocolArm64.Translation //in those cases if we attempt to write an output registers that was //not written, we will be just writing zero and messing up the old register value. //So we just need to ensure that all outputs are loaded. - IntInputs |= IntOutputs; - VecInputs |= VecOutputs; + if (Graph.Length > 1) + { + IntInputs |= IntOutputs; + VecInputs |= VecOutputs; + } foreach (AILBlock Block in Graph) { diff --git a/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs b/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs index 41c5d8b3b..dee6573d3 100644 --- a/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs +++ b/Ryujinx.Core/OsHle/Services/Set/ServiceSetSys.cs @@ -1,6 +1,4 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Ipc; -using System; +using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; namespace Ryujinx.Core.OsHle.IpcServices.Set From 344fc8a55de471121d3f600cca9e95315d0e502f Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 4 Mar 2018 20:32:18 -0300 Subject: [PATCH 48/67] Try fixing NvFlinger rotation with scaling, return correct error code on WaitSignal timeout, always display window at the center of the screen --- ChocolArm64/ATranslator.cs | 1 - Ryujinx.Core/OsHle/CondVar.cs | 8 +++- .../OsHle/Handles/KProcessScheduler.cs | 12 ++++-- Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 38 +++++++++++-------- Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs | 7 +++- Ryujinx/Ui/GLScreen.cs | 4 ++ 6 files changed, 46 insertions(+), 24 deletions(-) diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs index ab434e226..1f4a922ab 100644 --- a/ChocolArm64/ATranslator.cs +++ b/ChocolArm64/ATranslator.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection.Emit; -using System.Threading; namespace ChocolArm64 { diff --git a/Ryujinx.Core/OsHle/CondVar.cs b/Ryujinx.Core/OsHle/CondVar.cs index 7b3e18521..ac3ba5749 100644 --- a/Ryujinx.Core/OsHle/CondVar.cs +++ b/Ryujinx.Core/OsHle/CondVar.cs @@ -24,7 +24,7 @@ namespace Ryujinx.Core.OsHle WaitingThreads = new List(); } - public void WaitForSignal(HThread Thread) + public bool WaitForSignal(HThread Thread) { int Count = Process.Memory.ReadInt32(CondVarAddress); @@ -41,12 +41,14 @@ namespace Ryujinx.Core.OsHle } else { - Process.Scheduler.WaitForSignal(Thread, (int)(Timeout / 1000000)); + bool Result = Process.Scheduler.WaitForSignal(Thread, (int)(Timeout / 1000000)); lock (WaitingThreads) { WaitingThreads.Remove(Thread); } + + return Result; } } @@ -60,6 +62,8 @@ namespace Ryujinx.Core.OsHle } ReleaseCondVarValue(); + + return true; } public void SetSignal(HThread Thread, int Count) diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs index 2045f8a17..b11160781 100644 --- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs +++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs @@ -183,7 +183,7 @@ namespace Ryujinx.Core.OsHle.Handles TryResumingExecution(SchedThread); } - public void WaitForSignal(HThread Thread, int Timeout = -1) + public bool WaitForSignal(HThread Thread, int Timeout = -1) { SchedulerThread SchedThread; @@ -206,22 +206,26 @@ namespace Ryujinx.Core.OsHle.Handles { Logging.Error($"{GetDbgThreadInfo(Thread)} was not found on the scheduler queue!"); - return; + return false; } } + bool Result; + if (Timeout >= 0) { Logging.Debug($"{GetDbgThreadInfo(Thread)} has wait timeout of {Timeout}ms."); - SchedThread.WaitEvent.WaitOne(Timeout); + Result = SchedThread.WaitEvent.WaitOne(Timeout); } else { - SchedThread.WaitEvent.WaitOne(); + Result = SchedThread.WaitEvent.WaitOne(); } TryResumingExecution(SchedThread); + + return Result; } private void TryResumingExecution(SchedulerThread SchedThread) diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index b745867e9..4b5f9819a 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -278,39 +278,45 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android int RealWidth = FbWidth; int RealHeight = FbHeight; + float XSign = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX) ? -1 : 1; + float YSign = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY) ? -1 : 1; + float ScaleX = 1; float ScaleY = 1; + float OffsX = 0; float OffsY = 0; if (Crop.Right != 0 && Crop.Bottom != 0) { + //Who knows if this is right, I was never good with math... RealWidth = Crop.Right - Crop.Left; RealHeight = Crop.Bottom - Crop.Top; - ScaleX = (float)FbWidth / RealWidth; - ScaleY = (float)FbHeight / RealHeight; + if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90)) + { + ScaleY = (float)FbHeight / RealHeight; + ScaleX = (float)FbWidth / RealWidth; - OffsX = -(float)Crop.Left / Crop.Right; - OffsY = -(float)Crop.Top / Crop.Bottom; + OffsY = ((-(float)Crop.Left / Crop.Right) + ScaleX - 1) * -XSign; + OffsX = ((-(float)Crop.Top / Crop.Bottom) + ScaleY - 1) * -YSign; + } + else + { + ScaleX = (float)FbWidth / RealWidth; + ScaleY = (float)FbHeight / RealHeight; - OffsX += ScaleX - 1; - OffsY += ScaleY - 1; + OffsX = ((-(float)Crop.Left / Crop.Right) + ScaleX - 1) * XSign; + OffsY = ((-(float)Crop.Top / Crop.Bottom) + ScaleY - 1) * -YSign; + } } + ScaleX *= XSign; + ScaleY *= YSign; + float Rotate = 0; - if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX)) - { - ScaleX = -ScaleX; - } - - if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY)) - { - ScaleY = -ScaleY; - } - if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90)) { Rotate = -MathF.PI * 0.5f; diff --git a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs index dec13f75e..2705272a3 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs @@ -53,7 +53,12 @@ namespace Ryujinx.Core.OsHle.Svc Cv = Ns.Os.CondVars.GetOrAdd(CondVarAddress, Cv); - Cv.WaitForSignal(Thread); + if (!Cv.WaitForSignal(Thread)) + { + ThreadState.X0 = (int)SvcResult.ErrTimeout; + + return; + } M.WaitForLock(Thread, ThreadHandle); diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 1e48b2805..4c7cee467 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -29,6 +29,10 @@ namespace Ryujinx { this.Ns = Ns; this.Renderer = Renderer; + + Location = new Point( + (DisplayDevice.Default.Width / 2) - (Width / 2), + (DisplayDevice.Default.Height / 2) - (Height / 2)); } protected override void OnLoad(EventArgs e) From 73cc30cc8015685cdb2b8630492703e16f8b4bd9 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 5 Mar 2018 02:09:52 -0300 Subject: [PATCH 49/67] Allow multiple hid shared memory locations --- Ryujinx.Core/Hid/Hid.cs | 200 ++++++++++++++--------- Ryujinx.Core/OsHle/Handles/HSharedMem.cs | 31 +--- Ryujinx.Core/OsHle/Horizon.cs | 16 +- Ryujinx.Core/Switch.cs | 10 +- 4 files changed, 132 insertions(+), 125 deletions(-) diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs index d7227889a..249747c15 100644 --- a/Ryujinx.Core/Hid/Hid.cs +++ b/Ryujinx.Core/Hid/Hid.cs @@ -1,4 +1,6 @@ using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Handles; +using System; using System.Diagnostics; namespace Ryujinx.Core.Input @@ -60,33 +62,65 @@ namespace Ryujinx.Core.Input private const int HidEntryCount = 17; - private long SharedMemOffset; + private object ShMemLock; - private Switch Ns; + private long[] ShMemPositions; - public Hid(Switch Ns) + private IntPtr Ram; + + public Hid(IntPtr Ram) { - this.Ns = Ns; + this.Ram = Ram; + + ShMemLock = new object(); + + ShMemPositions = new long[0]; } - public void Init(long HidOffset) + internal void ShMemMap(object sender, EventArgs e) { - SharedMemOffset = HidOffset; + HSharedMem SharedMem = (HSharedMem)sender; + lock (ShMemLock) + { + ShMemPositions = SharedMem.GetVirtualPositions(); + + long BasePosition = ShMemPositions[ShMemPositions.Length - 1]; + + Logging.Info($"HID shared memory successfully mapped to 0x{BasePosition:x16}!"); + + Init(BasePosition); + } + } + + internal void ShMemUnmap(object sender, EventArgs e) + { + HSharedMem SharedMem = (HSharedMem)sender; + + lock (ShMemLock) + { + ShMemPositions = SharedMem.GetVirtualPositions(); + } + } + + private void Init(long BasePosition) + { InitializeJoyconPair( + BasePosition, JoyConColor.Body_Neon_Red, JoyConColor.Buttons_Neon_Red, JoyConColor.Body_Neon_Blue, JoyConColor.Buttons_Neon_Blue); } - public void InitializeJoyconPair( + private void InitializeJoyconPair( + long BasePosition, JoyConColor LeftColorBody, JoyConColor LeftColorButtons, JoyConColor RightColorBody, JoyConColor RightColorButtons) { - long BaseControllerOffset = HidControllersOffset + 8 * HidControllerSize; + long BaseControllerOffset = BasePosition + HidControllersOffset + 8 * HidControllerSize; HidControllerType Type = HidControllerType.ControllerType_Handheld | @@ -125,115 +159,123 @@ namespace Ryujinx.Core.Input HidJoystickPosition LeftStick, HidJoystickPosition RightStick) { - long ControllerOffset = HidControllersOffset + (int)ControllerId * HidControllerSize; + lock (ShMemLock) + { + foreach (long Position in ShMemPositions) + { + long ControllerOffset = Position + HidControllersOffset; - ControllerOffset += HidControllerHeaderSize; + ControllerOffset += (int)ControllerId * HidControllerSize; - ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; + ControllerOffset += HidControllerHeaderSize; - long LastEntry = ReadInt64(ControllerOffset + 0x10); + ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; - long CurrEntry = (LastEntry + 1) % HidEntryCount; + long LastEntry = ReadInt64(ControllerOffset + 0x10); - long Timestamp = Stopwatch.GetTimestamp(); + long CurrEntry = (LastEntry + 1) % HidEntryCount; - WriteInt64(ControllerOffset + 0x0, Timestamp); - WriteInt64(ControllerOffset + 0x8, HidEntryCount); - WriteInt64(ControllerOffset + 0x10, CurrEntry); - WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1); + long Timestamp = Stopwatch.GetTimestamp(); - ControllerOffset += HidControllersLayoutHeaderSize; + WriteInt64(ControllerOffset + 0x0, Timestamp); + WriteInt64(ControllerOffset + 0x8, HidEntryCount); + WriteInt64(ControllerOffset + 0x10, CurrEntry); + WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1); - ControllerOffset += CurrEntry * HidControllersInputEntrySize; + ControllerOffset += HidControllersLayoutHeaderSize; - WriteInt64(ControllerOffset + 0x0, Timestamp); - WriteInt64(ControllerOffset + 0x8, Timestamp); + ControllerOffset += CurrEntry * HidControllersInputEntrySize; - WriteInt64(ControllerOffset + 0x10, (uint)Buttons); + WriteInt64(ControllerOffset + 0x0, Timestamp); + WriteInt64(ControllerOffset + 0x8, Timestamp); - WriteInt32(ControllerOffset + 0x18, LeftStick.DX); - WriteInt32(ControllerOffset + 0x1c, LeftStick.DY); + WriteInt64(ControllerOffset + 0x10, (uint)Buttons); - WriteInt64(ControllerOffset + 0x20, RightStick.DX); - WriteInt64(ControllerOffset + 0x24, RightStick.DY); + WriteInt32(ControllerOffset + 0x18, LeftStick.DX); + WriteInt32(ControllerOffset + 0x1c, LeftStick.DY); - WriteInt64(ControllerOffset + 0x28, - (uint)HidControllerConnState.Controller_State_Connected | - (uint)HidControllerConnState.Controller_State_Wired); + WriteInt64(ControllerOffset + 0x20, RightStick.DX); + WriteInt64(ControllerOffset + 0x24, RightStick.DY); + + WriteInt64(ControllerOffset + 0x28, + (uint)HidControllerConnState.Controller_State_Connected | + (uint)HidControllerConnState.Controller_State_Wired); + } + } } public void SetTouchPoints(params HidTouchPoint[] Points) { - long LastEntry = ReadInt64(HidTouchScreenOffset + 0x10); - - long CurrEntry = (LastEntry + 1) % HidEntryCount; - - long Timestamp = Stopwatch.GetTimestamp(); - - WriteInt64(HidTouchScreenOffset + 0x0, Timestamp); - WriteInt64(HidTouchScreenOffset + 0x8, HidEntryCount); - WriteInt64(HidTouchScreenOffset + 0x10, CurrEntry); - WriteInt64(HidTouchScreenOffset + 0x18, HidEntryCount - 1); - WriteInt64(HidTouchScreenOffset + 0x20, Timestamp); - - long TouchEntryOffset = HidTouchScreenOffset + HidTouchHeaderSize; - - long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize; - - long LastTimestamp = ReadInt64(LastEntryOffset); - - TouchEntryOffset += CurrEntry * HidTouchEntrySize; - - WriteInt64(TouchEntryOffset + 0x0, LastTimestamp + 1); - WriteInt64(TouchEntryOffset + 0x8, Points.Length); - - TouchEntryOffset += HidTouchEntryHeaderSize; - - const int Padding = 0; - - int Index = 0; - - foreach (HidTouchPoint Point in Points) + lock (ShMemLock) { - WriteInt64(TouchEntryOffset + 0x0, Timestamp); - WriteInt32(TouchEntryOffset + 0x8, Padding); - WriteInt32(TouchEntryOffset + 0xc, Index++); - WriteInt32(TouchEntryOffset + 0x10, Point.X); - WriteInt32(TouchEntryOffset + 0x14, Point.Y); - WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX); - WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY); - WriteInt32(TouchEntryOffset + 0x20, Point.Angle); - WriteInt32(TouchEntryOffset + 0x24, Padding); + foreach (long Position in ShMemPositions) + { + long TouchScreenOffset = Position + HidTouchScreenOffset; - TouchEntryOffset += HidTouchEntryTouchSize; + long LastEntry = ReadInt64(TouchScreenOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = ReadInt64(TouchScreenOffset) + 1; + + WriteInt64(TouchScreenOffset + 0x0, Timestamp); + WriteInt64(TouchScreenOffset + 0x8, HidEntryCount); + WriteInt64(TouchScreenOffset + 0x10, CurrEntry); + WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1); + WriteInt64(TouchScreenOffset + 0x20, Timestamp); + + long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize; + + long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize; + + TouchEntryOffset += CurrEntry * HidTouchEntrySize; + + WriteInt64(TouchEntryOffset + 0x0, Timestamp); + WriteInt64(TouchEntryOffset + 0x8, Points.Length); + + TouchEntryOffset += HidTouchEntryHeaderSize; + + const int Padding = 0; + + int Index = 0; + + foreach (HidTouchPoint Point in Points) + { + WriteInt64(TouchEntryOffset + 0x0, Timestamp); + WriteInt32(TouchEntryOffset + 0x8, Padding); + WriteInt32(TouchEntryOffset + 0xc, Index++); + WriteInt32(TouchEntryOffset + 0x10, Point.X); + WriteInt32(TouchEntryOffset + 0x14, Point.Y); + WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX); + WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY); + WriteInt32(TouchEntryOffset + 0x20, Point.Angle); + WriteInt32(TouchEntryOffset + 0x24, Padding); + + TouchEntryOffset += HidTouchEntryTouchSize; + } + } } } private unsafe long ReadInt64(long Position) { - Position += SharedMemOffset; - if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return 0; - return *((long*)((byte*)Ns.Ram + Position)); + return *((long*)((byte*)Ram + Position)); } private unsafe void WriteInt32(long Position, int Value) { - Position += SharedMemOffset; - if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return; - *((int*)((byte*)Ns.Ram + Position)) = Value; + *((int*)((byte*)Ram + Position)) = Value; } private unsafe void WriteInt64(long Position, long Value) { - Position += SharedMemOffset; - if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return; - *((long*)((byte*)Ns.Ram + Position)) = Value; + *((long*)((byte*)Ram + Position)) = Value; } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Handles/HSharedMem.cs b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs index 9cd0a0d47..eb173e965 100644 --- a/Ryujinx.Core/OsHle/Handles/HSharedMem.cs +++ b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs @@ -7,8 +7,6 @@ namespace Ryujinx.Core.OsHle.Handles { private List Positions; - public int PositionsCount => Positions.Count; - public EventHandler MemoryMapped; public EventHandler MemoryUnmapped; @@ -37,34 +35,9 @@ namespace Ryujinx.Core.OsHle.Handles } } - public long GetVirtualPosition(int Index) + public long[] GetVirtualPositions() { - lock (Positions) - { - if (Index < 0 || Index >= Positions.Count) - { - throw new ArgumentOutOfRangeException(nameof(Index)); - } - - return Positions[Index]; - } - } - - public bool TryGetLastVirtualPosition(out long Position) - { - lock (Positions) - { - if (Positions.Count > 0) - { - Position = Positions[Positions.Count - 1]; - - return true; - } - - Position = 0; - - return false; - } + return Positions.ToArray(); } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs index c23891439..a8f5df7c9 100644 --- a/Ryujinx.Core/OsHle/Horizon.cs +++ b/Ryujinx.Core/OsHle/Horizon.cs @@ -27,7 +27,7 @@ namespace Ryujinx.Core.OsHle private ConcurrentDictionary Processes; - private HSharedMem HidSharedMem; + internal HSharedMem HidSharedMem; private Switch Ns; @@ -49,8 +49,6 @@ namespace Ryujinx.Core.OsHle HidSharedMem = new HSharedMem(); - HidSharedMem.MemoryMapped += HidInit; - HidHandle = Handles.GenerateId(HidSharedMem); FontHandle = Handles.GenerateId(new HSharedMem()); @@ -166,17 +164,5 @@ namespace Ryujinx.Core.OsHle Handles.Delete(Handle); } - - private void HidInit(object sender, EventArgs e) - { - HSharedMem SharedMem = (HSharedMem)sender; - - if (SharedMem.TryGetLastVirtualPosition(out long Position)) - { - Logging.Info($"HID shared memory successfully mapped to 0x{Position:x16}!"); - - Ns.Hid.Init(Position); - } - } } } \ No newline at end of file diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index 6f41da814..3f7b1e2b8 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -27,10 +27,16 @@ namespace Ryujinx.Core Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); Gpu = new NsGpu(Renderer); + VFs = new VirtualFs(); - Hid = new Hid(this); - Os = new Horizon(this); + Hid = new Hid(Ram); + + Os = new Horizon(this); + + Os.HidSharedMem.MemoryMapped += Hid.ShMemMap; + Os.HidSharedMem.MemoryUnmapped += Hid.ShMemUnmap; + Settings = new SetSys(); } From c9ef25681dc05ff87c6fb7d0da9d555964e201c1 Mon Sep 17 00:00:00 2001 From: MS-DOS1999 Date: Mon, 5 Mar 2018 13:21:19 +0100 Subject: [PATCH 50/67] Add Frintx_S, ASRV test, update ADCS, use Assert.Multiple and indent (#44) * add 'ADC 32bit and Overflow' test * Add WZR/WSP tests * fix ADC and ADDS * add ADCS test * add SBCS test * indent my code and delete comment * '/' <- i hate you x) * remove spacebar char * remove false tab * add frintx_S test * update frintx_S test * add ASRV test * fix new line * fix PR * fix indent --- Ryujinx.Tests/Cpu/CpuTest.cs | 7 +- Ryujinx.Tests/Cpu/CpuTestAlu.cs | 111 ++++++++++++++------- Ryujinx.Tests/Cpu/CpuTestMisc.cs | 7 +- Ryujinx.Tests/Cpu/CpuTestScalar.cs | 6 +- Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs | 78 +++++++++++++++ 5 files changed, 165 insertions(+), 44 deletions(-) create mode 100644 Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index a56eeb728..a4a3b33fc 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -57,7 +57,7 @@ namespace Ryujinx.Tests.Cpu protected void SetThreadState(ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X31 = 0, AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec), - bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false) + bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false, int Fpcr = 0x0) { Thread.ThreadState.X0 = X0; Thread.ThreadState.X1 = X1; @@ -70,6 +70,7 @@ namespace Ryujinx.Tests.Cpu Thread.ThreadState.Carry = Carry; Thread.ThreadState.Zero = Zero; Thread.ThreadState.Negative = Negative; + Thread.ThreadState.Fpcr = Fpcr; } protected void ExecuteOpcodes() @@ -92,12 +93,12 @@ namespace Ryujinx.Tests.Cpu protected AThreadState SingleOpcode(uint Opcode, ulong X0 = 0, ulong X1 = 0, ulong X2 = 0, ulong X31 = 0, AVec V0 = default(AVec), AVec V1 = default(AVec), AVec V2 = default(AVec), - bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false) + bool Overflow = false, bool Carry = false, bool Zero = false, bool Negative = false, int Fpcr = 0x0) { this.Opcode(Opcode); this.Opcode(0xD4200000); // BRK #0 this.Opcode(0xD65F03C0); // RET - SetThreadState(X0, X1, X2, X31, V0, V1, V2, Overflow, Carry, Zero, Negative); + SetThreadState(X0, X1, X2, X31, V0, V1, V2, Overflow, Carry, Zero, Negative, Fpcr); ExecuteOpcodes(); return GetThreadState(); diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu.cs b/Ryujinx.Tests/Cpu/CpuTestAlu.cs index 0445c97ab..8116fc7c7 100644 --- a/Ryujinx.Tests/Cpu/CpuTestAlu.cs +++ b/Ryujinx.Tests/Cpu/CpuTestAlu.cs @@ -17,20 +17,24 @@ namespace Ryujinx.Tests.Cpu Assert.AreEqual(Result, ThreadState.X0); } - [TestCase(0x3A020020u, 2u, 3u, false, false, false, 5u)] - [TestCase(0x3A020020u, 2u, 3u, true, false, false, 6u)] - [TestCase(0xBA020020u, 2u, 3u, false, false, false, 5u)] - [TestCase(0xBA020020u, 2u, 3u, true, false, false, 6u)] - [TestCase(0x3A020020u, 0xFFFFFFFEu, 0x1u, true, true, true, 0x0u)] - public void Adcs(uint Opcode, uint A, uint B, bool CarryState, bool Zero, bool Carry, uint Result) + [TestCase(0x3A020020u, 2u, 3u, false, false, false, false, 5u)] + [TestCase(0x3A020020u, 2u, 3u, true, false, false, false, 6u)] + [TestCase(0xBA020020u, 2u, 3u, false, false, false, false, 5u)] + [TestCase(0xBA020020u, 2u, 3u, true, false, false, false, 6u)] + [TestCase(0x3A020020u, 0xFFFFFFFEu, 0x1u, true, false, true, true, 0x0u)] + [TestCase(0x3A020020u, 0xFFFFFFFFu, 0xFFFFFFFFu, true, true, false, true, 0xFFFFFFFFu)] + public void Adcs(uint Opcode, uint A, uint B, bool CarryState, bool Negative, bool Zero, bool Carry, uint Result) { //ADCS (X0/W0), (X1, W1), (X2/W2) AThreadState ThreadState = SingleOpcode(Opcode, X1: A, X2: B, Carry: CarryState); - Assert.IsFalse(ThreadState.Negative); - Assert.IsFalse(ThreadState.Overflow); - Assert.AreEqual(Zero, ThreadState.Zero); - Assert.AreEqual(Carry, ThreadState.Carry); - Assert.AreEqual(Result, ThreadState.X0); + Assert.Multiple(() => + { + Assert.IsFalse(ThreadState.Overflow); + Assert.AreEqual(Negative, ThreadState.Negative); + Assert.AreEqual(Zero, ThreadState.Zero); + Assert.AreEqual(Carry, ThreadState.Carry); + Assert.AreEqual(Result, ThreadState.X0); + }); } [Test] @@ -50,11 +54,14 @@ namespace Ryujinx.Tests.Cpu { //ADDS WZR, WSP, #5 AThreadState ThreadState = SingleOpcode(0x310017FF, X31: A); - Assert.IsFalse(ThreadState.Negative); - Assert.AreEqual(Zero, ThreadState.Zero); - Assert.AreEqual(Carry, ThreadState.Carry); - Assert.IsFalse(ThreadState.Overflow); - Assert.AreEqual(A, ThreadState.X31); + Assert.Multiple(() => + { + Assert.IsFalse(ThreadState.Negative); + Assert.IsFalse(ThreadState.Overflow); + Assert.AreEqual(Zero, ThreadState.Zero); + Assert.AreEqual(Carry, ThreadState.Carry); + Assert.AreEqual(A, ThreadState.X31); + }); } [TestCase(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFul, true, false)] @@ -65,26 +72,55 @@ namespace Ryujinx.Tests.Cpu // ANDS W0, W1, W2 uint Opcode = 0x6A020020; AThreadState ThreadState = SingleOpcode(Opcode, X1: A, X2: B); - Assert.AreEqual(Result, ThreadState.X0); - Assert.AreEqual(Negative, ThreadState.Negative); - Assert.AreEqual(Zero, ThreadState.Zero); + Assert.Multiple(() => + { + Assert.AreEqual(Result, ThreadState.X0); + Assert.AreEqual(Negative, ThreadState.Negative); + Assert.AreEqual(Zero, ThreadState.Zero); + }); } - [Test] - public void OrrBitmasks() + [TestCase(0x0000FF44u, 0x00000004u, 0x00000FF4u)] + [TestCase(0x00000000u, 0x00000004u, 0x00000000u)] + [TestCase(0x0000FF44u, 0x00000008u, 0x000000FFu)] + [TestCase(0xFFFFFFFFu, 0x00000004u, 0xFFFFFFFFu)] + [TestCase(0xFFFFFFFFu, 0x00000008u, 0xFFFFFFFFu)] + [TestCase(0xFFFFFFFFu, 0x00000020u, 0xFFFFFFFFu)] + [TestCase(0x0FFFFFFFu, 0x0000001Cu, 0x00000000u)] + [TestCase(0x80000000u, 0x0000001Fu, 0xFFFFFFFFu)] + [TestCase(0xCAFE0000u, 0x00000020u, 0xCAFE0000u)] + public void Asrv32(uint A, uint ShiftValue, uint Result) { - // ORR W0, WZR, #0x01010101 - Assert.AreEqual(0x01010101, SingleOpcode(0x3200C3E0).X0); + // ASRV W0, W1, W2 + AThreadState ThreadState = SingleOpcode(0x1AC22820, X1: A, X2: ShiftValue); + Assert.AreEqual(Result, ThreadState.X0); + } - Reset(); + [TestCase(0x000000000000FF44ul, 0x00000004u, 0x0000000000000FF4ul)] + [TestCase(0x0000000000000000ul, 0x00000004u, 0x0000000000000000ul)] + [TestCase(0x000000000000FF44ul, 0x00000008u, 0x00000000000000FFul)] + [TestCase(0x00000000FFFFFFFFul, 0x00000004u, 0x000000000FFFFFFFul)] + [TestCase(0x00000000FFFFFFFFul, 0x00000008u, 0x0000000000FFFFFFul)] + [TestCase(0x00000000FFFFFFFFul, 0x00000020u, 0x0000000000000000ul)] + [TestCase(0x000000000FFFFFFFul, 0x0000001Cu, 0x0000000000000000ul)] + [TestCase(0x000CC4488FFFFFFFul, 0x0000001Cu, 0x0000000000CC4488ul)] + [TestCase(0xFFFFFFFFFFFFFFFFul, 0x0000001Cu, 0xFFFFFFFFFFFFFFFFul)] + [TestCase(0x8000000000000000ul, 0x0000003Fu, 0xFFFFFFFFFFFFFFFFul)] + [TestCase(0xCAFE000000000000ul, 0x00000040u, 0xCAFE000000000000ul)] + public void Asrv64(ulong A, uint ShiftValue, ulong Result) + { + // ASRV X0, X1, X2 + AThreadState ThreadState = SingleOpcode(0x9AC22820, X1: A, X2: ShiftValue); + Assert.AreEqual(Result, ThreadState.X0); + } - // ORR W1, WZR, #0x00F000F0 - Assert.AreEqual(0x00F000F0, SingleOpcode(0x320C8FE1).X1); - - Reset(); - - // ORR W2, WZR, #1 - Assert.AreEqual(0x00000001, SingleOpcode(0x320003E2).X2); + [TestCase(0x01010101u, 0x3200C3E2u)] + [TestCase(0x00F000F0u, 0x320C8FE2u)] + [TestCase(0x00000001u, 0x320003E2u)] + public void OrrBitmasks(uint Bitmask, uint Opcode) + { + // ORR W2, WZR, #Bitmask + Assert.AreEqual(Bitmask, SingleOpcode(Opcode).X2); } [Test] @@ -113,11 +149,14 @@ namespace Ryujinx.Tests.Cpu { //SBCS (X0/W0), (X1, W1), (X2/W2) AThreadState ThreadState = SingleOpcode(Opcode, X1: A, X2: B, Carry: CarryState); - Assert.AreEqual(Negative, ThreadState.Negative); - Assert.IsFalse(ThreadState.Overflow); - Assert.AreEqual(Zero, ThreadState.Zero); - Assert.AreEqual(Carry, ThreadState.Carry); - Assert.AreEqual(Result, ThreadState.X0); + Assert.Multiple(() => + { + Assert.IsFalse(ThreadState.Overflow); + Assert.AreEqual(Negative, ThreadState.Negative); + Assert.AreEqual(Zero, ThreadState.Zero); + Assert.AreEqual(Carry, ThreadState.Carry); + Assert.AreEqual(Result, ThreadState.X0); + }); } } } diff --git a/Ryujinx.Tests/Cpu/CpuTestMisc.cs b/Ryujinx.Tests/Cpu/CpuTestMisc.cs index 97947b9a9..3a995fe26 100644 --- a/Ryujinx.Tests/Cpu/CpuTestMisc.cs +++ b/Ryujinx.Tests/Cpu/CpuTestMisc.cs @@ -197,8 +197,11 @@ namespace Ryujinx.Tests.Cpu Opcode(0xD4200000); Opcode(0xD65F03C0); ExecuteOpcodes(); - Assert.AreEqual(0, GetThreadState().X0); - Assert.IsTrue(GetThreadState().Zero); + Assert.Multiple(() => + { + Assert.AreEqual(0, GetThreadState().X0); + Assert.IsTrue(GetThreadState().Zero); + }); } [Test] diff --git a/Ryujinx.Tests/Cpu/CpuTestScalar.cs b/Ryujinx.Tests/Cpu/CpuTestScalar.cs index ffe01a299..a178be272 100644 --- a/Ryujinx.Tests/Cpu/CpuTestScalar.cs +++ b/Ryujinx.Tests/Cpu/CpuTestScalar.cs @@ -14,9 +14,9 @@ namespace Ryujinx.Tests.Cpu [TestCase(0x7F7FFFFFu, 0x807FFFFFu, 0x7F7FFFFFu)] [TestCase(0x7FC00000u, 0x3F800000u, 0x7FC00000u)] [TestCase(0x3F800000u, 0x7FC00000u, 0x7FC00000u)] - [TestCase(0x7F800001u, 0x7FC00042u, 0x7FC00001u, Ignore = "NaN test.")] - [TestCase(0x7FC00042u, 0x7F800001u, 0x7FC00001u, Ignore = "NaN test.")] - [TestCase(0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Au, Ignore = "NaN test.")] + [TestCase(0x7F800001u, 0x7FC00042u, 0x7FC00001u)] + [TestCase(0x7FC00042u, 0x7F800001u, 0x7FC00001u)] + [TestCase(0x7FC0000Au, 0x7FC0000Bu, 0x7FC0000Au)] public void Fmax_S(uint A, uint B, uint Result) { // FMAX S0, S1, S2 diff --git a/Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs b/Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs new file mode 100644 index 000000000..56aaef488 --- /dev/null +++ b/Ryujinx.Tests/Cpu/CpuTestSimdArithmetic.cs @@ -0,0 +1,78 @@ +using ChocolArm64.State; +using NUnit.Framework; + +namespace Ryujinx.Tests.Cpu +{ + public class CpuTestSimdArithmetic : CpuTest + { + [TestCase(0x3FE66666u, 'N', false, 0x40000000u)] + [TestCase(0x3F99999Au, 'N', false, 0x3F800000u)] + [TestCase(0x404CCCCDu, 'P', false, 0x40800000u)] + [TestCase(0x40733333u, 'P', false, 0x40800000u)] + [TestCase(0x404CCCCDu, 'M', false, 0x40400000u)] + [TestCase(0x40733333u, 'M', false, 0x40400000u)] + [TestCase(0x3F99999Au, 'Z', false, 0x3F800000u)] + [TestCase(0x3FE66666u, 'Z', false, 0x3F800000u)] + [TestCase(0x00000000u, 'N', false, 0x00000000u)] + [TestCase(0x00000000u, 'P', false, 0x00000000u)] + [TestCase(0x00000000u, 'M', false, 0x00000000u)] + [TestCase(0x00000000u, 'Z', false, 0x00000000u)] + [TestCase(0x80000000u, 'N', false, 0x80000000u)] + [TestCase(0x80000000u, 'P', false, 0x80000000u)] + [TestCase(0x80000000u, 'M', false, 0x80000000u)] + [TestCase(0x80000000u, 'Z', false, 0x80000000u)] + [TestCase(0x7F800000u, 'N', false, 0x7F800000u)] + [TestCase(0x7F800000u, 'P', false, 0x7F800000u)] + [TestCase(0x7F800000u, 'M', false, 0x7F800000u)] + [TestCase(0x7F800000u, 'Z', false, 0x7F800000u)] + [TestCase(0xFF800000u, 'N', false, 0xFF800000u)] + [TestCase(0xFF800000u, 'P', false, 0xFF800000u)] + [TestCase(0xFF800000u, 'M', false, 0xFF800000u)] + [TestCase(0xFF800000u, 'Z', false, 0xFF800000u)] + [TestCase(0xFF800001u, 'N', false, 0xFFC00001u)] + [TestCase(0xFF800001u, 'P', false, 0xFFC00001u)] + [TestCase(0xFF800001u, 'M', false, 0xFFC00001u)] + [TestCase(0xFF800001u, 'Z', false, 0xFFC00001u)] + [TestCase(0xFF800001u, 'N', true, 0x7FC00000u)] + [TestCase(0xFF800001u, 'P', true, 0x7FC00000u)] + [TestCase(0xFF800001u, 'M', true, 0x7FC00000u)] + [TestCase(0xFF800001u, 'Z', true, 0x7FC00000u)] + [TestCase(0x7FC00002u, 'N', false, 0x7FC00002u)] + [TestCase(0x7FC00002u, 'P', false, 0x7FC00002u)] + [TestCase(0x7FC00002u, 'M', false, 0x7FC00002u)] + [TestCase(0x7FC00002u, 'Z', false, 0x7FC00002u)] + [TestCase(0x7FC00002u, 'N', true, 0x7FC00000u)] + [TestCase(0x7FC00002u, 'P', true, 0x7FC00000u)] + [TestCase(0x7FC00002u, 'M', true, 0x7FC00000u)] + [TestCase(0x7FC00002u, 'Z', true, 0x7FC00000u)] + public void Frintx_S(uint A, char RoundType, bool DefaultNaN, uint Result) + { + int FpcrTemp = 0x0; + switch(RoundType) + { + case 'N': + FpcrTemp = 0x0; + break; + + case 'P': + FpcrTemp = 0x400000; + break; + + case 'M': + FpcrTemp = 0x800000; + break; + + case 'Z': + FpcrTemp = 0xC00000; + break; + } + if(DefaultNaN) + { + FpcrTemp |= 1 << 25; + } + AVec V1 = new AVec { X0 = A }; + AThreadState ThreadState = SingleOpcode(0x1E274020, V1: V1, Fpcr: FpcrTemp); + Assert.AreEqual(Result, ThreadState.V0.X0); + } + } +} From 0e343a748d9dcfe50b885b8c0c5e886bc44080ac Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 5 Mar 2018 12:58:19 -0300 Subject: [PATCH 51/67] Add FCVTL and FCVTN instruction (no Half support yet), stub SvcClearEvent --- ChocolArm64/AOpCodeTable.cs | 2 + ChocolArm64/Instruction/AInstEmitSimdCvt.cs | 60 +++++++++++++++++++++ Ryujinx.Core/OsHle/Svc/SvcHandler.cs | 1 + Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 9 ++++ 4 files changed, 72 insertions(+) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index e192f5ec5..5db495af9 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -161,8 +161,10 @@ namespace ChocolArm64 Set("000111100x10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd)); Set("x00111100x100100000000xxxxxxxxxx", AInstEmit.Fcvtas_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x100101000000xxxxxxxxxx", AInstEmit.Fcvtau_Gp, typeof(AOpCodeSimdCvt)); + Set("0x0011100x100001011110xxxxxxxxxx", AInstEmit.Fcvtl_V, typeof(AOpCodeSimd)); Set("x00111100x110000000000xxxxxxxxxx", AInstEmit.Fcvtms_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x110001000000xxxxxxxxxx", AInstEmit.Fcvtmu_Gp, typeof(AOpCodeSimdCvt)); + Set("0x0011100x100001011010xxxxxxxxxx", AInstEmit.Fcvtn_V, typeof(AOpCodeSimd)); Set("x00111100x101000000000xxxxxxxxxx", AInstEmit.Fcvtps_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x101001000000xxxxxxxxxx", AInstEmit.Fcvtpu_Gp, typeof(AOpCodeSimdCvt)); Set("x00111100x111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_Gp, typeof(AOpCodeSimdCvt)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs index 688f05a20..e97027777 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs @@ -31,6 +31,36 @@ namespace ChocolArm64.Instruction EmitFcvt_u_Gp(Context, () => EmitRoundMathCall(Context, MidpointRounding.AwayFromZero)); } + public static void Fcvtl_V(AILEmitterCtx Context) + { + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + + int SizeF = Op.Size & 1; + + int Elems = 4 >> SizeF; + + int Part = Context.CurrOp.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; + + for (int Index = 0; Index < Elems; Index++) + { + if (SizeF == 0) + { + //TODO: This need the half precision floating point type, + //that is not yet supported on .NET. We should probably + //do our own implementation on the meantime. + throw new NotImplementedException(); + } + else /* if (SizeF == 1) */ + { + EmitVectorExtractF(Context, Op.Rn, Part + Index, 0); + + Context.Emit(OpCodes.Conv_R8); + } + + EmitVectorInsertF(Context, Op.Rd, Index, SizeF); + } + } + public static void Fcvtms_Gp(AILEmitterCtx Context) { EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor))); @@ -41,6 +71,36 @@ namespace ChocolArm64.Instruction EmitFcvt_u_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Floor))); } + public static void Fcvtn_V(AILEmitterCtx Context) + { + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + + int SizeF = Op.Size & 1; + + int Elems = 4 >> SizeF; + + int Part = Context.CurrOp.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; + + for (int Index = 0; Index < Elems; Index++) + { + EmitVectorExtractF(Context, Op.Rd, Index, SizeF); + + if (SizeF == 0) + { + //TODO: This need the half precision floating point type, + //that is not yet supported on .NET. We should probably + //do our own implementation on the meantime. + throw new NotImplementedException(); + } + else /* if (SizeF == 1) */ + { + Context.Emit(OpCodes.Conv_R4); + + EmitVectorInsertF(Context, Op.Rd, Part + Index, 0); + } + } + } + public static void Fcvtps_Gp(AILEmitterCtx Context) { EmitFcvt_s_Gp(Context, () => EmitUnaryMathCall(Context, nameof(Math.Ceiling))); diff --git a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs index 212d30a6c..b3e6262db 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs @@ -36,6 +36,7 @@ namespace Ryujinx.Core.OsHle.Svc { 0x0c, SvcGetThreadPriority }, { 0x0d, SvcSetThreadPriority }, { 0x0f, SvcSetThreadCoreMask }, + { 0x12, SvcClearEvent }, { 0x13, SvcMapSharedMemory }, { 0x14, SvcUnmapSharedMemory }, { 0x15, SvcCreateTransferMemory }, diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index 51b2e26c6..d0459f2f2 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -20,6 +20,15 @@ namespace Ryujinx.Core.OsHle.Svc Ns.Os.ExitProcess(ThreadState.ProcessId); } + private void SvcClearEvent(AThreadState ThreadState) + { + int Handle = (int)ThreadState.X0; + + //TODO: Implement events. + + ThreadState.X0 = (int)SvcResult.Success; + } + private void SvcCloseHandle(AThreadState ThreadState) { int Handle = (int)ThreadState.X0; From 59d1b2ad83385dad49cf930e826ce0693b9cee2c Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 5 Mar 2018 16:18:37 -0300 Subject: [PATCH 52/67] Add MUL (vector by element), fix FCVTN, make svcs use MakeError too --- ChocolArm64/AOpCodeTable.cs | 5 +- ChocolArm64/Decoder/AOpCodeSimdReg.cs | 6 +- ChocolArm64/Decoder/AOpCodeSimdRegElem.cs | 26 +++++-- ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs | 22 ++++++ .../Instruction/AInstEmitSimdArithmetic.cs | 5 ++ ChocolArm64/Instruction/AInstEmitSimdCvt.cs | 5 ++ .../Instruction/AInstEmitSimdHelper.cs | 76 +++++++++++++++---- Ryujinx.Core/OsHle/ErrorCode.cs | 10 +++ .../OsHle/{Services => }/ErrorModule.cs | 2 +- Ryujinx.Core/OsHle/KernelErr.cs | 11 +++ Ryujinx.Core/OsHle/Services/ErrorCode.cs | 10 --- .../OsHle/Services/FspSrv/IFileSystem.cs | 2 +- Ryujinx.Core/OsHle/Svc/SvcMemory.cs | 23 +++--- Ryujinx.Core/OsHle/Svc/SvcResult.cs | 11 --- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 22 +++--- Ryujinx.Core/OsHle/Svc/SvcThread.cs | 12 +-- Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs | 12 +-- 17 files changed, 180 insertions(+), 80 deletions(-) create mode 100644 ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs create mode 100644 Ryujinx.Core/OsHle/ErrorCode.cs rename Ryujinx.Core/OsHle/{Services => }/ErrorModule.cs (98%) create mode 100644 Ryujinx.Core/OsHle/KernelErr.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ErrorCode.cs delete mode 100644 Ryujinx.Core/OsHle/Svc/SvcResult.cs diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 5db495af9..6b250b4b0 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -183,7 +183,7 @@ namespace ChocolArm64 Set("000111100x1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg)); Set("000111100x1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg)); Set("0>0011100<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg)); - Set("0x0011111<1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); - Set("0x0011111<> 11) & 1; - } - else - { - Index = (OpCode >> 21) & 1 | - (OpCode >> 10) & 2; + case 1: + Index = (OpCode >> 21) & 1 | + (OpCode >> 10) & 2 | + (OpCode >> 18) & 4; + + Rm &= 0xf; + + break; + + case 2: + Index = (OpCode >> 21) & 1 | + (OpCode >> 10) & 2; + + break; + + default: Emitter = AInstEmit.Und; return; } + + } } } \ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs b/ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs new file mode 100644 index 000000000..e61d7093a --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdRegElemF.cs @@ -0,0 +1,22 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdRegElemF : AOpCodeSimdReg + { + public int Index { get; private set; } + + public AOpCodeSimdRegElemF(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + if ((Size & 1) != 0) + { + Index = (OpCode >> 11) & 1; + } + else + { + Index = (OpCode >> 21) & 1 | + (OpCode >> 10) & 2; + } + } + } +} \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index 9c1bc2862..9f5cc64f4 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -341,6 +341,11 @@ namespace ChocolArm64.Instruction EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul)); } + public static void Mul_Ve(AILEmitterCtx Context) + { + EmitVectorBinaryOpByElemZx(Context, () => Context.Emit(OpCodes.Mul)); + } + public static void Neg_V(AILEmitterCtx Context) { EmitVectorUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs index e97027777..b9944e565 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdCvt.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdCvt.cs @@ -99,6 +99,11 @@ namespace ChocolArm64.Instruction EmitVectorInsertF(Context, Op.Rd, Part + Index, 0); } } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } } public static void Fcvtps_Gp(AILEmitterCtx Context) diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs index 68ee3d3e4..33e4d5487 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs @@ -200,20 +200,6 @@ namespace ChocolArm64.Instruction EmitVectorOpF(Context, Emit, OperFlags.RdRnRm); } - public static void EmitVectorBinaryOpByElemF(AILEmitterCtx Context, Action Emit) - { - AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; - - EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: false); - } - - public static void EmitVectorTernaryOpByElemF(AILEmitterCtx Context, Action Emit) - { - AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; - - EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: true); - } - public static void EmitVectorOpF(AILEmitterCtx Context, Action Emit, OperFlags Opers) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; @@ -250,6 +236,20 @@ namespace ChocolArm64.Instruction } } + public static void EmitVectorBinaryOpByElemF(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp; + + EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: false); + } + + public static void EmitVectorTernaryOpByElemF(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp; + + EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: true); + } + public static void EmitVectorOpByElemF(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; @@ -341,6 +341,54 @@ namespace ChocolArm64.Instruction } } + public static void EmitVectorBinaryOpByElemSx(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; + + EmitVectorOpByElem(Context, Emit, Op.Index, false, true); + } + + public static void EmitVectorBinaryOpByElemZx(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; + + EmitVectorOpByElem(Context, Emit, Op.Index, false, false); + } + + public static void EmitVectorTernaryOpByElemZx(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; + + EmitVectorOpByElem(Context, Emit, Op.Index, true, false); + } + + public static void EmitVectorOpByElem(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary, bool Signed) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + for (int Index = 0; Index < (Bytes >> Op.Size); Index++) + { + if (Ternary) + { + EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed); + } + + EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed); + EmitVectorExtract(Context, Op.Rm, Index, Op.Size, Signed); + + Emit(); + + EmitVectorInsert(Context, Op.Rd, Index, Op.Size); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + public static void EmitVectorImmUnaryOp(AILEmitterCtx Context, Action Emit) { EmitVectorImmOp(Context, Emit, false); diff --git a/Ryujinx.Core/OsHle/ErrorCode.cs b/Ryujinx.Core/OsHle/ErrorCode.cs new file mode 100644 index 000000000..4210b2300 --- /dev/null +++ b/Ryujinx.Core/OsHle/ErrorCode.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.Core.OsHle +{ + static class ErrorCode + { + public static uint MakeError(ErrorModule Module, int Code) + { + return (uint)Module | ((uint)Code << 9); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ErrorModule.cs b/Ryujinx.Core/OsHle/ErrorModule.cs similarity index 98% rename from Ryujinx.Core/OsHle/Services/ErrorModule.cs rename to Ryujinx.Core/OsHle/ErrorModule.cs index 78af6195d..f23e8d270 100644 --- a/Ryujinx.Core/OsHle/Services/ErrorModule.cs +++ b/Ryujinx.Core/OsHle/ErrorModule.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Core.OsHle.IpcServices +namespace Ryujinx.Core.OsHle { enum ErrorModule { diff --git a/Ryujinx.Core/OsHle/KernelErr.cs b/Ryujinx.Core/OsHle/KernelErr.cs new file mode 100644 index 000000000..19983af19 --- /dev/null +++ b/Ryujinx.Core/OsHle/KernelErr.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.Core.OsHle +{ + static class KernelErr + { + public const int InvalidMemRange = 110; + public const int InvalidHandle = 114; + public const int Timeout = 117; + public const int InvalidInfo = 120; + public const int InvalidIpcReq = 123; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ErrorCode.cs b/Ryujinx.Core/OsHle/Services/ErrorCode.cs deleted file mode 100644 index a4e197b22..000000000 --- a/Ryujinx.Core/OsHle/Services/ErrorCode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Core.OsHle.IpcServices -{ - static class ErrorCode - { - public static long MakeError(ErrorModule Module, int Code) - { - return (int)Module | (Code << 9); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs index 569a7dd6b..62bcb8e8b 100644 --- a/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Text; -using static Ryujinx.Core.OsHle.IpcServices.ErrorCode; +using static Ryujinx.Core.OsHle.ErrorCode; using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; namespace Ryujinx.Core.OsHle.IpcServices.FspSrv diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index 6969d3793..1bb3011b8 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -2,6 +2,8 @@ using ChocolArm64.Memory; using ChocolArm64.State; using Ryujinx.Core.OsHle.Handles; +using static Ryujinx.Core.OsHle.ErrorCode; + namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler @@ -23,7 +25,7 @@ namespace Ryujinx.Core.OsHle.Svc CurrentHeapSize = Size; - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; ThreadState.X1 = (ulong)Position; } @@ -44,7 +46,7 @@ namespace Ryujinx.Core.OsHle.Svc Memory.Manager.SetAttrBit(Position, Size, 3); } - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcMapMemory(AThreadState ThreadState) @@ -61,7 +63,7 @@ namespace Ryujinx.Core.OsHle.Svc Memory.Manager.SetAttrBit(Src, Size, 0); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcUnmapMemory(AThreadState ThreadState) @@ -78,7 +80,7 @@ namespace Ryujinx.Core.OsHle.Svc Memory.Manager.ClearAttrBit(Src, Size, 0); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcQueryMemory(AThreadState ThreadState) @@ -86,12 +88,13 @@ namespace Ryujinx.Core.OsHle.Svc long InfoPtr = (long)ThreadState.X0; long Position = (long)ThreadState.X2; + Position &= uint.MaxValue; + AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position); if (MapInfo == null) { - //TODO: Correct error code. - ThreadState.X0 = ulong.MaxValue; + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); return; } @@ -106,7 +109,7 @@ namespace Ryujinx.Core.OsHle.Svc Memory.WriteInt32(InfoPtr + 0x24, 0); //TODO: X1. - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; ThreadState.X1 = 0; } @@ -127,7 +130,7 @@ namespace Ryujinx.Core.OsHle.Svc Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } //TODO: Error codes. @@ -143,7 +146,7 @@ namespace Ryujinx.Core.OsHle.Svc if (HndData != null) { - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } //TODO: Error codes. @@ -164,7 +167,7 @@ namespace Ryujinx.Core.OsHle.Svc int Handle = Ns.Os.Handles.GenerateId(HndData); ThreadState.X1 = (ulong)Handle; - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Svc/SvcResult.cs b/Ryujinx.Core/OsHle/Svc/SvcResult.cs deleted file mode 100644 index a5be9a945..000000000 --- a/Ryujinx.Core/OsHle/Svc/SvcResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Ryujinx.Core.OsHle.Svc -{ - enum SvcResult - { - Success = 0, - ErrBadHandle = 0xe401, - ErrTimeout = 0xea01, - ErrBadInfo = 0xf001, - ErrBadIpcReq = 0xf601 - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index d0459f2f2..8a0a39175 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -7,6 +7,8 @@ using Ryujinx.Core.OsHle.IpcServices; using System; using System.Threading; +using static Ryujinx.Core.OsHle.ErrorCode; + namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler @@ -26,7 +28,7 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Implement events. - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcCloseHandle(AThreadState ThreadState) @@ -35,7 +37,7 @@ namespace Ryujinx.Core.OsHle.Svc Ns.Os.CloseHandle(Handle); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcResetSignal(AThreadState ThreadState) @@ -44,7 +46,7 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Implement events. - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcWaitSynchronization(AThreadState ThreadState) @@ -60,7 +62,7 @@ namespace Ryujinx.Core.OsHle.Svc Process.Scheduler.Suspend(CurrThread.ProcessorId); Process.Scheduler.Resume(CurrThread); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcGetSystemTick(AThreadState ThreadState) @@ -81,7 +83,7 @@ namespace Ryujinx.Core.OsHle.Svc HSession Session = new HSession(ServiceFactory.MakeService(Name)); ThreadState.X1 = (ulong)Ns.Os.Handles.GenerateId(Session); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcSendSyncRequest(AThreadState ThreadState) @@ -127,11 +129,11 @@ namespace Ryujinx.Core.OsHle.Svc byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } else { - ThreadState.X0 = (int)SvcResult.ErrBadIpcReq; + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidIpcReq); } Thread.Yield(); @@ -157,7 +159,7 @@ namespace Ryujinx.Core.OsHle.Svc Logging.Info($"SvcOutputDebugString: {Str}"); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcGetInfo(AThreadState ThreadState) @@ -171,7 +173,7 @@ namespace Ryujinx.Core.OsHle.Svc if (InfoType == 18 || InfoType == 19) { - ThreadState.X0 = (int)SvcResult.ErrBadInfo; + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidInfo); return; } @@ -233,7 +235,7 @@ namespace Ryujinx.Core.OsHle.Svc default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}"); } - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } } } diff --git a/Ryujinx.Core/OsHle/Svc/SvcThread.cs b/Ryujinx.Core/OsHle/Svc/SvcThread.cs index cc0f980be..6afd2e610 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcThread.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThread.cs @@ -28,7 +28,7 @@ namespace Ryujinx.Core.OsHle.Svc Priority, ProcessorId); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; ThreadState.X1 = (ulong)Handle; } @@ -45,7 +45,7 @@ namespace Ryujinx.Core.OsHle.Svc { Process.Scheduler.StartThread(Thread); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } //TODO: Error codes. @@ -75,8 +75,8 @@ namespace Ryujinx.Core.OsHle.Svc if (Thread != null) { + ThreadState.X0 = 0; ThreadState.X1 = (ulong)Thread.Priority; - ThreadState.X0 = (int)SvcResult.Success; } //TODO: Error codes. @@ -93,7 +93,7 @@ namespace Ryujinx.Core.OsHle.Svc { Thread.Priority = Prio; - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } //TODO: Error codes. @@ -101,7 +101,7 @@ namespace Ryujinx.Core.OsHle.Svc private void SvcSetThreadCoreMask(AThreadState ThreadState) { - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; //TODO: Error codes. } @@ -114,8 +114,8 @@ namespace Ryujinx.Core.OsHle.Svc if (Thread != null) { + ThreadState.X0 = 0; ThreadState.X1 = (ulong)Thread.ThreadId; - ThreadState.X0 = (int)SvcResult.Success; } //TODO: Error codes. diff --git a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs index 2705272a3..6e488da58 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs @@ -1,6 +1,8 @@ using ChocolArm64.State; using Ryujinx.Core.OsHle.Handles; +using static Ryujinx.Core.OsHle.ErrorCode; + namespace Ryujinx.Core.OsHle.Svc { partial class SvcHandler @@ -19,7 +21,7 @@ namespace Ryujinx.Core.OsHle.Svc M.WaitForLock(RequestingThread, RequestingThreadHandle); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcArbitrateUnlock(AThreadState ThreadState) @@ -31,7 +33,7 @@ namespace Ryujinx.Core.OsHle.Svc M.Unlock(); } - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState) @@ -55,14 +57,14 @@ namespace Ryujinx.Core.OsHle.Svc if (!Cv.WaitForSignal(Thread)) { - ThreadState.X0 = (int)SvcResult.ErrTimeout; + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout); return; } M.WaitForLock(Thread, ThreadHandle); - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } private void SvcSignalProcessWideKey(AThreadState ThreadState) @@ -77,7 +79,7 @@ namespace Ryujinx.Core.OsHle.Svc Cv.SetSignal(CurrThread, Count); } - ThreadState.X0 = (int)SvcResult.Success; + ThreadState.X0 = 0; } } } \ No newline at end of file From 2d9edddf8ccc32ce1b179a10e23bca1276289447 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 5 Mar 2018 16:20:30 -0300 Subject: [PATCH 53/67] Remove QueryMemory workaround --- ChocolArm64/Decoder/AOpCodeSimdRegElem.cs | 2 -- Ryujinx.Core/OsHle/Svc/SvcMemory.cs | 2 -- 2 files changed, 4 deletions(-) diff --git a/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs b/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs index 127debd17..721da88fa 100644 --- a/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs +++ b/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs @@ -27,8 +27,6 @@ namespace ChocolArm64.Decoder default: Emitter = AInstEmit.Und; return; } - - } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index 1bb3011b8..bf946e4f8 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -88,8 +88,6 @@ namespace Ryujinx.Core.OsHle.Svc long InfoPtr = (long)ThreadState.X0; long Position = (long)ThreadState.X2; - Position &= uint.MaxValue; - AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position); if (MapInfo == null) From 39ed14a3d6304eeec8ce1fa34819b39c3ae28956 Mon Sep 17 00:00:00 2001 From: emmauss Date: Tue, 6 Mar 2018 15:25:26 +0200 Subject: [PATCH 54/67] stub IApplicationDisplayService:CloseDisplay (#52) --- .../OsHle/Services/Vi/IApplicationDisplayService.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs index a899cdd56..04dfee158 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi { 102, GetManagerDisplayService }, { 103, GetIndirectDisplayTransactionService }, { 1010, OpenDisplay }, + { 1020, CloseDisplay }, { 2020, OpenLayer }, { 2030, CreateStrayLayer }, { 2101, SetLayerScalingMode }, @@ -70,6 +71,15 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi return 0; } + public long CloseDisplay(ServiceCtx Context) + { + int DisplayId = Context.RequestData.ReadInt32(); + + Context.Ns.Os.Displays.Delete(DisplayId); + + return 0; + } + public long OpenLayer(ServiceCtx Context) { long LayerId = Context.RequestData.ReadInt64(); From 4038e63de14bf12c0cfbe885e2cac44577fe8a6a Mon Sep 17 00:00:00 2001 From: emmauss Date: Tue, 6 Mar 2018 22:18:49 +0200 Subject: [PATCH 55/67] Implement basic performance statistics (#53) * implement basic frame time stats * added game frame time * made performancestatictics class non-static * report average framerate instead of current framerate --- Ryujinx.Core/Logging.cs | 2 - Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 2 + Ryujinx.Core/PerformanceStatistics.cs | 87 +++++++++++++++++++++ Ryujinx.Core/Switch.cs | 7 +- Ryujinx/Ui/GLScreen.cs | 7 +- 5 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 Ryujinx.Core/PerformanceStatistics.cs diff --git a/Ryujinx.Core/Logging.cs b/Ryujinx.Core/Logging.cs index b14f26653..d544a5d64 100644 --- a/Ryujinx.Core/Logging.cs +++ b/Ryujinx.Core/Logging.cs @@ -22,8 +22,6 @@ namespace Ryujinx.Core static Logging() { - ExecutionTime.Start(); - if (File.Exists(LogFileName)) File.Delete(LogFileName); } diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 4b5f9819a..720dd44f9 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -154,6 +154,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android private long GbpQueueBuffer(ServiceCtx Context, BinaryReader ParcelReader) { + Context.Ns.Statistics.RecordGameFrameTime(); + //TODO: Errors. int Slot = ParcelReader.ReadInt32(); int Unknown4 = ParcelReader.ReadInt32(); diff --git a/Ryujinx.Core/PerformanceStatistics.cs b/Ryujinx.Core/PerformanceStatistics.cs new file mode 100644 index 000000000..3740daa58 --- /dev/null +++ b/Ryujinx.Core/PerformanceStatistics.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Timers; + +namespace Ryujinx.Core +{ + public class PerformanceStatistics + { + Stopwatch ExecutionTime = new Stopwatch(); + Timer ResetTimer = new Timer(1000); + + long CurrentGameFrameEnded; + long CurrentSystemFrameEnded; + long CurrentSystemFrameStart; + long LastGameFrameEnded; + long LastSystemFrameEnded; + + double AccumulatedGameFrameTime; + double AccumulatedSystemFrameTime; + double CurrentGameFrameTime; + double CurrentSystemFrameTime; + double PreviousGameFrameTime; + double PreviousSystemFrameTime; + public double GameFrameRate { get; private set; } + public double SystemFrameRate { get; private set; } + public long SystemFramesRendered; + public long GameFramesRendered; + public long ElapsedMilliseconds => ExecutionTime.ElapsedMilliseconds; + public long ElapsedMicroseconds => (long) + (((double)ExecutionTime.ElapsedTicks / Stopwatch.Frequency) * 1000000); + public long ElapsedNanoseconds => (long) + (((double)ExecutionTime.ElapsedTicks / Stopwatch.Frequency) * 1000000000); + + public PerformanceStatistics() + { + ExecutionTime.Start(); + ResetTimer.Elapsed += ResetTimerElapsed; + ResetTimer.AutoReset = true; + ResetTimer.Start(); + } + + private void ResetTimerElapsed(object sender, ElapsedEventArgs e) + { + ResetStatistics(); + } + + public void StartSystemFrame() + { + PreviousSystemFrameTime = CurrentSystemFrameTime; + LastSystemFrameEnded = CurrentSystemFrameEnded; + CurrentSystemFrameStart = ElapsedMicroseconds; + } + + public void EndSystemFrame() + { + CurrentSystemFrameEnded = ElapsedMicroseconds; + CurrentSystemFrameTime = CurrentSystemFrameEnded - CurrentSystemFrameStart; + AccumulatedSystemFrameTime += CurrentSystemFrameTime; + SystemFramesRendered++; + } + + public void RecordGameFrameTime() + { + CurrentGameFrameEnded = ElapsedMicroseconds; + CurrentGameFrameTime = CurrentGameFrameEnded - LastGameFrameEnded; + PreviousGameFrameTime = CurrentGameFrameTime; + LastGameFrameEnded = CurrentGameFrameEnded; + AccumulatedGameFrameTime += CurrentGameFrameTime; + GameFramesRendered++; + } + + public void ResetStatistics() + { + GameFrameRate = 1000 / ((AccumulatedGameFrameTime / GameFramesRendered) / 1000); + GameFrameRate = double.IsNaN(GameFrameRate) ? 0 : GameFrameRate; + SystemFrameRate = 1000 / ((AccumulatedSystemFrameTime / SystemFramesRendered) / 1000); + SystemFrameRate = double.IsNaN(SystemFrameRate) ? 0 : SystemFrameRate; + + GameFramesRendered = 0; + SystemFramesRendered = 0; + AccumulatedGameFrameTime = 0; + AccumulatedSystemFrameTime = 0; + } + } +} diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index 3f7b1e2b8..1acd87f01 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -17,8 +17,9 @@ namespace Ryujinx.Core internal Horizon Os { get; private set; } internal VirtualFs VFs { get; private set; } - public Hid Hid { get; private set; } - public SetSys Settings { get; private set; } + public Hid Hid { get; private set; } + public SetSys Settings { get; private set; } + public PerformanceStatistics Statistics { get; private set; } public event EventHandler Finish; @@ -32,6 +33,8 @@ namespace Ryujinx.Core Hid = new Hid(Ram); + Statistics = new PerformanceStatistics(); + Os = new Horizon(this); Os.HidSharedMem.MemoryMapped += Hid.ShMemMap; diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 4c7cee467..b0dca81b7 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -166,9 +166,12 @@ namespace Ryujinx protected override void OnRenderFrame(FrameEventArgs e) { + Ns.Statistics.StartSystemFrame(); + GL.Viewport(0, 0, Width, Height); - Title = $"Ryujinx Screen - (Vsync: {VSync} - FPS: {1f / e.Time:0})"; + Title = $"Ryujinx Screen - (Vsync: {VSync} - FPS: {Ns.Statistics.SystemFrameRate:0} - Guest FPS: " + + $"{Ns.Statistics.GameFrameRate:0})"; GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); @@ -176,6 +179,8 @@ namespace Ryujinx Renderer.Render(); SwapBuffers(); + + Ns.Statistics.EndSystemFrame(); } protected override void OnResize(EventArgs e) From 4f177c9ee7452274f5e792349e9b443d78a27816 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 6 Mar 2018 17:27:50 -0300 Subject: [PATCH 56/67] More Vi/NvFlinger/NvDrv stubs, allow paths starting with //, do not allow paths that don't start with at least a /, increase map region size --- Ryujinx.Core/OsHle/MemoryRegions.cs | 2 +- .../OsHle/Services/Nv/ServiceNvDrv.cs | 20 +++++++++++++++++++ .../Services/Vi/IApplicationDisplayService.cs | 6 ++++++ .../Services/Vi/IManagerDisplayService.cs | 10 ++++++++-- Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 6 ++++++ Ryujinx.Core/VirtualFs.cs | 10 +++++++++- 6 files changed, 50 insertions(+), 4 deletions(-) diff --git a/Ryujinx.Core/OsHle/MemoryRegions.cs b/Ryujinx.Core/OsHle/MemoryRegions.cs index e362ba9fd..7f5ab0ede 100644 --- a/Ryujinx.Core/OsHle/MemoryRegions.cs +++ b/Ryujinx.Core/OsHle/MemoryRegions.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle public const long AddrSpaceStart = 0x08000000; public const long MapRegionAddress = 0x10000000; - public const long MapRegionSize = 0x10000000; + public const long MapRegionSize = 0x20000000; public const long MainStackSize = 0x100000; diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs index 0ea1d2ac0..515c15e03 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs @@ -38,6 +38,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices { ("/dev/nvmap", 0x0101), NvMapIocCreate }, { ("/dev/nvmap", 0x0103), NvMapIocFromId }, { ("/dev/nvmap", 0x0104), NvMapIocAlloc }, + { ("/dev/nvmap", 0x0105), NvMapIocFree }, { ("/dev/nvmap", 0x0109), NvMapIocParam }, { ("/dev/nvmap", 0x010e), NvMapIocGetId }, }; @@ -585,6 +586,25 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } + private static long NvMapIocFree(ServiceCtx Context) + { + long Position = Context.Request.GetSendBuffPtr(); + + MemReader Reader = new MemReader(Context.Memory, Position); + MemWriter Writer = new MemWriter(Context.Memory, Position + 8); + + int Handle = Reader.ReadInt32(); + int Padding = Reader.ReadInt32(); + + HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + + Writer.WriteInt64(0); + Writer.WriteInt32(NvMap.Size); + Writer.WriteInt32(0); + + return 0; + } + private static long NvMapIocParam(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); diff --git a/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs index 04dfee158..4e40b99b3 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs @@ -26,6 +26,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi { 1010, OpenDisplay }, { 1020, CloseDisplay }, { 2020, OpenLayer }, + { 2021, CloseLayer }, { 2030, CreateStrayLayer }, { 2101, SetLayerScalingMode }, { 5202, GetDisplayVSyncEvent } @@ -96,6 +97,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi return 0; } + public long CloseLayer(ServiceCtx Context) + { + return 0; + } + public long CreateStrayLayer(ServiceCtx Context) { long LayerFlags = Context.RequestData.ReadInt64(); diff --git a/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs index 5adee78d1..69dbff47a 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs @@ -13,8 +13,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi { m_Commands = new Dictionary() { - { 2010, CreateManagedLayer }, - { 6000, AddToLayerStack } + { 2010, CreateManagedLayer }, + { 2011, DestroyManagedLayer }, + { 6000, AddToLayerStack } }; } @@ -25,6 +26,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi return 0; } + public long DestroyManagedLayer(ServiceCtx Context) + { + return 0; + } + public static long AddToLayerStack(ServiceCtx Context) { return 0; diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 720dd44f9..740a35f9c 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -70,6 +70,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android { ("android.gui.IGraphicBufferProducer", 0x8), GbpCancelBuffer }, { ("android.gui.IGraphicBufferProducer", 0x9), GbpQuery }, { ("android.gui.IGraphicBufferProducer", 0xa), GbpConnect }, + { ("android.gui.IGraphicBufferProducer", 0xb), GbpDisconnect }, { ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer } }; @@ -212,6 +213,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); } + private long GbpDisconnect(ServiceCtx Context, BinaryReader ParcelReader) + { + return MakeReplyParcel(Context, 0); + } + private long GbpPreallocBuffer(ServiceCtx Context, BinaryReader ParcelReader) { int Slot = ParcelReader.ReadInt32(); diff --git a/Ryujinx.Core/VirtualFs.cs b/Ryujinx.Core/VirtualFs.cs index 195fb6a3c..c0858e0ee 100644 --- a/Ryujinx.Core/VirtualFs.cs +++ b/Ryujinx.Core/VirtualFs.cs @@ -18,10 +18,18 @@ namespace Ryujinx.Core public string GetFullPath(string BasePath, string FileName) { - if (FileName.StartsWith('/')) + if (FileName.StartsWith("//")) + { + FileName = FileName.Substring(2); + } + else if (FileName.StartsWith('/')) { FileName = FileName.Substring(1); } + else + { + return null; + } string FullPath = Path.GetFullPath(Path.Combine(BasePath, FileName)); From be0e4007dc92e24a77bdc36a40d2450c41d9b560 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 6 Mar 2018 21:36:49 -0300 Subject: [PATCH 57/67] Add SMLAL (vector), fix EXT instruction --- ChocolArm64/AOpCodeTable.cs | 1 + ChocolArm64/Decoder/AOpCodeSimdExt.cs | 2 +- .../Instruction/AInstEmitSimdArithmetic.cs | 9 ++++++++ .../Instruction/AInstEmitSimdHelper.cs | 21 ++++++++++++++++--- ChocolArm64/Instruction/AInstEmitSimdMove.cs | 13 +++++++----- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 6b250b4b0..5afdbd1ff 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -243,6 +243,7 @@ namespace ChocolArm64 Set("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm)); Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg)); Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg)); + Set("0x001110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Smlal_V, typeof(AOpCodeSimdReg)); Set("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg)); Set("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg)); Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm)); diff --git a/ChocolArm64/Decoder/AOpCodeSimdExt.cs b/ChocolArm64/Decoder/AOpCodeSimdExt.cs index cf22d6546..888e44703 100644 --- a/ChocolArm64/Decoder/AOpCodeSimdExt.cs +++ b/ChocolArm64/Decoder/AOpCodeSimdExt.cs @@ -8,7 +8,7 @@ namespace ChocolArm64.Decoder public AOpCodeSimdExt(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { - int Imm4 = (OpCode >> 11) & 0xf; + Imm4 = (OpCode >> 11) & 0xf; } } } \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index 9f5cc64f4..b2d190f1a 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -374,6 +374,15 @@ namespace ChocolArm64.Instruction EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo)); } + public static void Smlal_V(AILEmitterCtx Context) + { + EmitVectorWidenRnRmTernaryOpSx(Context, () => + { + Context.Emit(OpCodes.Mul); + Context.Emit(OpCodes.Add); + }); + } + public static void Smull_V(AILEmitterCtx Context) { EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs index 33e4d5487..e6ead99aa 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs @@ -459,15 +459,25 @@ namespace ChocolArm64.Instruction public static void EmitVectorWidenRnRmBinaryOpSx(AILEmitterCtx Context, Action Emit) { - EmitVectorWidenRnRmBinaryOp(Context, Emit, true); + EmitVectorWidenRnRmOp(Context, Emit, false, true); } public static void EmitVectorWidenRnRmBinaryOpZx(AILEmitterCtx Context, Action Emit) { - EmitVectorWidenRnRmBinaryOp(Context, Emit, false); + EmitVectorWidenRnRmOp(Context, Emit, false, false); } - public static void EmitVectorWidenRnRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed) + public static void EmitVectorWidenRnRmTernaryOpSx(AILEmitterCtx Context, Action Emit) + { + EmitVectorWidenRnRmOp(Context, Emit, true, true); + } + + public static void EmitVectorWidenRnRmTernaryOpZx(AILEmitterCtx Context, Action Emit) + { + EmitVectorWidenRnRmOp(Context, Emit, true, false); + } + + public static void EmitVectorWidenRnRmOp(AILEmitterCtx Context, Action Emit, bool Ternary, bool Signed) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; @@ -477,6 +487,11 @@ namespace ChocolArm64.Instruction for (int Index = 0; Index < Elems; Index++) { + if (Ternary) + { + EmitVectorExtract(Context, Op.Rd, Index, Op.Size + 1, Signed); + } + EmitVectorExtract(Context, Op.Rn, Part + Index, Op.Size, Signed); EmitVectorExtract(Context, Op.Rm, Part + Index, Op.Size, Signed); diff --git a/ChocolArm64/Instruction/AInstEmitSimdMove.cs b/ChocolArm64/Instruction/AInstEmitSimdMove.cs index a4e533709..3f427ad8a 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdMove.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdMove.cs @@ -63,15 +63,18 @@ namespace ChocolArm64.Instruction int Bytes = Context.CurrOp.GetBitsCount() >> 3; + int Position = Op.Imm4; + for (int Index = 0; Index < Bytes; Index++) { - int Position = Op.Imm4 + Index; + int Reg = Op.Imm4 + Index < Bytes ? Op.Rn : Op.Rm; - int Reg = Position < Bytes ? Op.Rn : Op.Rm; + if (Position == Bytes) + { + Position = 0; + } - Position &= Bytes - 1; - - EmitVectorExtractZx(Context, Reg, Position, 0); + EmitVectorExtractZx(Context, Reg, Position++, 0); EmitVectorInsert(Context, Op.Rd, Index, 0); } From 5912bd2beb42e1853fdcf11e4bb87e063a0ef35b Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 9 Mar 2018 23:12:57 -0300 Subject: [PATCH 58/67] Disable memory checks by default, even on debug, move ram memory allocation inside the CPU, since the size if fixed anyway, better heap region size --- ChocolArm64/AOptimizations.cs | 2 +- ChocolArm64/AThread.cs | 2 +- ChocolArm64/Memory/AMemory.cs | 113 ++++------ ChocolArm64/Memory/AMemoryMgr.cs | 6 +- Ryujinx.Core/Hid/Hid.cs | 222 ++++++++++---------- Ryujinx.Core/OsHle/MemoryRegions.cs | 5 +- Ryujinx.Core/OsHle/Process.cs | 2 +- Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 6 +- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 2 +- Ryujinx.Core/PerformanceStatistics.cs | 5 +- Ryujinx.Core/Switch.cs | 11 +- Ryujinx.Tests/Cpu/CpuTest.cs | 8 +- 12 files changed, 177 insertions(+), 207 deletions(-) diff --git a/ChocolArm64/AOptimizations.cs b/ChocolArm64/AOptimizations.cs index cbfd1ce51..0cdbd76e2 100644 --- a/ChocolArm64/AOptimizations.cs +++ b/ChocolArm64/AOptimizations.cs @@ -1,4 +1,4 @@ public static class AOptimizations { - + public static bool EnableMemoryChecks = false; } \ No newline at end of file diff --git a/ChocolArm64/AThread.cs b/ChocolArm64/AThread.cs index 6e018db68..cec268175 100644 --- a/ChocolArm64/AThread.cs +++ b/ChocolArm64/AThread.cs @@ -10,7 +10,7 @@ namespace ChocolArm64 public AThreadState ThreadState { get; private set; } public AMemory Memory { get; private set; } - public long EntryPoint { get; private set; } + private long EntryPoint; private ATranslator Translator; diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs index 0d202fed3..7f2dd7d3f 100644 --- a/ChocolArm64/Memory/AMemory.cs +++ b/ChocolArm64/Memory/AMemory.cs @@ -3,10 +3,11 @@ using ChocolArm64.State; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace ChocolArm64.Memory { - public unsafe class AMemory + public unsafe class AMemory : IDisposable { private const long ErgMask = (4 << AThreadState.ErgSizeLog2) - 1; @@ -39,9 +40,11 @@ namespace ChocolArm64.Memory private HashSet ExAddrs; + public IntPtr Ram { get; private set; } + private byte* RamPtr; - public AMemory(IntPtr Ram) + public AMemory() { Manager = new AMemoryMgr(); @@ -49,6 +52,8 @@ namespace ChocolArm64.Memory ExAddrs = new HashSet(); + Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize); + RamPtr = (byte*)Ram; } @@ -142,9 +147,7 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public byte ReadByte(long Position) { -#if DEBUG EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif return *((byte*)(RamPtr + (uint)Position)); } @@ -152,9 +155,8 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public ushort ReadUInt16(long Position) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif + EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); + EnsureAccessIsValid(Position + 1, AMemoryPerm.Read); return *((ushort*)(RamPtr + (uint)Position)); } @@ -162,9 +164,8 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint ReadUInt32(long Position) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif + EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); + EnsureAccessIsValid(Position + 3, AMemoryPerm.Read); return *((uint*)(RamPtr + (uint)Position)); } @@ -172,9 +173,8 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public ulong ReadUInt64(long Position) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif + EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); + EnsureAccessIsValid(Position + 7, AMemoryPerm.Read); return *((ulong*)(RamPtr + (uint)Position)); } @@ -182,50 +182,30 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector8(long Position) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif - return new AVec() { B0 = ReadByte(Position) }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector16(long Position) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif - return new AVec() { H0 = ReadUInt16(Position) }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector32(long Position) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif - return new AVec() { W0 = ReadUInt32(Position) }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector64(long Position) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif - return new AVec() { X0 = ReadUInt64(Position) }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector128(long Position) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Read); -#endif - return new AVec() { X0 = ReadUInt64(Position + 0), @@ -241,9 +221,7 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteByte(long Position, byte Value) { -#if DEBUG EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif *((byte*)(RamPtr + (uint)Position)) = Value; } @@ -251,9 +229,8 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt16(long Position, ushort Value) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif + EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); + EnsureAccessIsValid(Position + 1, AMemoryPerm.Write); *((ushort*)(RamPtr + (uint)Position)) = Value; } @@ -261,9 +238,8 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt32(long Position, uint Value) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif + EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); + EnsureAccessIsValid(Position + 3, AMemoryPerm.Write); *((uint*)(RamPtr + (uint)Position)) = Value; } @@ -271,9 +247,8 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt64(long Position, ulong Value) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif + EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); + EnsureAccessIsValid(Position + 7, AMemoryPerm.Write); *((ulong*)(RamPtr + (uint)Position)) = Value; } @@ -281,64 +256,64 @@ namespace ChocolArm64.Memory [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector8(long Position, AVec Value) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif - WriteByte(Position, Value.B0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector16(long Position, AVec Value) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif - WriteUInt16(Position, Value.H0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector32(long Position, AVec Value) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif - WriteUInt32(Position, Value.W0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector64(long Position, AVec Value) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif - WriteUInt64(Position, Value.X0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector128(long Position, AVec Value) { -#if DEBUG - EnsureAccessIsValid(Position, AMemoryPerm.Write); -#endif - WriteUInt64(Position + 0, Value.X0); WriteUInt64(Position + 8, Value.X1); } private void EnsureAccessIsValid(long Position, AMemoryPerm Perm) { - if (!Manager.IsMapped(Position)) +#if DEBUG + if (AOptimizations.EnableMemoryChecks) { - throw new VmmPageFaultException(Position); - } + if (!Manager.IsMapped(Position)) + { + throw new VmmPageFaultException(Position); + } - if (!Manager.HasPermission(Position, Perm)) + if (!Manager.HasPermission(Position, Perm)) + { + throw new VmmAccessViolationException(Position, Perm); + } + } +#endif + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (Ram != IntPtr.Zero) { - throw new VmmAccessViolationException(Position, Perm); + Marshal.FreeHGlobal(Ram); + + Ram = IntPtr.Zero; } } } diff --git a/ChocolArm64/Memory/AMemoryMgr.cs b/ChocolArm64/Memory/AMemoryMgr.cs index bc3644524..8a165b079 100644 --- a/ChocolArm64/Memory/AMemoryMgr.cs +++ b/ChocolArm64/Memory/AMemoryMgr.cs @@ -4,8 +4,8 @@ namespace ChocolArm64.Memory { public class AMemoryMgr { - public const long AddrSize = RamSize; public const long RamSize = 4L * 1024 * 1024 * 1024; + public const long AddrSize = RamSize; private const int PTLvl0Bits = 10; private const int PTLvl1Bits = 10; @@ -19,8 +19,8 @@ namespace ChocolArm64.Memory private const int PTLvl1Mask = PTLvl1Size - 1; public const int PageMask = PageSize - 1; - private const int PTLvl0Bit = PTPageBits + PTLvl1Bits; - private const int PTLvl1Bit = PTPageBits; + private const int PTLvl0Bit = PTPageBits + PTLvl1Bits; + private const int PTLvl1Bit = PTPageBits; private enum PTMap { diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs index 249747c15..169768892 100644 --- a/Ryujinx.Core/Hid/Hid.cs +++ b/Ryujinx.Core/Hid/Hid.cs @@ -1,7 +1,5 @@ -using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.Handles; using System; -using System.Diagnostics; namespace Ryujinx.Core.Input { @@ -66,11 +64,15 @@ namespace Ryujinx.Core.Input private long[] ShMemPositions; - private IntPtr Ram; + private long CurrControllerEntry; + private long CurrTouchEntry; + private long CurrTouchSampleCounter; - public Hid(IntPtr Ram) + private Switch Ns; + + public Hid(Switch Ns) { - this.Ram = Ram; + this.Ns = Ns; ShMemLock = new object(); @@ -136,20 +138,20 @@ namespace Ryujinx.Core.Input HidControllerColorDesc SplitColorDesc = 0; - WriteInt32(BaseControllerOffset + 0x0, (int)Type); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x0, (int)Type); - WriteInt32(BaseControllerOffset + 0x4, IsHalf ? 1 : 0); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x4, IsHalf ? 1 : 0); - WriteInt32(BaseControllerOffset + 0x8, (int)SingleColorDesc); - WriteInt32(BaseControllerOffset + 0xc, (int)SingleColorBody); - WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons); - WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x8, (int)SingleColorDesc); + Ns.Memory.WriteInt32(BaseControllerOffset + 0xc, (int)SingleColorBody); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc); - WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody); - WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons); - WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody); - WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody); + Ns.Memory.WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons); } public void SetJoyconButton( @@ -163,119 +165,119 @@ namespace Ryujinx.Core.Input { foreach (long Position in ShMemPositions) { - long ControllerOffset = Position + HidControllersOffset; - - ControllerOffset += (int)ControllerId * HidControllerSize; - - ControllerOffset += HidControllerHeaderSize; - - ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; - - long LastEntry = ReadInt64(ControllerOffset + 0x10); - - long CurrEntry = (LastEntry + 1) % HidEntryCount; - - long Timestamp = Stopwatch.GetTimestamp(); - - WriteInt64(ControllerOffset + 0x0, Timestamp); - WriteInt64(ControllerOffset + 0x8, HidEntryCount); - WriteInt64(ControllerOffset + 0x10, CurrEntry); - WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1); - - ControllerOffset += HidControllersLayoutHeaderSize; - - ControllerOffset += CurrEntry * HidControllersInputEntrySize; - - WriteInt64(ControllerOffset + 0x0, Timestamp); - WriteInt64(ControllerOffset + 0x8, Timestamp); - - WriteInt64(ControllerOffset + 0x10, (uint)Buttons); - - WriteInt32(ControllerOffset + 0x18, LeftStick.DX); - WriteInt32(ControllerOffset + 0x1c, LeftStick.DY); - - WriteInt64(ControllerOffset + 0x20, RightStick.DX); - WriteInt64(ControllerOffset + 0x24, RightStick.DY); - - WriteInt64(ControllerOffset + 0x28, - (uint)HidControllerConnState.Controller_State_Connected | - (uint)HidControllerConnState.Controller_State_Wired); + WriteJoyconButtons( + Position, + ControllerId, + ControllerLayout, + Buttons, + LeftStick, + RightStick); } } } + private void WriteJoyconButtons( + long BasePosition, + HidControllerId ControllerId, + HidControllerLayouts ControllerLayout, + HidControllerButtons Buttons, + HidJoystickPosition LeftStick, + HidJoystickPosition RightStick) + { + long ControllerOffset = BasePosition + HidControllersOffset; + + ControllerOffset += (int)ControllerId * HidControllerSize; + + ControllerOffset += HidControllerHeaderSize; + + ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; + + CurrControllerEntry = (CurrControllerEntry + 1) % HidEntryCount; + + long Timestamp = GetTimestamp(); + + Ns.Memory.WriteInt64(ControllerOffset + 0x0, Timestamp); + Ns.Memory.WriteInt64(ControllerOffset + 0x8, HidEntryCount); + Ns.Memory.WriteInt64(ControllerOffset + 0x10, CurrControllerEntry); + Ns.Memory.WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1); + + ControllerOffset += HidControllersLayoutHeaderSize; + + ControllerOffset += CurrControllerEntry * HidControllersInputEntrySize; + + Ns.Memory.WriteInt64(ControllerOffset + 0x0, Timestamp); + Ns.Memory.WriteInt64(ControllerOffset + 0x8, Timestamp); + + Ns.Memory.WriteInt64(ControllerOffset + 0x10, (uint)Buttons); + + Ns.Memory.WriteInt32(ControllerOffset + 0x18, LeftStick.DX); + Ns.Memory.WriteInt32(ControllerOffset + 0x1c, LeftStick.DY); + + Ns.Memory.WriteInt32(ControllerOffset + 0x20, RightStick.DX); + Ns.Memory.WriteInt32(ControllerOffset + 0x24, RightStick.DY); + + Ns.Memory.WriteInt64(ControllerOffset + 0x28, + (uint)HidControllerConnState.Controller_State_Connected | + (uint)HidControllerConnState.Controller_State_Wired); + } + public void SetTouchPoints(params HidTouchPoint[] Points) { lock (ShMemLock) { foreach (long Position in ShMemPositions) { - long TouchScreenOffset = Position + HidTouchScreenOffset; - - long LastEntry = ReadInt64(TouchScreenOffset + 0x10); - - long CurrEntry = (LastEntry + 1) % HidEntryCount; - - long Timestamp = ReadInt64(TouchScreenOffset) + 1; - - WriteInt64(TouchScreenOffset + 0x0, Timestamp); - WriteInt64(TouchScreenOffset + 0x8, HidEntryCount); - WriteInt64(TouchScreenOffset + 0x10, CurrEntry); - WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1); - WriteInt64(TouchScreenOffset + 0x20, Timestamp); - - long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize; - - long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize; - - TouchEntryOffset += CurrEntry * HidTouchEntrySize; - - WriteInt64(TouchEntryOffset + 0x0, Timestamp); - WriteInt64(TouchEntryOffset + 0x8, Points.Length); - - TouchEntryOffset += HidTouchEntryHeaderSize; - - const int Padding = 0; - - int Index = 0; - - foreach (HidTouchPoint Point in Points) - { - WriteInt64(TouchEntryOffset + 0x0, Timestamp); - WriteInt32(TouchEntryOffset + 0x8, Padding); - WriteInt32(TouchEntryOffset + 0xc, Index++); - WriteInt32(TouchEntryOffset + 0x10, Point.X); - WriteInt32(TouchEntryOffset + 0x14, Point.Y); - WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX); - WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY); - WriteInt32(TouchEntryOffset + 0x20, Point.Angle); - WriteInt32(TouchEntryOffset + 0x24, Padding); - - TouchEntryOffset += HidTouchEntryTouchSize; - } + WriteTouchPoints(Position, Points); } } } - private unsafe long ReadInt64(long Position) + private void WriteTouchPoints(long BasePosition, params HidTouchPoint[] Points) { - if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return 0; + long TouchScreenOffset = BasePosition + HidTouchScreenOffset; - return *((long*)((byte*)Ram + Position)); + long Timestamp = GetTimestamp(); + + CurrTouchEntry = (CurrTouchEntry + 1) % HidEntryCount; + + Ns.Memory.WriteInt64(TouchScreenOffset + 0x0, Timestamp); + Ns.Memory.WriteInt64(TouchScreenOffset + 0x8, HidEntryCount); + Ns.Memory.WriteInt64(TouchScreenOffset + 0x10, CurrTouchEntry); + Ns.Memory.WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1); + Ns.Memory.WriteInt64(TouchScreenOffset + 0x20, Timestamp); + + long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize; + + TouchEntryOffset += CurrTouchEntry * HidTouchEntrySize; + + Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, CurrTouchSampleCounter++); + Ns.Memory.WriteInt64(TouchEntryOffset + 0x8, Points.Length); + + TouchEntryOffset += HidTouchEntryHeaderSize; + + const int Padding = 0; + + int Index = 0; + + foreach (HidTouchPoint Point in Points) + { + Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, Timestamp); + Ns.Memory.WriteInt32(TouchEntryOffset + 0x8, Padding); + Ns.Memory.WriteInt32(TouchEntryOffset + 0xc, Index++); + Ns.Memory.WriteInt32(TouchEntryOffset + 0x10, Point.X); + Ns.Memory.WriteInt32(TouchEntryOffset + 0x14, Point.Y); + Ns.Memory.WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX); + Ns.Memory.WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY); + Ns.Memory.WriteInt32(TouchEntryOffset + 0x20, Point.Angle); + Ns.Memory.WriteInt32(TouchEntryOffset + 0x24, Padding); + + TouchEntryOffset += HidTouchEntryTouchSize; + } } - private unsafe void WriteInt32(long Position, int Value) + private long GetTimestamp() { - if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return; - - *((int*)((byte*)Ram + Position)) = Value; - } - - private unsafe void WriteInt64(long Position, long Value) - { - if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return; - - *((long*)((byte*)Ram + Position)) = Value; + return Environment.TickCount * 19_200; } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/MemoryRegions.cs b/Ryujinx.Core/OsHle/MemoryRegions.cs index 7f5ab0ede..75b97b1f2 100644 --- a/Ryujinx.Core/OsHle/MemoryRegions.cs +++ b/Ryujinx.Core/OsHle/MemoryRegions.cs @@ -9,6 +9,9 @@ namespace Ryujinx.Core.OsHle public const long MapRegionAddress = 0x10000000; public const long MapRegionSize = 0x20000000; + public const long HeapRegionAddress = MapRegionAddress + MapRegionSize; + public const long HeapRegionSize = TlsPagesAddress - HeapRegionAddress; + public const long MainStackSize = 0x100000; public const long MainStackAddress = AMemoryMgr.AddrSize - MainStackSize; @@ -17,8 +20,6 @@ namespace Ryujinx.Core.OsHle public const long TlsPagesAddress = MainStackAddress - TlsPagesSize; - public const long HeapRegionAddress = MapRegionAddress + MapRegionSize; - public const long TotalMemoryUsed = HeapRegionAddress + TlsPagesSize + MainStackSize; public const long TotalMemoryAvailable = AMemoryMgr.RamSize - AddrSpaceStart; diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index f549b0279..a919f1af6 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -45,7 +45,7 @@ namespace Ryujinx.Core.OsHle this.Ns = Ns; this.ProcessId = ProcessId; - Memory = new AMemory(Ns.Ram); + Memory = Ns.Memory; Scheduler = new KProcessScheduler(); diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 740a35f9c..1d394fb4a 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -264,11 +264,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android int FbWidth = BufferQueue[Slot].Data.Width; int FbHeight = BufferQueue[Slot].Data.Height; - int FbSize = FbWidth * FbHeight * 4; + long FbSize = (uint)FbWidth * FbHeight * 4; HNvMap NvMap = GetNvMap(Context, Slot); - if (FbSize < 0 || NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize) + if ((ulong)(NvMap.Address + FbSize) > AMemoryMgr.AddrSize) { Logging.Error($"Frame buffer address {NvMap.Address:x16} is invalid!"); @@ -330,7 +330,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android Rotate = -MathF.PI * 0.5f; } - byte* Fb = (byte*)Context.Ns.Ram + NvMap.Address; + byte* Fb = (byte*)Context.Ns.Memory.Ram + NvMap.Address; Context.Ns.Gpu.Renderer.QueueAction(delegate() { diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index 8a0a39175..a276fe3c8 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -197,7 +197,7 @@ namespace Ryujinx.Core.OsHle.Svc break; case 5: - ThreadState.X1 = CurrentHeapSize; + ThreadState.X1 = MemoryRegions.HeapRegionSize; break; case 6: diff --git a/Ryujinx.Core/PerformanceStatistics.cs b/Ryujinx.Core/PerformanceStatistics.cs index 3740daa58..e5d930f93 100644 --- a/Ryujinx.Core/PerformanceStatistics.cs +++ b/Ryujinx.Core/PerformanceStatistics.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; +using System.Diagnostics; using System.Timers; namespace Ryujinx.Core diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index 1acd87f01..dff7802b7 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -5,13 +5,12 @@ using Ryujinx.Core.Settings; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gpu; using System; -using System.Runtime.InteropServices; namespace Ryujinx.Core { public class Switch : IDisposable { - public IntPtr Ram {get; private set; } + internal AMemory Memory { get; private set; } internal NsGpu Gpu { get; private set; } internal Horizon Os { get; private set; } @@ -25,13 +24,13 @@ namespace Ryujinx.Core public Switch(IGalRenderer Renderer) { - Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); + Memory = new AMemory(); Gpu = new NsGpu(Renderer); VFs = new VirtualFs(); - Hid = new Hid(Ram); + Hid = new Hid(this); Statistics = new PerformanceStatistics(); @@ -72,10 +71,10 @@ namespace Ryujinx.Core { if (disposing) { + Memory.Dispose(); + VFs.Dispose(); } - - Marshal.FreeHGlobal(Ram); } } } \ No newline at end of file diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index a4a3b33fc..c4f0bbd74 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -2,8 +2,6 @@ using ChocolArm64; using ChocolArm64.Memory; using ChocolArm64.State; using NUnit.Framework; -using System; -using System.Runtime.InteropServices; using System.Threading; namespace Ryujinx.Tests.Cpu @@ -16,7 +14,6 @@ namespace Ryujinx.Tests.Cpu private long EntryPoint; - private IntPtr Ram; private AMemory Memory; private AThread Thread; @@ -28,9 +25,8 @@ namespace Ryujinx.Tests.Cpu EntryPoint = Position; - Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); ATranslator Translator = new ATranslator(); - Memory = new AMemory(Ram); + Memory = new AMemory(); Memory.Manager.Map(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute); Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint); } @@ -38,9 +34,9 @@ namespace Ryujinx.Tests.Cpu [TearDown] public void Teardown() { + Memory.Dispose(); Thread = null; Memory = null; - Marshal.FreeHGlobal(Ram); } protected void Reset() From aa2d2b3149536792bf49a9d5695778efea64c53a Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 9 Mar 2018 23:28:38 -0300 Subject: [PATCH 59/67] Add SHLL instruction --- ChocolArm64/AOpCodeTable.cs | 1 + ChocolArm64/Instruction/AInstEmitSimdShift.cs | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 5afdbd1ff..357d63db0 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -240,6 +240,7 @@ namespace ChocolArm64 Set("0x0011100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_V, typeof(AOpCodeSimd)); Set("010111110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_S, typeof(AOpCodeSimdShImm)); Set("0x0011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm)); + Set("0x101110<<100001001110xxxxxxxxxx", AInstEmit.Shll_V, typeof(AOpCodeSimd)); Set("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm)); Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg)); Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs index 8740ba4d6..01ed3a28b 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdShift.cs @@ -32,6 +32,15 @@ namespace ChocolArm64.Instruction EmitVectorShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift); } + public static void Shll_V(AILEmitterCtx Context) + { + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; + + int Shift = 8 << Op.Size; + + EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift); + } + public static void Shrn_V(AILEmitterCtx Context) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; @@ -205,7 +214,7 @@ namespace ChocolArm64.Instruction private static void EmitVectorShImmBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed) { - AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Bytes = Context.CurrOp.GetBitsCount() >> 3; @@ -238,7 +247,7 @@ namespace ChocolArm64.Instruction private static void EmitVectorShImmNarrowBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed) { - AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Elems = 8 >> Op.Size; @@ -273,7 +282,7 @@ namespace ChocolArm64.Instruction private static void EmitVectorShImmWidenBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed) { - AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Elems = 8 >> Op.Size; From 30bcb8da33c328be1abd922b0a6a95dc5c4d6c64 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 9 Mar 2018 23:41:05 -0300 Subject: [PATCH 60/67] Add FRINTM (vector) instruction --- ChocolArm64/AOpCodeTable.cs | 1 + ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs | 8 ++++++++ ChocolArm64/Instruction/AInstEmitSimdHelper.cs | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 357d63db0..f25d69734 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -200,6 +200,7 @@ namespace ChocolArm64 Set("000111100x1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg)); Set("000111100x100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd)); Set("000111100x100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd)); + Set("0>0011100<100001100110xxxxxxxxxx", AInstEmit.Frintm_V, typeof(AOpCodeSimd)); Set("000111100x100100110000xxxxxxxxxx", AInstEmit.Frintp_S, typeof(AOpCodeSimd)); Set("000111100x100111010000xxxxxxxxxx", AInstEmit.Frintx_S, typeof(AOpCodeSimd)); Set("000111100x100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index b2d190f1a..bf980a581 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -267,6 +267,14 @@ namespace ChocolArm64.Instruction }); } + public static void Frintm_V(AILEmitterCtx Context) + { + EmitVectorUnaryOpF(Context, () => + { + EmitUnaryMathCall(Context, nameof(Math.Floor)); + }); + } + public static void Frintp_S(AILEmitterCtx Context) { EmitScalarUnaryOpF(Context, () => diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs index e6ead99aa..1f78b71a1 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs @@ -190,6 +190,11 @@ namespace ChocolArm64.Instruction EmitScalarSetF(Context, Op.Rd, SizeF); } + public static void EmitVectorUnaryOpF(AILEmitterCtx Context, Action Emit) + { + EmitVectorOpF(Context, Emit, OperFlags.Rn); + } + public static void EmitVectorBinaryOpF(AILEmitterCtx Context, Action Emit) { EmitVectorOpF(Context, Emit, OperFlags.RnRm); From 553f6c2976818b3abcd0fd09de582dc71f03736e Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 10 Mar 2018 00:00:31 -0300 Subject: [PATCH 61/67] Fix EmitScalarUnaryOpF and add SSRA (vector) --- ChocolArm64/AOpCodeTable.cs | 1 + .../Instruction/AInstEmitSimdHelper.cs | 4 +- ChocolArm64/Instruction/AInstEmitSimdShift.cs | 39 +++++++++++++++---- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index f25d69734..60646d0ee 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -251,6 +251,7 @@ namespace ChocolArm64 Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm)); Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm)); Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm)); + Set("0x0011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm)); Set("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs)); Set("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs)); Set("0x00110100000000xx0xxxxxxxxxxxxx", AInstEmit.St__Vss, typeof(AOpCodeSimdMemSs)); diff --git a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs index 1f78b71a1..4e45a11d6 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdHelper.cs @@ -207,7 +207,7 @@ namespace ChocolArm64.Instruction public static void EmitVectorOpF(AILEmitterCtx Context, Action Emit, OperFlags Opers) { - AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int SizeF = Op.Size & 1; @@ -227,7 +227,7 @@ namespace ChocolArm64.Instruction if (Opers.HasFlag(OperFlags.Rm)) { - EmitVectorExtractF(Context, Op.Rm, Index, SizeF); + EmitVectorExtractF(Context, ((AOpCodeSimdReg)Op).Rm, Index, SizeF); } Emit(); diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs index 01ed3a28b..bb8a8f178 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdShift.cs @@ -29,7 +29,7 @@ namespace ChocolArm64.Instruction int Shift = Op.Imm - (8 << Op.Size); - EmitVectorShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift); + EmitVectorBinaryShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift); } public static void Shll_V(AILEmitterCtx Context) @@ -83,7 +83,22 @@ namespace ChocolArm64.Instruction int Shift = (8 << (Op.Size + 1)) - Op.Imm; - EmitVectorShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift); + EmitVectorBinaryShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift); + } + + public static void Ssra_V(AILEmitterCtx Context) + { + AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; + + int Shift = (8 << (Op.Size + 1)) - Op.Imm; + + Action Emit = () => + { + Context.Emit(OpCodes.Shr); + Context.Emit(OpCodes.Add); + }; + + EmitVectorTernaryShImmBinarySx(Context, Emit, Shift); } public static void Ushl_V(AILEmitterCtx Context) @@ -202,17 +217,22 @@ namespace ChocolArm64.Instruction } } - private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm) + private static void EmitVectorBinaryShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm) { - EmitVectorShImmBinaryOp(Context, Emit, Imm, true); + EmitVectorShImmBinaryOp(Context, Emit, Imm, false, true); } - private static void EmitVectorShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm) + private static void EmitVectorTernaryShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm) { - EmitVectorShImmBinaryOp(Context, Emit, Imm, false); + EmitVectorShImmBinaryOp(Context, Emit, Imm, true, true); } - private static void EmitVectorShImmBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed) + private static void EmitVectorBinaryShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm) + { + EmitVectorShImmBinaryOp(Context, Emit, Imm, false, false); + } + + private static void EmitVectorShImmBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Ternary, bool Signed) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; @@ -220,6 +240,11 @@ namespace ChocolArm64.Instruction for (int Index = 0; Index < (Bytes >> Op.Size); Index++) { + if (Ternary) + { + EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed); + } + EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed); Context.EmitLdc_I4(Imm); From 3777fb44cf03d05fdedee00f1a19d30fac73b31b Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 10 Mar 2018 20:39:16 -0300 Subject: [PATCH 62/67] Allow to enable/disable memory checks even on release mode through the flag, return error for invalid addresses on SvcMap*Memory svcs, do not return error on SvcQueryMemory (instead, return reserved for the end of the address space), other minor tweaks --- ChocolArm64/AOptimizations.cs | 2 +- .../Instruction/AInstEmitMemoryHelper.cs | 86 +++++-- ChocolArm64/Memory/AMemory.cs | 235 ++++++++++++++---- Ryujinx.Core/Hid/Hid.cs | 211 ++++++++-------- Ryujinx.Core/Loaders/Executable.cs | 13 +- .../Loaders/Executables/IExecutable.cs | 8 +- Ryujinx.Core/Loaders/Executables/Nro.cs | 18 +- Ryujinx.Core/Loaders/Executables/Nso.cs | 35 ++- Ryujinx.Core/OsHle/Horizon.cs | 2 + Ryujinx.Core/OsHle/Ipc/IpcMessage.cs | 14 +- .../OsHle/Services/Nv/ServiceNvDrv.cs | 42 ++-- Ryujinx.Core/OsHle/Svc/SvcMemory.cs | 107 +++++++- Ryujinx.Core/Switch.cs | 2 +- Ryujinx.Tests/Cpu/CpuTest.cs | 2 +- Ryujinx/Ui/Program.cs | 2 + 15 files changed, 516 insertions(+), 263 deletions(-) diff --git a/ChocolArm64/AOptimizations.cs b/ChocolArm64/AOptimizations.cs index 0cdbd76e2..a3c82dccd 100644 --- a/ChocolArm64/AOptimizations.cs +++ b/ChocolArm64/AOptimizations.cs @@ -1,4 +1,4 @@ public static class AOptimizations { - public static bool EnableMemoryChecks = false; + public static bool DisableMemoryChecks = false; } \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs index d5a0051b5..6ffcf2dc9 100644 --- a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs @@ -45,21 +45,46 @@ namespace ChocolArm64.Instruction { switch (Size) { - case 0: Name = nameof(AMemory.ReadVector8); break; - case 1: Name = nameof(AMemory.ReadVector16); break; - case 2: Name = nameof(AMemory.ReadVector32); break; - case 3: Name = nameof(AMemory.ReadVector64); break; - case 4: Name = nameof(AMemory.ReadVector128); break; + case 0: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadVector8Unchecked) + : nameof(AMemory.ReadVector8); break; + + case 1: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadVector16Unchecked) + : nameof(AMemory.ReadVector16); break; + + case 2: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadVector32Unchecked) + : nameof(AMemory.ReadVector32); break; + + case 3: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadVector64Unchecked) + : nameof(AMemory.ReadVector64); break; + + case 4: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadVector128Unchecked) + : nameof(AMemory.ReadVector128); break; } } else { switch (Size) { - case 0: Name = nameof(AMemory.ReadByte); break; - case 1: Name = nameof(AMemory.ReadUInt16); break; - case 2: Name = nameof(AMemory.ReadUInt32); break; - case 3: Name = nameof(AMemory.ReadUInt64); break; + case 0: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadByteUnchecked) + : nameof(AMemory.ReadByte); break; + + case 1: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadUInt16Unchecked) + : nameof(AMemory.ReadUInt16); break; + + case 2: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadUInt32Unchecked) + : nameof(AMemory.ReadUInt32); break; + + case 3: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadUInt64Unchecked) + : nameof(AMemory.ReadUInt64); break; } } @@ -107,21 +132,46 @@ namespace ChocolArm64.Instruction { switch (Size) { - case 0: Name = nameof(AMemory.WriteVector8); break; - case 1: Name = nameof(AMemory.WriteVector16); break; - case 2: Name = nameof(AMemory.WriteVector32); break; - case 3: Name = nameof(AMemory.WriteVector64); break; - case 4: Name = nameof(AMemory.WriteVector128); break; + case 0: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteVector8Unchecked) + : nameof(AMemory.WriteVector8); break; + + case 1: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteVector16Unchecked) + : nameof(AMemory.WriteVector16); break; + + case 2: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteVector32Unchecked) + : nameof(AMemory.WriteVector32); break; + + case 3: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteVector64Unchecked) + : nameof(AMemory.WriteVector64); break; + + case 4: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteVector128Unchecked) + : nameof(AMemory.WriteVector128); break; } } else { switch (Size) { - case 0: Name = nameof(AMemory.WriteByte); break; - case 1: Name = nameof(AMemory.WriteUInt16); break; - case 2: Name = nameof(AMemory.WriteUInt32); break; - case 3: Name = nameof(AMemory.WriteUInt64); break; + case 0: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteByteUnchecked) + : nameof(AMemory.WriteByte); break; + + case 1: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteUInt16Unchecked) + : nameof(AMemory.WriteUInt16); break; + + case 2: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteUInt32Unchecked) + : nameof(AMemory.WriteUInt32); break; + + case 3: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteUInt64Unchecked) + : nameof(AMemory.WriteUInt64); break; } } diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs index 7f2dd7d3f..d7e11189f 100644 --- a/ChocolArm64/Memory/AMemory.cs +++ b/ChocolArm64/Memory/AMemory.cs @@ -2,7 +2,6 @@ using ChocolArm64.Exceptions; using ChocolArm64.State; using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace ChocolArm64.Memory @@ -139,71 +138,77 @@ namespace ChocolArm64.Memory } } - public sbyte ReadSByte(long Position) => (sbyte)ReadByte (Position); - public short ReadInt16(long Position) => (short)ReadUInt16(Position); - public int ReadInt32(long Position) => (int)ReadUInt32(Position); - public long ReadInt64(long Position) => (long)ReadUInt64(Position); + public sbyte ReadSByte(long Position) + { + return (sbyte)ReadByte(Position); + } + + public short ReadInt16(long Position) + { + return (short)ReadUInt16(Position); + } + + public int ReadInt32(long Position) + { + return (int)ReadUInt32(Position); + } + + public long ReadInt64(long Position) + { + return (long)ReadUInt64(Position); + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public byte ReadByte(long Position) { EnsureAccessIsValid(Position, AMemoryPerm.Read); - return *((byte*)(RamPtr + (uint)Position)); + return ReadByteUnchecked(Position); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ushort ReadUInt16(long Position) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); EnsureAccessIsValid(Position + 1, AMemoryPerm.Read); - return *((ushort*)(RamPtr + (uint)Position)); + return ReadUInt16Unchecked(Position); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint ReadUInt32(long Position) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); EnsureAccessIsValid(Position + 3, AMemoryPerm.Read); - return *((uint*)(RamPtr + (uint)Position)); + return ReadUInt32Unchecked(Position); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ulong ReadUInt64(long Position) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); EnsureAccessIsValid(Position + 7, AMemoryPerm.Read); - return *((ulong*)(RamPtr + (uint)Position)); + return ReadUInt64Unchecked(Position); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector8(long Position) { return new AVec() { B0 = ReadByte(Position) }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector16(long Position) { return new AVec() { H0 = ReadUInt16(Position) }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector32(long Position) { return new AVec() { W0 = ReadUInt32(Position) }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector64(long Position) { return new AVec() { X0 = ReadUInt64(Position) }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector128(long Position) { return new AVec() @@ -213,93 +218,229 @@ namespace ChocolArm64.Memory }; } - public void WriteSByte(long Position, sbyte Value) => WriteByte (Position, (byte)Value); - public void WriteInt16(long Position, short Value) => WriteUInt16(Position, (ushort)Value); - public void WriteInt32(long Position, int Value) => WriteUInt32(Position, (uint)Value); - public void WriteInt64(long Position, long Value) => WriteUInt64(Position, (ulong)Value); + public sbyte ReadSByteUnchecked(long Position) + { + return (sbyte)ReadByteUnchecked(Position); + } + + public short ReadInt16Unchecked(long Position) + { + return (short)ReadUInt16Unchecked(Position); + } + + public int ReadInt32Unchecked(long Position) + { + return (int)ReadUInt32Unchecked(Position); + } + + public long ReadInt64Unchecked(long Position) + { + return (long)ReadUInt64Unchecked(Position); + } + + public byte ReadByteUnchecked(long Position) + { + return *((byte*)(RamPtr + (uint)Position)); + } + + public ushort ReadUInt16Unchecked(long Position) + { + return *((ushort*)(RamPtr + (uint)Position)); + } + + public uint ReadUInt32Unchecked(long Position) + { + return *((uint*)(RamPtr + (uint)Position)); + } + + public ulong ReadUInt64Unchecked(long Position) + { + return *((ulong*)(RamPtr + (uint)Position)); + } + + public AVec ReadVector8Unchecked(long Position) + { + return new AVec() { B0 = ReadByteUnchecked(Position) }; + } + + public AVec ReadVector16Unchecked(long Position) + { + return new AVec() { H0 = ReadUInt16Unchecked(Position) }; + } + + public AVec ReadVector32Unchecked(long Position) + { + return new AVec() { W0 = ReadUInt32Unchecked(Position) }; + } + + public AVec ReadVector64Unchecked(long Position) + { + return new AVec() { X0 = ReadUInt64Unchecked(Position) }; + } + + public AVec ReadVector128Unchecked(long Position) + { + return new AVec() + { + X0 = ReadUInt64Unchecked(Position + 0), + X1 = ReadUInt64Unchecked(Position + 8) + }; + } + + public void WriteSByte(long Position, sbyte Value) + { + WriteByte(Position, (byte)Value); + } + + public void WriteInt16(long Position, short Value) + { + WriteUInt16(Position, (ushort)Value); + } + + public void WriteInt32(long Position, int Value) + { + WriteUInt32(Position, (uint)Value); + } + + public void WriteInt64(long Position, long Value) + { + WriteUInt64(Position, (ulong)Value); + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteByte(long Position, byte Value) { EnsureAccessIsValid(Position, AMemoryPerm.Write); - *((byte*)(RamPtr + (uint)Position)) = Value; + WriteByteUnchecked(Position, Value); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt16(long Position, ushort Value) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); EnsureAccessIsValid(Position + 1, AMemoryPerm.Write); - *((ushort*)(RamPtr + (uint)Position)) = Value; + WriteUInt16Unchecked(Position, Value); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt32(long Position, uint Value) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); EnsureAccessIsValid(Position + 3, AMemoryPerm.Write); - *((uint*)(RamPtr + (uint)Position)) = Value; + WriteUInt32Unchecked(Position, Value); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt64(long Position, ulong Value) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); EnsureAccessIsValid(Position + 7, AMemoryPerm.Write); - *((ulong*)(RamPtr + (uint)Position)) = Value; + WriteUInt64Unchecked(Position, Value); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector8(long Position, AVec Value) { WriteByte(Position, Value.B0); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector16(long Position, AVec Value) { WriteUInt16(Position, Value.H0); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector32(long Position, AVec Value) { WriteUInt32(Position, Value.W0); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector64(long Position, AVec Value) { WriteUInt64(Position, Value.X0); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector128(long Position, AVec Value) { WriteUInt64(Position + 0, Value.X0); WriteUInt64(Position + 8, Value.X1); } + public void WriteSByteUnchecked(long Position, sbyte Value) + { + WriteByteUnchecked(Position, (byte)Value); + } + + public void WriteInt16Unchecked(long Position, short Value) + { + WriteUInt16Unchecked(Position, (ushort)Value); + } + + public void WriteInt32Unchecked(long Position, int Value) + { + WriteUInt32Unchecked(Position, (uint)Value); + } + + public void WriteInt64Unchecked(long Position, long Value) + { + WriteUInt64Unchecked(Position, (ulong)Value); + } + + public void WriteByteUnchecked(long Position, byte Value) + { + *((byte*)(RamPtr + (uint)Position)) = Value; + } + + public void WriteUInt16Unchecked(long Position, ushort Value) + { + *((ushort*)(RamPtr + (uint)Position)) = Value; + } + + public void WriteUInt32Unchecked(long Position, uint Value) + { + *((uint*)(RamPtr + (uint)Position)) = Value; + } + + public void WriteUInt64Unchecked(long Position, ulong Value) + { + *((ulong*)(RamPtr + (uint)Position)) = Value; + } + + public void WriteVector8Unchecked(long Position, AVec Value) + { + WriteByteUnchecked(Position, Value.B0); + } + + public void WriteVector16Unchecked(long Position, AVec Value) + { + WriteUInt16Unchecked(Position, Value.H0); + } + + public void WriteVector32Unchecked(long Position, AVec Value) + { + WriteUInt32Unchecked(Position, Value.W0); + } + + public void WriteVector64Unchecked(long Position, AVec Value) + { + WriteUInt64Unchecked(Position, Value.X0); + } + + public void WriteVector128Unchecked(long Position, AVec Value) + { + WriteUInt64Unchecked(Position + 0, Value.X0); + WriteUInt64Unchecked(Position + 8, Value.X1); + } + private void EnsureAccessIsValid(long Position, AMemoryPerm Perm) { -#if DEBUG - if (AOptimizations.EnableMemoryChecks) + if (!Manager.IsMapped(Position)) { - if (!Manager.IsMapped(Position)) - { - throw new VmmPageFaultException(Position); - } - - if (!Manager.HasPermission(Position, Perm)) - { - throw new VmmAccessViolationException(Position, Perm); - } + throw new VmmPageFaultException(Position); + } + + if (!Manager.HasPermission(Position, Perm)) + { + throw new VmmAccessViolationException(Position, Perm); } -#endif } public void Dispose() diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs index 169768892..76ecf5ffd 100644 --- a/Ryujinx.Core/Hid/Hid.cs +++ b/Ryujinx.Core/Hid/Hid.cs @@ -1,4 +1,5 @@ -using Ryujinx.Core.OsHle.Handles; +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Handles; using System; namespace Ryujinx.Core.Input @@ -64,15 +65,11 @@ namespace Ryujinx.Core.Input private long[] ShMemPositions; - private long CurrControllerEntry; - private long CurrTouchEntry; - private long CurrTouchSampleCounter; + private AMemory Memory; - private Switch Ns; - - public Hid(Switch Ns) + public Hid(AMemory Memory) { - this.Ns = Ns; + this.Memory = Memory; ShMemLock = new object(); @@ -138,20 +135,20 @@ namespace Ryujinx.Core.Input HidControllerColorDesc SplitColorDesc = 0; - Ns.Memory.WriteInt32(BaseControllerOffset + 0x0, (int)Type); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x0, (int)Type); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x4, IsHalf ? 1 : 0); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x4, IsHalf ? 1 : 0); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x8, (int)SingleColorDesc); - Ns.Memory.WriteInt32(BaseControllerOffset + 0xc, (int)SingleColorBody); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x8, (int)SingleColorDesc); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0xc, (int)SingleColorBody); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x10, (int)SingleColorButtons); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x14, (int)SplitColorDesc); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x18, (int)LeftColorBody); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x1c, (int)LeftColorButtons); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x20, (int)RightColorBody); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x24, (int)RightColorButtons); } public void SetJoyconButton( @@ -165,116 +162,102 @@ namespace Ryujinx.Core.Input { foreach (long Position in ShMemPositions) { - WriteJoyconButtons( - Position, - ControllerId, - ControllerLayout, - Buttons, - LeftStick, - RightStick); + long ControllerOffset = Position + HidControllersOffset; + + ControllerOffset += (int)ControllerId * HidControllerSize; + + ControllerOffset += HidControllerHeaderSize; + + ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; + + long LastEntry = Memory.ReadInt64Unchecked(ControllerOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = GetTimestamp(); + + Memory.WriteInt64Unchecked(ControllerOffset + 0x0, Timestamp); + Memory.WriteInt64Unchecked(ControllerOffset + 0x8, HidEntryCount); + Memory.WriteInt64Unchecked(ControllerOffset + 0x10, CurrEntry); + Memory.WriteInt64Unchecked(ControllerOffset + 0x18, HidEntryCount - 1); + + ControllerOffset += HidControllersLayoutHeaderSize; + + ControllerOffset += CurrEntry * HidControllersInputEntrySize; + + Memory.WriteInt64Unchecked(ControllerOffset + 0x0, Timestamp); + Memory.WriteInt64Unchecked(ControllerOffset + 0x8, Timestamp); + + Memory.WriteInt64Unchecked(ControllerOffset + 0x10, (uint)Buttons); + + Memory.WriteInt32Unchecked(ControllerOffset + 0x18, LeftStick.DX); + Memory.WriteInt32Unchecked(ControllerOffset + 0x1c, LeftStick.DY); + + Memory.WriteInt64Unchecked(ControllerOffset + 0x20, RightStick.DX); + Memory.WriteInt64Unchecked(ControllerOffset + 0x24, RightStick.DY); + + Memory.WriteInt64Unchecked(ControllerOffset + 0x28, + (uint)HidControllerConnState.Controller_State_Connected | + (uint)HidControllerConnState.Controller_State_Wired); } } } - private void WriteJoyconButtons( - long BasePosition, - HidControllerId ControllerId, - HidControllerLayouts ControllerLayout, - HidControllerButtons Buttons, - HidJoystickPosition LeftStick, - HidJoystickPosition RightStick) - { - long ControllerOffset = BasePosition + HidControllersOffset; - - ControllerOffset += (int)ControllerId * HidControllerSize; - - ControllerOffset += HidControllerHeaderSize; - - ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; - - CurrControllerEntry = (CurrControllerEntry + 1) % HidEntryCount; - - long Timestamp = GetTimestamp(); - - Ns.Memory.WriteInt64(ControllerOffset + 0x0, Timestamp); - Ns.Memory.WriteInt64(ControllerOffset + 0x8, HidEntryCount); - Ns.Memory.WriteInt64(ControllerOffset + 0x10, CurrControllerEntry); - Ns.Memory.WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1); - - ControllerOffset += HidControllersLayoutHeaderSize; - - ControllerOffset += CurrControllerEntry * HidControllersInputEntrySize; - - Ns.Memory.WriteInt64(ControllerOffset + 0x0, Timestamp); - Ns.Memory.WriteInt64(ControllerOffset + 0x8, Timestamp); - - Ns.Memory.WriteInt64(ControllerOffset + 0x10, (uint)Buttons); - - Ns.Memory.WriteInt32(ControllerOffset + 0x18, LeftStick.DX); - Ns.Memory.WriteInt32(ControllerOffset + 0x1c, LeftStick.DY); - - Ns.Memory.WriteInt32(ControllerOffset + 0x20, RightStick.DX); - Ns.Memory.WriteInt32(ControllerOffset + 0x24, RightStick.DY); - - Ns.Memory.WriteInt64(ControllerOffset + 0x28, - (uint)HidControllerConnState.Controller_State_Connected | - (uint)HidControllerConnState.Controller_State_Wired); - } - public void SetTouchPoints(params HidTouchPoint[] Points) { lock (ShMemLock) { foreach (long Position in ShMemPositions) { - WriteTouchPoints(Position, Points); + long TouchScreenOffset = Position + HidTouchScreenOffset; + + long LastEntry = Memory.ReadInt64Unchecked(TouchScreenOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = GetTimestamp(); + + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x0, Timestamp); + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x8, HidEntryCount); + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x10, CurrEntry); + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x18, HidEntryCount - 1); + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x20, Timestamp); + + long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize; + + long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize; + + long SampleCounter = Memory.ReadInt64Unchecked(LastEntryOffset) + 1; + + TouchEntryOffset += CurrEntry * HidTouchEntrySize; + + Memory.WriteInt64Unchecked(TouchEntryOffset + 0x0, SampleCounter); + Memory.WriteInt64Unchecked(TouchEntryOffset + 0x8, Points.Length); + + TouchEntryOffset += HidTouchEntryHeaderSize; + + const int Padding = 0; + + int Index = 0; + + foreach (HidTouchPoint Point in Points) + { + Memory.WriteInt64Unchecked(TouchEntryOffset + 0x0, Timestamp); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x8, Padding); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0xc, Index++); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x10, Point.X); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x14, Point.Y); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x18, Point.DiameterX); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x1c, Point.DiameterY); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x20, Point.Angle); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x24, Padding); + + TouchEntryOffset += HidTouchEntryTouchSize; + } } } } - private void WriteTouchPoints(long BasePosition, params HidTouchPoint[] Points) - { - long TouchScreenOffset = BasePosition + HidTouchScreenOffset; - - long Timestamp = GetTimestamp(); - - CurrTouchEntry = (CurrTouchEntry + 1) % HidEntryCount; - - Ns.Memory.WriteInt64(TouchScreenOffset + 0x0, Timestamp); - Ns.Memory.WriteInt64(TouchScreenOffset + 0x8, HidEntryCount); - Ns.Memory.WriteInt64(TouchScreenOffset + 0x10, CurrTouchEntry); - Ns.Memory.WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1); - Ns.Memory.WriteInt64(TouchScreenOffset + 0x20, Timestamp); - - long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize; - - TouchEntryOffset += CurrTouchEntry * HidTouchEntrySize; - - Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, CurrTouchSampleCounter++); - Ns.Memory.WriteInt64(TouchEntryOffset + 0x8, Points.Length); - - TouchEntryOffset += HidTouchEntryHeaderSize; - - const int Padding = 0; - - int Index = 0; - - foreach (HidTouchPoint Point in Points) - { - Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, Timestamp); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x8, Padding); - Ns.Memory.WriteInt32(TouchEntryOffset + 0xc, Index++); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x10, Point.X); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x14, Point.Y); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x20, Point.Angle); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x24, Padding); - - TouchEntryOffset += HidTouchEntryTouchSize; - } - } - private long GetTimestamp() { return Environment.TickCount * 19_200; diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index fa204460f..943b8e510 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Core.Loaders if (Exe.Mod0Offset == 0) { - int BssOffset = Exe.DataOffset + Exe.Data.Count; + int BssOffset = Exe.DataOffset + Exe.Data.Length; int BssSize = Exe.BssSize; MapBss(ImageBase + BssOffset, BssSize); @@ -92,18 +92,15 @@ namespace Ryujinx.Core.Loaders private void WriteData( long Position, - IList Data, + byte[] Data, MemoryType Type, AMemoryPerm Perm) { - Memory.Manager.Map(Position, Data.Count, (int)Type, AMemoryPerm.Write); + Memory.Manager.Map(Position, Data.Length, (int)Type, AMemoryPerm.Write); - for (int Index = 0; Index < Data.Count; Index++) - { - Memory.WriteByte(Position + Index, Data[Index]); - } + AMemoryHelper.WriteBytes(Memory, Position, Data); - Memory.Manager.Reprotect(Position, Data.Count, Perm); + Memory.Manager.Reprotect(Position, Data.Length, Perm); } private void MapBss(long Position, long Size) diff --git a/Ryujinx.Core/Loaders/Executables/IExecutable.cs b/Ryujinx.Core/Loaders/Executables/IExecutable.cs index 73787b1d2..09d0aab23 100644 --- a/Ryujinx.Core/Loaders/Executables/IExecutable.cs +++ b/Ryujinx.Core/Loaders/Executables/IExecutable.cs @@ -1,12 +1,10 @@ -using System.Collections.ObjectModel; - namespace Ryujinx.Core.Loaders.Executables { public interface IExecutable { - ReadOnlyCollection Text { get; } - ReadOnlyCollection RO { get; } - ReadOnlyCollection Data { get; } + byte[] Text { get; } + byte[] RO { get; } + byte[] Data { get; } int Mod0Offset { get; } int TextOffset { get; } diff --git a/Ryujinx.Core/Loaders/Executables/Nro.cs b/Ryujinx.Core/Loaders/Executables/Nro.cs index 3cbc4c5d4..9f4ef59f5 100644 --- a/Ryujinx.Core/Loaders/Executables/Nro.cs +++ b/Ryujinx.Core/Loaders/Executables/Nro.cs @@ -1,18 +1,12 @@ -using System; -using System.Collections.ObjectModel; using System.IO; namespace Ryujinx.Core.Loaders.Executables { class Nro : IExecutable { - private byte[] m_Text; - private byte[] m_RO; - private byte[] m_Data; - - public ReadOnlyCollection Text => Array.AsReadOnly(m_Text); - public ReadOnlyCollection RO => Array.AsReadOnly(m_RO); - public ReadOnlyCollection Data => Array.AsReadOnly(m_Data); + public byte[] Text { get; private set; } + public byte[] RO { get; private set; } + public byte[] Data { get; private set; } public int Mod0Offset { get; private set; } public int TextOffset { get; private set; } @@ -54,9 +48,9 @@ namespace Ryujinx.Core.Loaders.Executables return Reader.ReadBytes(Size); } - m_Text = Read(TextOffset, TextSize); - m_RO = Read(ROOffset, ROSize); - m_Data = Read(DataOffset, DataSize); + Text = Read(TextOffset, TextSize); + RO = Read(ROOffset, ROSize); + Data = Read(DataOffset, DataSize); } } } \ No newline at end of file diff --git a/Ryujinx.Core/Loaders/Executables/Nso.cs b/Ryujinx.Core/Loaders/Executables/Nso.cs index 7b8bf253a..7341ba622 100644 --- a/Ryujinx.Core/Loaders/Executables/Nso.cs +++ b/Ryujinx.Core/Loaders/Executables/Nso.cs @@ -1,19 +1,14 @@ using Ryujinx.Core.Loaders.Compression; using System; -using System.Collections.ObjectModel; using System.IO; namespace Ryujinx.Core.Loaders.Executables { class Nso : IExecutable { - private byte[] m_Text; - private byte[] m_RO; - private byte[] m_Data; - - public ReadOnlyCollection Text => Array.AsReadOnly(m_Text); - public ReadOnlyCollection RO => Array.AsReadOnly(m_RO); - public ReadOnlyCollection Data => Array.AsReadOnly(m_Data); + public byte[] Text { get; private set; } + public byte[] RO { get; private set; } + public byte[] Data { get; private set; } public int Mod0Offset { get; private set; } public int TextOffset { get; private set; } @@ -57,9 +52,9 @@ namespace Ryujinx.Core.Loaders.Executables byte[] BuildId = Reader.ReadBytes(0x20); - int TextSize = Reader.ReadInt32(); - int ROSize = Reader.ReadInt32(); - int DataSize = Reader.ReadInt32(); + int TextSize = Reader.ReadInt32(); + int ROSize = Reader.ReadInt32(); + int DataSize = Reader.ReadInt32(); Input.Seek(0x24, SeekOrigin.Current); @@ -82,38 +77,38 @@ namespace Ryujinx.Core.Loaders.Executables //Text segment Input.Seek(TextOffset, SeekOrigin.Begin); - m_Text = Reader.ReadBytes(TextSize); + Text = Reader.ReadBytes(TextSize); if (Flags.HasFlag(NsoFlags.IsTextCompressed) || true) { - m_Text = Lz4.Decompress(m_Text, TextDecSize); + Text = Lz4.Decompress(Text, TextDecSize); } //Read-only data segment Input.Seek(ROOffset, SeekOrigin.Begin); - m_RO = Reader.ReadBytes(ROSize); + RO = Reader.ReadBytes(ROSize); if (Flags.HasFlag(NsoFlags.IsROCompressed) || true) { - m_RO = Lz4.Decompress(m_RO, RODecSize); + RO = Lz4.Decompress(RO, RODecSize); } //Data segment Input.Seek(DataOffset, SeekOrigin.Begin); - m_Data = Reader.ReadBytes(DataSize); + Data = Reader.ReadBytes(DataSize); if (Flags.HasFlag(NsoFlags.IsDataCompressed) || true) { - m_Data = Lz4.Decompress(m_Data, DataDecSize); + Data = Lz4.Decompress(Data, DataDecSize); } - using (MemoryStream Text = new MemoryStream(m_Text)) + using (MemoryStream TextMS = new MemoryStream(Text)) { - BinaryReader TextReader = new BinaryReader(Text); + BinaryReader TextReader = new BinaryReader(TextMS); - Text.Seek(4, SeekOrigin.Begin); + TextMS.Seek(4, SeekOrigin.Begin); Mod0Offset = TextReader.ReadInt32(); } diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs index a8f5df7c9..c61e18e98 100644 --- a/Ryujinx.Core/OsHle/Horizon.cs +++ b/Ryujinx.Core/OsHle/Horizon.cs @@ -52,6 +52,8 @@ namespace Ryujinx.Core.OsHle HidHandle = Handles.GenerateId(HidSharedMem); FontHandle = Handles.GenerateId(new HSharedMem()); + + HidSharedMem.AddVirtualPosition(0); } public void LoadCart(string ExeFsDir, string RomFsFile = null) diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs index cc26df108..ebb3dbca0 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs @@ -217,16 +217,26 @@ namespace Ryujinx.Core.OsHle.Ipc public long GetSendBuffPtr() { - if (SendBuff.Count > 0 && SendBuff[0].Position != 0) + if (SendBuff.Count > 0 && SendBuff[0].Size != 0) { return SendBuff[0].Position; } - if (PtrBuff.Count > 0 && PtrBuff[0].Position != 0) + if (PtrBuff.Count > 0 && PtrBuff[0].Size != 0) { return PtrBuff[0].Position; } + if (ReceiveBuff.Count > 0 && ReceiveBuff[0].Size != 0) + { + return ReceiveBuff[0].Position; + } + + if (RecvListBuff.Count > 0 && RecvListBuff[0].Size != 0) + { + return RecvListBuff[0].Position; + } + return -1; } } diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs index 515c15e03..3c0c46fec 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs @@ -81,7 +81,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices FileDesc FdData = Context.Ns.Os.Fds.GetData(Fd); - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); Context.ResponseData.Write(0); @@ -139,7 +139,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlBindChannel(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); int Fd = Context.Memory.ReadInt32(Position); @@ -148,7 +148,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlAllocSpace(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -174,7 +174,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlMapBufferEx(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -207,7 +207,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlGetVaRegions(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position); @@ -237,7 +237,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlInitializeEx(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -254,7 +254,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvHostIoctlCtrlGetConfig(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position + 0x82); @@ -269,7 +269,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvHostIoctlCtrlEventWait(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -285,7 +285,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); Context.Memory.WriteInt32(Position, 1); @@ -294,7 +294,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlZcullGetInfo(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemWriter Writer = new MemWriter(Context.Memory, Position); @@ -314,7 +314,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlGetCharacteristics(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position); @@ -376,7 +376,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlGetTpcMasks(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -390,7 +390,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); Context.Memory.WriteInt32(Position + 0, 7); Context.Memory.WriteInt32(Position + 4, 1); @@ -400,14 +400,14 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelSetUserData(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); return 0; } private static long NvMapIoctlChannelSetNvMap(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); int Fd = Context.Memory.ReadInt32(Position); @@ -416,7 +416,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position + 0x10); @@ -455,7 +455,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); int ClassNum = Context.Memory.ReadInt32(Position + 0); int Flags = Context.Memory.ReadInt32(Position + 4); @@ -467,7 +467,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelZcullBind(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -480,7 +480,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -494,7 +494,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelSetPriority(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); int Priority = Context.Memory.ReadInt32(Position); @@ -503,7 +503,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position + 0xc); diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index bf946e4f8..c15f449bf 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -55,6 +55,24 @@ namespace Ryujinx.Core.OsHle.Svc long Src = (long)ThreadState.X1; long Size = (long)ThreadState.X2; + if (!IsValidPosition(Src)) + { + Logging.Warn($"Tried to map Memory at invalid src address {Src:x16}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); + + return; + } + + if (!IsValidMapPosition(Dst)) + { + Logging.Warn($"Tried to map Memory at invalid dst address {Dst:x16}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); + + return; + } + AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src); Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm); @@ -72,6 +90,24 @@ namespace Ryujinx.Core.OsHle.Svc long Src = (long)ThreadState.X1; long Size = (long)ThreadState.X2; + if (!IsValidPosition(Src)) + { + Logging.Warn($"Tried to unmap Memory at invalid src address {Src:x16}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); + + return; + } + + if (!IsValidMapPosition(Dst)) + { + Logging.Warn($"Tried to unmap Memory at invalid dst address {Dst:x16}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); + + return; + } + AMemoryMapInfo DstInfo = Memory.Manager.GetMapInfo(Dst); Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory); @@ -92,9 +128,11 @@ namespace Ryujinx.Core.OsHle.Svc if (MapInfo == null) { - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); + long AddrSpaceEnd = MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize; - return; + long ReservedSize = (long)(ulong.MaxValue - (ulong)AddrSpaceEnd) + 1; + + MapInfo = new AMemoryMapInfo(AddrSpaceEnd, ReservedSize, (int)MemoryType.Reserved, 0, AMemoryPerm.None); } Memory.WriteInt64(InfoPtr + 0x00, MapInfo.Position); @@ -118,15 +156,26 @@ namespace Ryujinx.Core.OsHle.Svc long Size = (long)ThreadState.X2; int Perm = (int)ThreadState.X3; + if (!IsValidPosition(Src)) + { + Logging.Warn($"Tried to map SharedMemory at invalid address {Src:x16}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); + + return; + } + HSharedMem SharedMem = Ns.Os.Handles.GetData(Handle); if (SharedMem != null) { + Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, AMemoryPerm.Write); + AMemoryHelper.FillWithZeros(Memory, Src, (int)Size); - SharedMem.AddVirtualPosition(Src); + Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm); - Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm); + SharedMem.AddVirtualPosition(Src); ThreadState.X0 = 0; } @@ -136,14 +185,25 @@ namespace Ryujinx.Core.OsHle.Svc private void SvcUnmapSharedMemory(AThreadState ThreadState) { - int Handle = (int)ThreadState.X0; - long Position = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; + int Handle = (int)ThreadState.X0; + long Src = (long)ThreadState.X1; + long Size = (long)ThreadState.X2; + + if (!IsValidPosition(Src)) + { + Logging.Warn($"Tried to unmap SharedMemory at invalid address {Src:x16}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); + + return; + } HSharedMem HndData = Ns.Os.Handles.GetData(Handle); if (HndData != null) { + Memory.Manager.Unmap(Src, Size, (int)MemoryType.SharedMemory); + ThreadState.X0 = 0; } @@ -152,20 +212,41 @@ namespace Ryujinx.Core.OsHle.Svc private void SvcCreateTransferMemory(AThreadState ThreadState) { - long Position = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; - int Perm = (int)ThreadState.X3; + long Src = (long)ThreadState.X1; + long Size = (long)ThreadState.X2; + int Perm = (int)ThreadState.X3; - AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position); + if (!IsValidPosition(Src)) + { + Logging.Warn($"Tried to create TransferMemory at invalid address {Src:x16}!"); - Memory.Manager.Reprotect(Position, Size, (AMemoryPerm)Perm); + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange); - HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Position, Size); + return; + } + + AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Src); + + Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm); + + HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Src, Size); int Handle = Ns.Os.Handles.GenerateId(HndData); ThreadState.X1 = (ulong)Handle; ThreadState.X0 = 0; } + + private static bool IsValidPosition(long Position) + { + return Position >= MemoryRegions.AddrSpaceStart && + Position < MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize; + } + + private static bool IsValidMapPosition(long Position) + { + return Position >= MemoryRegions.MapRegionAddress && + Position < MemoryRegions.MapRegionAddress + MemoryRegions.MapRegionSize; + } } } \ No newline at end of file diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index dff7802b7..f7ce109f6 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -30,7 +30,7 @@ namespace Ryujinx.Core VFs = new VirtualFs(); - Hid = new Hid(this); + Hid = new Hid(Memory); Statistics = new PerformanceStatistics(); diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index c4f0bbd74..0b35a7a6c 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -47,7 +47,7 @@ namespace Ryujinx.Tests.Cpu protected void Opcode(uint Opcode) { - Thread.Memory.WriteUInt32(Position, Opcode); + Thread.Memory.WriteUInt32Unchecked(Position, Opcode); Position += 4; } diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs index b5f8cb976..b67e52bdc 100644 --- a/Ryujinx/Ui/Program.cs +++ b/Ryujinx/Ui/Program.cs @@ -10,6 +10,8 @@ namespace Ryujinx { static void Main(string[] args) { + AOptimizations.DisableMemoryChecks = true; + Config.Read(); Console.Title = "Ryujinx Console"; From 28275a897696a707e222ee14dce20d4b8f65ed58 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 10 Mar 2018 20:51:55 -0300 Subject: [PATCH 63/67] Do not sign-extend timestamps --- ChocolArm64/State/AThreadState.cs | 6 +++--- Ryujinx.Core/Hid/Hid.cs | 4 ++-- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ChocolArm64/State/AThreadState.cs b/ChocolArm64/State/AThreadState.cs index 2d988a653..d86f5bf9c 100644 --- a/ChocolArm64/State/AThreadState.cs +++ b/ChocolArm64/State/AThreadState.cs @@ -38,10 +38,10 @@ namespace ChocolArm64.State public uint CtrEl0 => 0x8444c004; public uint DczidEl0 => 0x00000004; - private const long TicksPerS = 19_200_000; - private const long TicksPerMS = TicksPerS / 1_000; + private const ulong TicksPerS = 19_200_000; + private const ulong TicksPerMS = TicksPerS / 1_000; - public long CntpctEl0 => Environment.TickCount * TicksPerMS; + public ulong CntpctEl0 => (ulong)Environment.TickCount * TicksPerMS; public event EventHandler Break; public event EventHandler SvcCall; diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs index 76ecf5ffd..c287564d3 100644 --- a/Ryujinx.Core/Hid/Hid.cs +++ b/Ryujinx.Core/Hid/Hid.cs @@ -258,9 +258,9 @@ namespace Ryujinx.Core.Input } } - private long GetTimestamp() + private static long GetTimestamp() { - return Environment.TickCount * 19_200; + return (long)((ulong)Environment.TickCount * 19_200); } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index a276fe3c8..f70090352 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -67,7 +67,7 @@ namespace Ryujinx.Core.OsHle.Svc private void SvcGetSystemTick(AThreadState ThreadState) { - ThreadState.X0 = (ulong)ThreadState.CntpctEl0; + ThreadState.X0 = ThreadState.CntpctEl0; } private void SvcConnectToNamedPort(AThreadState ThreadState) From 3aaa4717b6f7400bac862e589a1f345e70e78d56 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Mon, 12 Mar 2018 02:05:39 +0100 Subject: [PATCH 64/67] Implement BSD Service (#54) * Implement BSD Service - Implementation of bsd:s & bsd:u. - Adding an EndianSwap class. * Corrections #1 * Correction2 --- Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs | 434 +++++++++++++++++- Ryujinx.Core/OsHle/Services/ServiceFactory.cs | 1 + Ryujinx.Core/OsHle/Utilities/EndianSwap.cs | 7 + 3 files changed, 423 insertions(+), 19 deletions(-) create mode 100644 Ryujinx.Core/OsHle/Utilities/EndianSwap.cs diff --git a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs index b59444127..da1e51e17 100644 --- a/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs +++ b/Ryujinx.Core/OsHle/Services/Bsd/ServiceBsd.cs @@ -1,14 +1,64 @@ +using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Ipc; +using Ryujinx.Core.OsHle.Utilities; +using System; using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading.Tasks; namespace Ryujinx.Core.OsHle.IpcServices.Bsd { + + //bsd_errno == (SocketException.ErrorCode - 10000) + //https://github.com/freebsd/freebsd/blob/master/sys/sys/errno.h + public enum BsdError + { + ENOTSOCK = 38, /* Socket operation on non-socket */ + EDESTADDRREQ = 39, /* Destination address required */ + EMSGSIZE = 40, /* Message too long */ + EPROTOTYPE = 41, /* Protocol wrong type for socket */ + ENOPROTOOPT = 42, /* Protocol not available */ + EPROTONOSUPPORT = 43, /* Protocol not supported */ + ESOCKTNOSUPPORT = 44, /* Socket type not supported */ + EOPNOTSUPP = 45, /* Operation not supported */ + EPFNOSUPPORT = 46, /* Protocol family not supported */ + EAFNOSUPPORT = 47, /* Address family not supported by protocol family */ + EADDRINUSE = 48, /* Address already in use */ + EADDRNOTAVAIL = 49, /* Can't assign requested address */ + ENETDOWN = 50, /* Network is down */ + ENETUNREACH = 51, /* Network is unreachable */ + ENETRESET = 52, /* Network dropped connection on reset */ + ECONNABORTED = 53, /* Software caused connection abort */ + ECONNRESET = 54, /* Connection reset by peer */ + ENOBUFS = 55, /* No buffer space available */ + EISCONN = 56, /* Socket is already connected */ + ENOTCONN = 57, /* Socket is not connected */ + ESHUTDOWN = 58, /* Can't send after socket shutdown */ + ETOOMANYREFS = 59, /* Too many references: can't splice */ + ETIMEDOUT = 60, /* Operation timed out */ + ECONNREFUSED = 61 /* Connection refused */ + } + + class SocketBsd + { + public int Family; + public int Type; + public int Protocol; + public IPAddress IpAddress; + public IPEndPoint RemoteEP; + public Socket Handle; + } + class ServiceBsd : IIpcService { private Dictionary m_Commands; public IReadOnlyDictionary Commands => m_Commands; + private List Sockets = new List(); + public ServiceBsd() { m_Commands = new Dictionary() @@ -16,26 +66,31 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd { 0, Initialize }, { 1, StartMonitoring }, { 2, Socket }, + { 6, Poll }, + { 8, Recv }, { 10, Send }, - { 14, Connect } + { 11, SendTo }, + { 12, Accept }, + { 13, Bind }, + { 14, Connect }, + { 18, Listen }, + { 21, SetSockOpt }, + { 26, Close } }; } - //Initialize(u32, u32, u32, u32, u32, u32, u32, u32, u64 pid, u64 transferMemorySize, pid, KObject) -> u32 bsd_errno + //(u32, u32, u32, u32, u32, u32, u32, u32, u64 pid, u64 transferMemorySize, pid, KObject) -> u32 bsd_errno public long Initialize(ServiceCtx Context) { /* typedef struct { u32 version; // Observed 1 on 2.0 LibAppletWeb, 2 on 3.0. - u32 tcp_tx_buf_size; // Size of the TCP transfer (send) buffer (initial or fixed). u32 tcp_rx_buf_size; // Size of the TCP recieve buffer (initial or fixed). u32 tcp_tx_buf_max_size; // Maximum size of the TCP transfer (send) buffer. If it is 0, the size of the buffer is fixed to its initial value. u32 tcp_rx_buf_max_size; // Maximum size of the TCP receive buffer. If it is 0, the size of the buffer is fixed to its initial value. - u32 udp_tx_buf_size; // Size of the UDP transfer (send) buffer (typically 0x2400 bytes). u32 udp_rx_buf_size; // Size of the UDP receive buffer (typically 0xA500 bytes). - u32 sb_efficiency; // Number of buffers for each socket (standard values range from 1 to 8). } BsdBufferConfig; */ @@ -52,7 +107,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd return 0; } - //StartMonitoring(u64, pid) + //(u64, pid) public long StartMonitoring(ServiceCtx Context) { //Todo: Stub @@ -60,37 +115,378 @@ namespace Ryujinx.Core.OsHle.IpcServices.Bsd return 0; } - //Socket(u32 domain, u32 type, u32 protocol) -> (i32 ret, u32 bsd_errno) + //(u32 domain, u32 type, u32 protocol) -> (i32 ret, u32 bsd_errno) public long Socket(ServiceCtx Context) { - Context.ResponseData.Write(0); - Context.ResponseData.Write(0); + SocketBsd NewBSDSocket = new SocketBsd + { + Family = Context.RequestData.ReadInt32(), + Type = Context.RequestData.ReadInt32(), + Protocol = Context.RequestData.ReadInt32() + }; - //Todo: Stub + Sockets.Add(NewBSDSocket); + + Sockets[Sockets.Count - 1].Handle = new Socket((AddressFamily)Sockets[Sockets.Count - 1].Family, + (SocketType)Sockets[Sockets.Count - 1].Type, + (ProtocolType)Sockets[Sockets.Count - 1].Protocol); + + Context.ResponseData.Write(Sockets.Count - 1); + Context.ResponseData.Write(0); return 0; } - //Connect(u32 socket, buffer) -> (i32 ret, u32 bsd_errno) - public long Connect(ServiceCtx Context) + //(u32, u32, buffer) -> (i32 ret, u32 bsd_errno, buffer) + public long Poll(ServiceCtx Context) { - Context.ResponseData.Write(0); - Context.ResponseData.Write(0); + int PollCount = Context.RequestData.ReadInt32(); + int TimeOut = Context.RequestData.ReadInt32(); - //Todo: Stub + //https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h + //https://msdn.microsoft.com/fr-fr/library/system.net.sockets.socket.poll(v=vs.110).aspx + //https://github.com/switchbrew/libnx/blob/e0457c4534b3c37426d83e1a620f82cb28c3b528/nx/source/services/bsd.c#L343 + //https://github.com/TuxSH/ftpd/blob/switch_pr/source/ftp.c#L1634 + //https://linux.die.net/man/2/poll + + byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory, + Context.Request.SendBuff[0].Position, + (int)Context.Request.SendBuff[0].Size); + int SocketId = Get32(SentBuffer, 0); + short RequestedEvents = (short)Get16(SentBuffer, 4); + short ReturnedEvents = (short)Get16(SentBuffer, 6); + + //Todo: Stub - Need to implemented the Type-22 buffer. + + Context.ResponseData.Write(1); + Context.ResponseData.Write(0); return 0; } - //Send(u32 socket, u32 flags, buffer) -> (i32 ret, u32 bsd_errno) + //(u32 socket, u32 flags) -> (i32 ret, u32 bsd_errno, buffer message) + public long Recv(ServiceCtx Context) + { + try + { + int SocketId = Context.RequestData.ReadInt32(); + int SocketFlags = Context.RequestData.ReadInt32(); + byte[] ReceivedBuffer = new byte[Context.Request.ReceiveBuff[0].Size]; + int ReadedBytes = Sockets[SocketId].Handle.Receive(ReceivedBuffer); + + //Logging.Debug("Received Buffer:" + Environment.NewLine + Logging.HexDump(ReceivedBuffer)); + + AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, ReceivedBuffer); + + Context.ResponseData.Write(ReadedBytes); + Context.ResponseData.Write(0); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + + return 0; + } + + //(u32 socket, u32 flags, buffer) -> (i32 ret, u32 bsd_errno) public long Send(ServiceCtx Context) { - Context.ResponseData.Write(0); - Context.ResponseData.Write(0); + int SocketId = Context.RequestData.ReadInt32(); + int SocketFlags = Context.RequestData.ReadInt32(); + byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory, + Context.Request.SendBuff[0].Position, + (int)Context.Request.SendBuff[0].Size); - //Todo: Stub + try + { + //Logging.Debug("Sended Buffer:" + Environment.NewLine + Logging.HexDump(SendedBuffer)); + + int BytesSent = Sockets[SocketId].Handle.Send(SentBuffer); + + Context.ResponseData.Write(BytesSent); + Context.ResponseData.Write(0); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } return 0; } + + //(u32 socket, u32 flags, buffer, buffer) -> (i32 ret, u32 bsd_errno) + public long SendTo(ServiceCtx Context) + { + int SocketId = Context.RequestData.ReadInt32(); + int SocketFlags = Context.RequestData.ReadInt32(); + byte[] SentBuffer = AMemoryHelper.ReadBytes(Context.Memory, + Context.Request.SendBuff[0].Position, + (int)Context.Request.SendBuff[0].Size); + byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory, + Context.Request.SendBuff[1].Position, + (int)Context.Request.SendBuff[1].Size); + + if (!Sockets[SocketId].Handle.Connected) + { + try + { + ParseAddrBuffer(SocketId, AddressBuffer); + + Sockets[SocketId].Handle.Connect(Sockets[SocketId].RemoteEP); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + } + + try + { + //Logging.Debug("Sended Buffer:" + Environment.NewLine + Logging.HexDump(SendedBuffer)); + + int BytesSent = Sockets[SocketId].Handle.Send(SentBuffer); + + Context.ResponseData.Write(BytesSent); + Context.ResponseData.Write(0); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + + return 0; + } + + //(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer addr) + public long Accept(ServiceCtx Context) + { + int SocketId = Context.RequestData.ReadInt32(); + long AddrBufferPtr = Context.Request.ReceiveBuff[0].Position; + + Socket HandleAccept = null; + + var TimeOut = Task.Factory.StartNew(() => + { + try + { + HandleAccept = Sockets[SocketId].Handle.Accept(); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + }); + + TimeOut.Wait(10000); + + if (HandleAccept != null) + { + SocketBsd NewBSDSocket = new SocketBsd + { + IpAddress = ((IPEndPoint)Sockets[SocketId].Handle.LocalEndPoint).Address, + RemoteEP = ((IPEndPoint)Sockets[SocketId].Handle.LocalEndPoint), + Handle = HandleAccept + }; + + Sockets.Add(NewBSDSocket); + + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + Writer.Write((byte)0); + Writer.Write((byte)Sockets[Sockets.Count - 1].Handle.AddressFamily); + Writer.Write((Int16)((IPEndPoint)Sockets[Sockets.Count - 1].Handle.LocalEndPoint).Port); + + string[] IpAdress = Sockets[Sockets.Count - 1].IpAddress.ToString().Split('.'); + Writer.Write(byte.Parse(IpAdress[0])); + Writer.Write(byte.Parse(IpAdress[1])); + Writer.Write(byte.Parse(IpAdress[2])); + Writer.Write(byte.Parse(IpAdress[3])); + + AMemoryHelper.WriteBytes(Context.Memory, AddrBufferPtr, MS.ToArray()); + + Context.ResponseData.Write(Sockets.Count - 1); + Context.ResponseData.Write(0); + Context.ResponseData.Write(MS.Length); + } + } + else + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write((int)BsdError.ETIMEDOUT); + } + + return 0; + } + + //(u32 socket, buffer) -> (i32 ret, u32 bsd_errno) + public long Bind(ServiceCtx Context) + { + int SocketId = Context.RequestData.ReadInt32(); + + byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory, + Context.Request.SendBuff[0].Position, + (int)Context.Request.SendBuff[0].Size); + + try + { + ParseAddrBuffer(SocketId, AddressBuffer); + + Context.ResponseData.Write(0); + Context.ResponseData.Write(0); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + + return 0; + } + + //(u32 socket, buffer) -> (i32 ret, u32 bsd_errno) + public long Connect(ServiceCtx Context) + { + int SocketId = Context.RequestData.ReadInt32(); + + byte[] AddressBuffer = AMemoryHelper.ReadBytes(Context.Memory, + Context.Request.SendBuff[0].Position, + (int)Context.Request.SendBuff[0].Size); + + try + { + ParseAddrBuffer(SocketId, AddressBuffer); + + Sockets[SocketId].Handle.Connect(Sockets[SocketId].RemoteEP); + + Context.ResponseData.Write(0); + Context.ResponseData.Write(0); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + + return 0; + } + + //(u32 socket, u32 backlog) -> (i32 ret, u32 bsd_errno) + public long Listen(ServiceCtx Context) + { + int SocketId = Context.RequestData.ReadInt32(); + int BackLog = Context.RequestData.ReadInt32(); + + try + { + Sockets[SocketId].Handle.Bind(Sockets[SocketId].RemoteEP); + Sockets[SocketId].Handle.Listen(BackLog); + + Context.ResponseData.Write(0); + Context.ResponseData.Write(0); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + + return 0; + } + + //(u32 socket, u32 level, u32 option_name, buffer) -> (i32 ret, u32 bsd_errno) + public long SetSockOpt(ServiceCtx Context) + { + int SocketId = Context.RequestData.ReadInt32(); + int SocketLevel = Context.RequestData.ReadInt32(); + int SocketOptionName = Context.RequestData.ReadInt32(); + + byte[] SocketOptionValue = AMemoryHelper.ReadBytes(Context.Memory, + Context.Request.PtrBuff[0].Position, + Context.Request.PtrBuff[0].Size); + + try + { + Sockets[SocketId].Handle.SetSocketOption((SocketOptionLevel)SocketLevel, + (SocketOptionName)SocketOptionName, + Get32(SocketOptionValue, 0)); + + Context.ResponseData.Write(0); + Context.ResponseData.Write(0); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + + return 0; + } + + //(u32 socket) -> (i32 ret, u32 bsd_errno) + public long Close(ServiceCtx Context) + { + int SocketId = Context.RequestData.ReadInt32(); + + try + { + Sockets[SocketId].Handle.Close(); + Sockets[SocketId] = null; + + Context.ResponseData.Write(0); + Context.ResponseData.Write(0); + } + catch (SocketException Ex) + { + Context.ResponseData.Write(-1); + Context.ResponseData.Write(Ex.ErrorCode - 10000); + } + + return 0; + } + + public void ParseAddrBuffer(int SocketId, byte[] AddrBuffer) + { + using (MemoryStream MS = new MemoryStream(AddrBuffer)) + { + BinaryReader Reader = new BinaryReader(MS); + + int Size = Reader.ReadByte(); + int Family = Reader.ReadByte(); + int Port = EndianSwap.Swap16(Reader.ReadInt16()); + string IpAddress = Reader.ReadByte().ToString() + + "." + Reader.ReadByte().ToString() + + "." + Reader.ReadByte().ToString() + + "." + Reader.ReadByte().ToString(); + + Logging.Debug($"Try to connect to {IpAddress}:{Port}"); + + Sockets[SocketId].IpAddress = IPAddress.Parse(IpAddress); + Sockets[SocketId].RemoteEP = new IPEndPoint(Sockets[SocketId].IpAddress, Port); + } + } + + private int Get16(byte[] Data, int Address) + { + return + Data[Address + 0] << 0 | + Data[Address + 1] << 8; + } + + private int Get32(byte[] Data, int Address) + { + return + Data[Address + 0] << 0 | + Data[Address + 1] << 8 | + Data[Address + 2] << 16 | + Data[Address + 3] << 24; + } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs index 31c8aa2c8..2b855d25b 100644 --- a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs @@ -35,6 +35,7 @@ namespace Ryujinx.Core.OsHle.IpcServices case "appletOE": return new ServiceAppletOE(); case "audout:u": return new ServiceAudOut(); case "audren:u": return new ServiceAudRen(); + case "bsd:s": return new ServiceBsd(); case "bsd:u": return new ServiceBsd(); case "friend:a": return new ServiceFriend(); case "fsp-srv": return new ServiceFspSrv(); diff --git a/Ryujinx.Core/OsHle/Utilities/EndianSwap.cs b/Ryujinx.Core/OsHle/Utilities/EndianSwap.cs new file mode 100644 index 000000000..6758f1f2f --- /dev/null +++ b/Ryujinx.Core/OsHle/Utilities/EndianSwap.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.Core.OsHle.Utilities +{ + static class EndianSwap + { + public static short Swap16(short Value) => (short)(((Value >> 8) & 0xff) | (Value << 8)); + } +} From 7a27990faa557c5c93f52e5cb082d551ad119ed0 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 12 Mar 2018 01:04:52 -0300 Subject: [PATCH 65/67] Allow more than one process, free resources on process dispose, implement SvcExitThread --- ChocolArm64/AThread.cs | 29 +- ChocolArm64/ATranslator.cs | 8 +- ChocolArm64/Instruction/AInstEmitException.cs | 16 ++ ChocolArm64/State/AThreadState.cs | 2 + Ryujinx.Core/Hid/Hid.cs | 30 +- Ryujinx.Core/Logging.cs | 7 +- Ryujinx.Core/OsHle/CondVar.cs | 2 +- Ryujinx.Core/OsHle/Handles/HDomain.cs | 62 ++-- Ryujinx.Core/OsHle/Handles/HNvMap.cs | 18 -- Ryujinx.Core/OsHle/Handles/HSharedMem.cs | 15 +- .../OsHle/Handles/KProcessHandleTable.cs | 63 +++++ Ryujinx.Core/OsHle/Homebrew.cs | 28 ++ Ryujinx.Core/OsHle/Horizon.cs | 139 ++++----- .../IdPoolWithObj.cs => IdDictionary.cs} | 59 ++-- Ryujinx.Core/OsHle/Ipc/IpcHandler.cs | 75 +++-- Ryujinx.Core/OsHle/Ipc/IpcMessageType.cs | 8 +- Ryujinx.Core/OsHle/Mutex.cs | 2 +- Ryujinx.Core/OsHle/Process.cs | 145 ++++++---- Ryujinx.Core/OsHle/ServiceCtx.cs | 3 + Ryujinx.Core/OsHle/ServiceMgr.cs | 109 +++++++ Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs | 2 +- .../OsHle/Services/Aud/IAudioRenderer.cs | 2 +- .../OsHle/Services/Hid/IAppletResource.cs | 12 +- Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs | 5 +- Ryujinx.Core/OsHle/Services/Nv/NvFd.cs | 12 + Ryujinx.Core/OsHle/Services/Nv/NvMap.cs | 12 + .../OsHle/Services/Nv/ServiceNvDrv.cs | 266 +++++++++++------- Ryujinx.Core/OsHle/Services/ObjHelper.cs | 4 +- Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs | 12 +- Ryujinx.Core/OsHle/Services/ServiceFactory.cs | 64 ----- Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs | 4 +- .../OsHle/{ => Services/Vi}/Display.cs | 2 +- .../Services/Vi/IApplicationDisplayService.cs | 24 +- .../OsHle/Services/Vi/IHOSBinderDriver.cs | 5 +- Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 63 ++++- Ryujinx.Core/OsHle/Svc/SvcHandler.cs | 33 ++- Ryujinx.Core/OsHle/Svc/SvcMemory.cs | 28 +- Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 21 +- Ryujinx.Core/OsHle/Svc/SvcThread.cs | 15 +- Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs | 4 +- Ryujinx.Core/OsHle/Utilities/IdPool.cs | 53 ---- Ryujinx.Core/Switch.cs | 19 +- Ryujinx.Graphics/Gal/IGalRenderer.cs | 1 + Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs | 34 ++- Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 5 + Ryujinx.Tests/Cpu/CpuTest.cs | 2 +- 46 files changed, 926 insertions(+), 598 deletions(-) delete mode 100644 Ryujinx.Core/OsHle/Handles/HNvMap.cs create mode 100644 Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs rename Ryujinx.Core/OsHle/{Utilities/IdPoolWithObj.cs => IdDictionary.cs} (50%) create mode 100644 Ryujinx.Core/OsHle/ServiceMgr.cs create mode 100644 Ryujinx.Core/OsHle/Services/Nv/NvFd.cs create mode 100644 Ryujinx.Core/OsHle/Services/Nv/NvMap.cs delete mode 100644 Ryujinx.Core/OsHle/Services/ServiceFactory.cs rename Ryujinx.Core/OsHle/{ => Services/Vi}/Display.cs (79%) delete mode 100644 Ryujinx.Core/OsHle/Utilities/IdPool.cs diff --git a/ChocolArm64/AThread.cs b/ChocolArm64/AThread.cs index cec268175..62f9d2d39 100644 --- a/ChocolArm64/AThread.cs +++ b/ChocolArm64/AThread.cs @@ -14,43 +14,30 @@ namespace ChocolArm64 private ATranslator Translator; - private ThreadPriority Priority; - private Thread Work; public event EventHandler WorkFinished; public int ThreadId => ThreadState.ThreadId; - public bool IsAlive => Work.IsAlive; + private int IsExecuting; - private bool IsExecuting; - - private object ExecuteLock; - - public AThread(ATranslator Translator, AMemory Memory, ThreadPriority Priority, long EntryPoint) + public AThread(ATranslator Translator, AMemory Memory, long EntryPoint) { this.Translator = Translator; this.Memory = Memory; - this.Priority = Priority; this.EntryPoint = EntryPoint; ThreadState = new AThreadState(); - ExecuteLock = new object(); - } - public void StopExecution() => Translator.StopExecution(); + ThreadState.Running = true; + } public bool Execute() { - lock (ExecuteLock) + if (Interlocked.Exchange(ref IsExecuting, 1) == 1) { - if (IsExecuting) - { - return false; - } - - IsExecuting = true; + return false; } Work = new Thread(delegate() @@ -62,11 +49,11 @@ namespace ChocolArm64 WorkFinished?.Invoke(this, EventArgs.Empty); }); - Work.Priority = Priority; - Work.Start(); return true; } + + public void StopExecution() => ThreadState.Running = false; } } \ No newline at end of file diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs index 1f4a922ab..02c18efd2 100644 --- a/ChocolArm64/ATranslator.cs +++ b/ChocolArm64/ATranslator.cs @@ -22,8 +22,6 @@ namespace ChocolArm64 public bool EnableCpuTrace { get; set; } - private bool KeepRunning; - public ATranslator(IReadOnlyDictionary SymbolTable = null) { SubBlocks = new HashSet(); @@ -38,12 +36,8 @@ namespace ChocolArm64 { this.SymbolTable = new ConcurrentDictionary(); } - - KeepRunning = true; } - internal void StopExecution() => KeepRunning = false; - internal void ExecuteSubroutine(AThread Thread, long Position) { do @@ -70,7 +64,7 @@ namespace ChocolArm64 Position = Sub.Execute(Thread.ThreadState, Thread.Memory); } - while (Position != 0 && KeepRunning); + while (Position != 0 && Thread.ThreadState.Running); } internal bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) diff --git a/ChocolArm64/Instruction/AInstEmitException.cs b/ChocolArm64/Instruction/AInstEmitException.cs index fe348edd1..3964c9497 100644 --- a/ChocolArm64/Instruction/AInstEmitException.cs +++ b/ChocolArm64/Instruction/AInstEmitException.cs @@ -34,6 +34,22 @@ namespace ChocolArm64.Instruction Context.EmitCall(MthdInfo); + //Check if the thread should still be running, if it isn't then we return 0 + //to force a return to the dispatcher and then exit the thread. + Context.EmitLdarg(ATranslatedSub.StateArgIdx); + + Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Running)); + + AILLabel LblEnd = new AILLabel(); + + Context.Emit(OpCodes.Brtrue_S, LblEnd); + + Context.EmitLdc_I8(0); + + Context.Emit(OpCodes.Ret); + + Context.MarkLabel(LblEnd); + if (Context.CurrBlock.Next != null) { Context.EmitLoadState(Context.CurrBlock.Next); diff --git a/ChocolArm64/State/AThreadState.cs b/ChocolArm64/State/AThreadState.cs index d86f5bf9c..ec8621b89 100644 --- a/ChocolArm64/State/AThreadState.cs +++ b/ChocolArm64/State/AThreadState.cs @@ -29,6 +29,8 @@ namespace ChocolArm64.State public int ProcessId; public int ThreadId; + public bool Running { get; set; } + public long TpidrEl0 { get; set; } public long Tpidr { get; set; } diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs index c287564d3..f25a94375 100644 --- a/Ryujinx.Core/Hid/Hid.cs +++ b/Ryujinx.Core/Hid/Hid.cs @@ -63,17 +63,13 @@ namespace Ryujinx.Core.Input private object ShMemLock; - private long[] ShMemPositions; + private (AMemory, long)[] ShMemPositions; - private AMemory Memory; - - public Hid(AMemory Memory) + public Hid() { - this.Memory = Memory; - ShMemLock = new object(); - ShMemPositions = new long[0]; + ShMemPositions = new (AMemory, long)[0]; } internal void ShMemMap(object sender, EventArgs e) @@ -84,11 +80,11 @@ namespace Ryujinx.Core.Input { ShMemPositions = SharedMem.GetVirtualPositions(); - long BasePosition = ShMemPositions[ShMemPositions.Length - 1]; + (AMemory Memory, long Position) ShMem = ShMemPositions[ShMemPositions.Length - 1]; - Logging.Info($"HID shared memory successfully mapped to 0x{BasePosition:x16}!"); + Logging.Info($"HID shared memory successfully mapped to 0x{ShMem.Position:x16}!"); - Init(BasePosition); + Init(ShMem.Memory, ShMem.Position); } } @@ -102,10 +98,11 @@ namespace Ryujinx.Core.Input } } - private void Init(long BasePosition) + private void Init(AMemory Memory, long Position) { InitializeJoyconPair( - BasePosition, + Memory, + Position, JoyConColor.Body_Neon_Red, JoyConColor.Buttons_Neon_Red, JoyConColor.Body_Neon_Blue, @@ -113,13 +110,14 @@ namespace Ryujinx.Core.Input } private void InitializeJoyconPair( - long BasePosition, + AMemory Memory, + long Position, JoyConColor LeftColorBody, JoyConColor LeftColorButtons, JoyConColor RightColorBody, JoyConColor RightColorButtons) { - long BaseControllerOffset = BasePosition + HidControllersOffset + 8 * HidControllerSize; + long BaseControllerOffset = Position + HidControllersOffset + 8 * HidControllerSize; HidControllerType Type = HidControllerType.ControllerType_Handheld | @@ -160,7 +158,7 @@ namespace Ryujinx.Core.Input { lock (ShMemLock) { - foreach (long Position in ShMemPositions) + foreach ((AMemory Memory, long Position) in ShMemPositions) { long ControllerOffset = Position + HidControllersOffset; @@ -207,7 +205,7 @@ namespace Ryujinx.Core.Input { lock (ShMemLock) { - foreach (long Position in ShMemPositions) + foreach ((AMemory Memory, long Position) in ShMemPositions) { long TouchScreenOffset = Position + HidTouchScreenOffset; diff --git a/Ryujinx.Core/Logging.cs b/Ryujinx.Core/Logging.cs index d544a5d64..89064ccbc 100644 --- a/Ryujinx.Core/Logging.cs +++ b/Ryujinx.Core/Logging.cs @@ -8,7 +8,8 @@ namespace Ryujinx.Core { public static class Logging { - private static Stopwatch ExecutionTime = new Stopwatch(); + private static Stopwatch ExecutionTime; + private const string LogFileName = "Ryujinx.log"; private static bool EnableInfo = Config.LoggingEnableInfo; @@ -23,6 +24,10 @@ namespace Ryujinx.Core static Logging() { if (File.Exists(LogFileName)) File.Delete(LogFileName); + + ExecutionTime = new Stopwatch(); + + ExecutionTime.Start(); } public static string GetExecutionTime() diff --git a/Ryujinx.Core/OsHle/CondVar.cs b/Ryujinx.Core/OsHle/CondVar.cs index ac3ba5749..f5fe3d292 100644 --- a/Ryujinx.Core/OsHle/CondVar.cs +++ b/Ryujinx.Core/OsHle/CondVar.cs @@ -4,7 +4,7 @@ using System.Threading; namespace Ryujinx.Core.OsHle { - public class CondVar + class CondVar { private Process Process; diff --git a/Ryujinx.Core/OsHle/Handles/HDomain.cs b/Ryujinx.Core/OsHle/Handles/HDomain.cs index ca287a5fd..ac99b03a6 100644 --- a/Ryujinx.Core/OsHle/Handles/HDomain.cs +++ b/Ryujinx.Core/OsHle/Handles/HDomain.cs @@ -1,58 +1,48 @@ -using Ryujinx.Core.OsHle.Utilities; using System; -using System.Collections.Generic; namespace Ryujinx.Core.OsHle.Handles { - class HDomain : HSession + class HDomain : HSession, IDisposable { - private Dictionary Objects; - - private IdPool ObjIds; + private IdDictionary Objects; public HDomain(HSession Session) : base(Session) { - Objects = new Dictionary(); - - ObjIds = new IdPool(); + Objects = new IdDictionary(); } - public int GenerateObjectId(object Obj) + public int Add(object Obj) { - int Id = ObjIds.GenerateId(); - - if (Id == -1) - { - throw new InvalidOperationException(); - } - - Objects.Add(Id, Obj); - - return Id; + return Objects.Add(Obj); } - public void DeleteObject(int Id) + public bool Delete(int Id) { - if (Objects.TryGetValue(Id, out object Obj)) - { - if (Obj is IDisposable DisposableObj) - { - DisposableObj.Dispose(); - } - - ObjIds.DeleteId(Id); - Objects.Remove(Id); - } + return Objects.Delete(Id); } public object GetObject(int Id) { - if (Objects.TryGetValue(Id, out object Obj)) - { - return Obj; - } + return Objects.GetData(Id); + } - return null; + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool Disposing) + { + if (Disposing) + { + foreach (object Obj in Objects) + { + if (Obj is IDisposable DisposableObj) + { + DisposableObj.Dispose(); + } + } + } } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Handles/HNvMap.cs b/Ryujinx.Core/OsHle/Handles/HNvMap.cs deleted file mode 100644 index 09173730b..000000000 --- a/Ryujinx.Core/OsHle/Handles/HNvMap.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Ryujinx.Core.OsHle.Handles -{ - class HNvMap - { - public int Id { get; private set; } - public int Size { get; private set; } - - public int Align { get; set; } - public int Kind { get; set; } - public long Address { get; set; } - - public HNvMap(int Id, int Size) - { - this.Id = Id; - this.Size = Size; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Handles/HSharedMem.cs b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs index eb173e965..b6bdc8987 100644 --- a/Ryujinx.Core/OsHle/Handles/HSharedMem.cs +++ b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs @@ -1,3 +1,4 @@ +using ChocolArm64.Memory; using System; using System.Collections.Generic; @@ -5,37 +6,37 @@ namespace Ryujinx.Core.OsHle.Handles { class HSharedMem { - private List Positions; + private List<(AMemory, long)> Positions; public EventHandler MemoryMapped; public EventHandler MemoryUnmapped; public HSharedMem() { - Positions = new List(); + Positions = new List<(AMemory, long)>(); } - public void AddVirtualPosition(long Position) + public void AddVirtualPosition(AMemory Memory, long Position) { lock (Positions) { - Positions.Add(Position); + Positions.Add((Memory, Position)); MemoryMapped?.Invoke(this, EventArgs.Empty); } } - public void RemoveVirtualPosition(long Position) + public void RemoveVirtualPosition(AMemory Memory, long Position) { lock (Positions) { - Positions.Remove(Position); + Positions.Remove((Memory, Position)); MemoryUnmapped?.Invoke(this, EventArgs.Empty); } } - public long[] GetVirtualPositions() + public (AMemory, long)[] GetVirtualPositions() { return Positions.ToArray(); } diff --git a/Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs b/Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs new file mode 100644 index 000000000..1156e035f --- /dev/null +++ b/Ryujinx.Core/OsHle/Handles/KProcessHandleTable.cs @@ -0,0 +1,63 @@ +using System; + +namespace Ryujinx.Core.OsHle.Handles +{ + class KProcessHandleTable : IDisposable + { + private IdDictionary Handles; + + public KProcessHandleTable() + { + Handles = new IdDictionary(); + } + + public int OpenHandle(object Obj) + { + return Handles.Add(Obj); + } + + public T GetData(int Handle) + { + return Handles.GetData(Handle); + } + + public bool ReplaceData(int Id, object Data) + { + return Handles.ReplaceData(Id, Data); + } + + public bool CloseHandle(int Handle) + { + object Data = Handles.GetData(Handle); + + if (Data is HTransferMem TMem) + { + TMem.Memory.Manager.Reprotect( + TMem.Position, + TMem.Size, + TMem.Perm); + } + + return Handles.Delete(Handle); + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool Disposing) + { + if (Disposing) + { + foreach (object Obj in Handles) + { + if (Obj is IDisposable DisposableObj) + { + DisposableObj.Dispose(); + } + } + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Homebrew.cs b/Ryujinx.Core/OsHle/Homebrew.cs index e2e95e4d4..2a717ca73 100644 --- a/Ryujinx.Core/OsHle/Homebrew.cs +++ b/Ryujinx.Core/OsHle/Homebrew.cs @@ -37,5 +37,33 @@ namespace Ryujinx.Core.OsHle Position += 0x18; } + + public static string ReadHbAbiNextLoadPath(AMemory Memory, long Position) + { + string FileName = null; + + while (true) + { + long Key = Memory.ReadInt64(Position); + + if (Key == 2) + { + long Value0 = Memory.ReadInt64(Position + 0x08); + long Value1 = Memory.ReadInt64(Position + 0x10); + + FileName = AMemoryHelper.ReadAsciiString(Memory, Value0, (int)(Value1 - Value0)); + + break; + } + else if (Key == 0) + { + break; + } + + Position += 0x18; + } + + return FileName; + } } } diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs index c61e18e98..c3f8cd8b0 100644 --- a/Ryujinx.Core/OsHle/Horizon.cs +++ b/Ryujinx.Core/OsHle/Horizon.cs @@ -1,33 +1,23 @@ using Ryujinx.Core.Loaders.Executables; using Ryujinx.Core.OsHle.Handles; -using Ryujinx.Core.OsHle.Utilities; using System; using System.Collections.Concurrent; using System.IO; namespace Ryujinx.Core.OsHle { - public class Horizon + public class Horizon : IDisposable { internal const int HidSize = 0x40000; internal const int FontSize = 0x50; - internal int HidHandle { get; private set; } - internal int FontHandle { get; private set; } - - internal IdPool IdGen { get; private set; } - internal IdPool NvMapIds { get; private set; } - - internal IdPoolWithObj Handles { get; private set; } - internal IdPoolWithObj Fds { get; private set; } - internal IdPoolWithObj Displays { get; private set; } - - public ConcurrentDictionary Mutexes { get; private set; } - public ConcurrentDictionary CondVars { get; private set; } + internal ConcurrentDictionary Mutexes { get; private set; } + internal ConcurrentDictionary CondVars { get; private set; } private ConcurrentDictionary Processes; internal HSharedMem HidSharedMem; + internal HSharedMem FontSharedMem; private Switch Ns; @@ -35,25 +25,13 @@ namespace Ryujinx.Core.OsHle { this.Ns = Ns; - IdGen = new IdPool(); - NvMapIds = new IdPool(); - - Handles = new IdPoolWithObj(); - Fds = new IdPoolWithObj(); - Displays = new IdPoolWithObj(); - Mutexes = new ConcurrentDictionary(); CondVars = new ConcurrentDictionary(); Processes = new ConcurrentDictionary(); - HidSharedMem = new HSharedMem(); - - HidHandle = Handles.GenerateId(HidSharedMem); - - FontHandle = Handles.GenerateId(new HSharedMem()); - - HidSharedMem.AddVirtualPosition(0); + HidSharedMem = new HSharedMem(); + FontSharedMem = new HSharedMem(); } public void LoadCart(string ExeFsDir, string RomFsFile = null) @@ -63,9 +41,7 @@ namespace Ryujinx.Core.OsHle Ns.VFs.LoadRomFs(RomFsFile); } - int ProcessId = IdGen.GenerateId(); - - Process MainProcess = new Process(Ns, ProcessId); + Process MainProcess = MakeProcess(); void LoadNso(string FileName) { @@ -96,17 +72,13 @@ namespace Ryujinx.Core.OsHle LoadNso("sdk"); MainProcess.Run(); - - Processes.TryAdd(ProcessId, MainProcess); } public void LoadProgram(string FileName) { bool IsNro = Path.GetExtension(FileName).ToLower() == ".nro"; - int ProcessId = IdGen.GenerateId(); - - Process MainProcess = new Process(Ns, ProcessId); + Process MainProcess = MakeProcess(); using (FileStream Input = new FileStream(FileName, FileMode.Open)) { @@ -117,34 +89,67 @@ namespace Ryujinx.Core.OsHle MainProcess.SetEmptyArgs(); MainProcess.Run(IsNro); - - Processes.TryAdd(ProcessId, MainProcess); } - public void FinalizeAllProcesses() + private Process MakeProcess() { - foreach (Process Process in Processes.Values) + Process Process; + + lock (Processes) { - Process.StopAllThreads(); + int ProcessId = 0; + + while (Processes.ContainsKey(ProcessId)) + { + ProcessId++; + } + + Process = new Process(Ns, ProcessId); + + Processes.TryAdd(ProcessId, Process); + } + + return Process; + } + + internal void ExitProcess(int ProcessId) + { + if (Processes.TryGetValue(ProcessId, out Process Process) && Process.NeedsHbAbi) + { + string NextNro = Homebrew.ReadHbAbiNextLoadPath(Process.Memory, Process.HbAbiDataPosition); + + Logging.Info($"HbAbi NextLoadPath {NextNro}"); + + if (NextNro == string.Empty) + { + NextNro = "sdmc:/hbmenu.nro"; + } + + NextNro = NextNro.Replace("sdmc:", string.Empty); + + NextNro = Ns.VFs.GetFullPath(Ns.VFs.GetSdCardPath(), NextNro); + + if (File.Exists(NextNro)) + { + //TODO: Those dictionaries shouldn't even exist, + //the Mutex and CondVar helper classes should be static. + Mutexes.Clear(); + CondVars.Clear(); + + LoadProgram(NextNro); + } + } + + if (Processes.TryRemove(ProcessId, out Process)) + { + Process.StopAllThreadsAsync(); Process.Dispose(); - } - } - internal bool ExitProcess(int ProcessId) - { - bool Success = Processes.TryRemove(ProcessId, out Process Process); - - if (Success) - { - Process.StopAllThreads(); + if (Processes.Count == 0) + { + Ns.OnFinish(EventArgs.Empty); + } } - - if (Processes.Count == 0) - { - Ns.OnFinish(EventArgs.Empty); - } - - return Success; } internal bool TryGetProcess(int ProcessId, out Process Process) @@ -152,19 +157,21 @@ namespace Ryujinx.Core.OsHle return Processes.TryGetValue(ProcessId, out Process); } - internal void CloseHandle(int Handle) + public void Dispose() { - object HndData = Handles.GetData(Handle); + Dispose(true); + } - if (HndData is HTransferMem TransferMem) + protected virtual void Dispose(bool Disposing) + { + if (Disposing) { - TransferMem.Memory.Manager.Reprotect( - TransferMem.Position, - TransferMem.Size, - TransferMem.Perm); + foreach (Process Process in Processes.Values) + { + Process.StopAllThreadsAsync(); + Process.Dispose(); + } } - - Handles.Delete(Handle); } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Utilities/IdPoolWithObj.cs b/Ryujinx.Core/OsHle/IdDictionary.cs similarity index 50% rename from Ryujinx.Core/OsHle/Utilities/IdPoolWithObj.cs rename to Ryujinx.Core/OsHle/IdDictionary.cs index f0a339df3..0b9092461 100644 --- a/Ryujinx.Core/OsHle/Utilities/IdPoolWithObj.cs +++ b/Ryujinx.Core/OsHle/IdDictionary.cs @@ -3,31 +3,40 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.Utilities +namespace Ryujinx.Core.OsHle { - class IdPoolWithObj : IEnumerable> + class IdDictionary : IEnumerable { - private IdPool Ids; - private ConcurrentDictionary Objs; - public IdPoolWithObj() - { - Ids = new IdPool(); + private int FreeIdHint = 1; + public IdDictionary() + { Objs = new ConcurrentDictionary(); } - public int GenerateId(object Data) + public int Add(object Data) { - int Id = Ids.GenerateId(); - - if (Id == -1 || !Objs.TryAdd(Id, Data)) + if (Objs.TryAdd(FreeIdHint, Data)) { - throw new InvalidOperationException(); + return FreeIdHint++; } - return Id; + return AddSlow(Data); + } + + private int AddSlow(object Data) + { + for (int Id = 1; Id < int.MaxValue; Id++) + { + if (Objs.TryAdd(Id, Data)) + { + return Id; + } + } + + throw new InvalidOperationException(); } public bool ReplaceData(int Id, object Data) @@ -42,6 +51,16 @@ namespace Ryujinx.Core.OsHle.Utilities return false; } + public object GetData(int Id) + { + if (Objs.TryGetValue(Id, out object Data)) + { + return Data; + } + + return null; + } + public T GetData(int Id) { if (Objs.TryGetValue(Id, out object Data) && Data is T) @@ -52,7 +71,7 @@ namespace Ryujinx.Core.OsHle.Utilities return default(T); } - public void Delete(int Id) + public bool Delete(int Id) { if (Objs.TryRemove(Id, out object Obj)) { @@ -61,18 +80,22 @@ namespace Ryujinx.Core.OsHle.Utilities DisposableObj.Dispose(); } - Ids.DeleteId(Id); + FreeIdHint = Id; + + return true; } + + return false; } - IEnumerator> IEnumerable>.GetEnumerator() + IEnumerator IEnumerable.GetEnumerator() { - return Objs.GetEnumerator(); + return Objs.Values.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - return Objs.GetEnumerator(); + return Objs.Values.GetEnumerator(); } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs index 2495d7014..f2179a962 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcHandler.cs @@ -13,6 +13,7 @@ namespace Ryujinx.Core.OsHle.Ipc public static void IpcCall( Switch Ns, + Process Process, AMemory Memory, HSession Session, IpcMessage Request, @@ -60,7 +61,7 @@ namespace Ryujinx.Core.OsHle.Ipc } else if (Request.DomCmd == IpcDomCmd.DeleteObj) { - Dom.DeleteObject(Request.DomObjId); + Dom.Delete(Request.DomObjId); Response = FillResponse(Response, 0); @@ -100,6 +101,7 @@ namespace Ryujinx.Core.OsHle.Ipc ServiceCtx Context = new ServiceCtx( Ns, + Process, Memory, Session, Request, @@ -124,15 +126,43 @@ namespace Ryujinx.Core.OsHle.Ipc switch (CmdId) { - case 0: Request = IpcConvertSessionToDomain(Ns, Session, Response, HndId); break; - case 3: Request = IpcQueryBufferPointerSize(Response); break; - case 2: //IpcDuplicateSession, differences is unknown. - case 4: Request = IpcDuplicateSessionEx(Ns, Session, Response, ReqReader); break; + case 0: + { + HDomain Dom = new HDomain(Session); + + Process.HandleTable.ReplaceData(HndId, Dom); + + Request = FillResponse(Response, 0, Dom.Add(Dom)); + + break; + } + + case 3: + { + Request = FillResponse(Response, 0, 0x500); + + break; + } + + //TODO: Whats the difference between IpcDuplicateSession/Ex? + case 2: + case 4: + { + int Unknown = ReqReader.ReadInt32(); + + int Handle = Process.HandleTable.OpenHandle(Session); + + Response.HandleDesc = IpcHandleDesc.MakeMove(Handle); + + Request = FillResponse(Response, 0); + + break; + } default: throw new NotImplementedException(CmdId.ToString()); } } - else if (Request.Type == IpcMessageType.Unknown2) + else if (Request.Type == IpcMessageType.CloseSession) { //TODO } @@ -145,39 +175,6 @@ namespace Ryujinx.Core.OsHle.Ipc } } - private static IpcMessage IpcConvertSessionToDomain( - Switch Ns, - HSession Session, - IpcMessage Response, - int HndId) - { - HDomain Dom = new HDomain(Session); - - Ns.Os.Handles.ReplaceData(HndId, Dom); - - return FillResponse(Response, 0, Dom.GenerateObjectId(Dom)); - } - - private static IpcMessage IpcDuplicateSessionEx( - Switch Ns, - HSession Session, - IpcMessage Response, - BinaryReader ReqReader) - { - int Unknown = ReqReader.ReadInt32(); - - int Handle = Ns.Os.Handles.GenerateId(Session); - - Response.HandleDesc = IpcHandleDesc.MakeMove(Handle); - - return FillResponse(Response, 0); - } - - private static IpcMessage IpcQueryBufferPointerSize(IpcMessage Response) - { - return FillResponse(Response, 0, 0x500); - } - private static IpcMessage FillResponse(IpcMessage Response, long Result, params int[] Values) { using (MemoryStream MS = new MemoryStream()) diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMessageType.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessageType.cs index 8027508de..560af41e7 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcMessageType.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcMessageType.cs @@ -2,9 +2,9 @@ namespace Ryujinx.Core.OsHle.Ipc { enum IpcMessageType { - Response = 0, - Unknown2 = 2, - Request = 4, - Control = 5 + Response = 0, + CloseSession = 2, + Request = 4, + Control = 5 } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Mutex.cs b/Ryujinx.Core/OsHle/Mutex.cs index c95ed7716..c619e1217 100644 --- a/Ryujinx.Core/OsHle/Mutex.cs +++ b/Ryujinx.Core/OsHle/Mutex.cs @@ -4,7 +4,7 @@ using System.Threading; namespace Ryujinx.Core.OsHle { - public class Mutex + class Mutex { private const int MutexHasListenersMask = 0x40000000; diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs index a919f1af6..a8719e1c2 100644 --- a/Ryujinx.Core/OsHle/Process.cs +++ b/Ryujinx.Core/OsHle/Process.cs @@ -9,25 +9,32 @@ using Ryujinx.Core.OsHle.Svc; using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Threading; namespace Ryujinx.Core.OsHle { - public class Process : IDisposable + class Process : IDisposable { - private const int TlsSize = 0x200; - private const int TotalTlsSlots = 32; + private const int TlsSize = 0x200; + private const int TotalTlsSlots = 32; private Switch Ns; + public bool NeedsHbAbi { get; private set; } + + public long HbAbiDataPosition { get; private set; } + public int ProcessId { get; private set; } private ATranslator Translator; public AMemory Memory { get; private set; } + public ServiceMgr Services { get; private set; } + public KProcessScheduler Scheduler { get; private set; } + public KProcessHandleTable HandleTable { get; private set; } + private SvcHandler SvcHandler; private ConcurrentDictionary TlsSlots; @@ -40,14 +47,22 @@ namespace Ryujinx.Core.OsHle private long ImageBase; + private bool ShouldDispose; + + private bool Disposed; + public Process(Switch Ns, int ProcessId) { this.Ns = Ns; this.ProcessId = ProcessId; - Memory = Ns.Memory; + Memory = new AMemory(); - Scheduler = new KProcessScheduler(); + Services = new ServiceMgr(); + + HandleTable = new KProcessHandleTable(); + + Scheduler = new KProcessScheduler(); SvcHandler = new SvcHandler(Ns, this); @@ -67,6 +82,11 @@ namespace Ryujinx.Core.OsHle public void LoadProgram(IExecutable Program) { + if (Disposed) + { + throw new ObjectDisposedException(nameof(Process)); + } + Logging.Info($"Image base at 0x{ImageBase:x16}."); Executable Executable = new Executable(Program, Memory, ImageBase); @@ -78,11 +98,19 @@ namespace Ryujinx.Core.OsHle public void SetEmptyArgs() { + //TODO: This should be part of Run. ImageBase += AMemoryMgr.PageSize; } - public bool Run(bool UseHbAbi = false) + public bool Run(bool NeedsHbAbi = false) { + if (Disposed) + { + throw new ObjectDisposedException(nameof(Process)); + } + + this.NeedsHbAbi = NeedsHbAbi; + if (Executables.Count == 0) { return false; @@ -102,11 +130,11 @@ namespace Ryujinx.Core.OsHle return false; } - MainThread = Ns.Os.Handles.GetData(Handle); + MainThread = HandleTable.GetData(Handle); - if (UseHbAbi) + if (NeedsHbAbi) { - long HbAbiDataPosition = AMemoryHelper.PageRoundUp(Executables[0].ImageEnd); + HbAbiDataPosition = AMemoryHelper.PageRoundUp(Executables[0].ImageEnd); Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle); @@ -124,22 +152,21 @@ namespace Ryujinx.Core.OsHle Memory.Manager.Map(Position, Size, (int)Type, AMemoryPerm.RW); } - public void StopAllThreads() + public void StopAllThreadsAsync() { + if (Disposed) + { + throw new ObjectDisposedException(nameof(Process)); + } + if (MainThread != null) { - while (MainThread.Thread.IsAlive) - { - MainThread.Thread.StopExecution(); - } + MainThread.Thread.StopExecution(); } foreach (AThread Thread in TlsSlots.Values) { - while (Thread.IsAlive) - { - Thread.StopExecution(); - } + Thread.StopExecution(); } } @@ -150,49 +177,26 @@ namespace Ryujinx.Core.OsHle int Priority, int ProcessorId) { - ThreadPriority ThreadPrio; - - if (Priority < 12) + if (Disposed) { - ThreadPrio = ThreadPriority.Highest; - } - else if (Priority < 24) - { - ThreadPrio = ThreadPriority.AboveNormal; - } - else if (Priority < 36) - { - ThreadPrio = ThreadPriority.Normal; - } - else if (Priority < 48) - { - ThreadPrio = ThreadPriority.BelowNormal; - } - else - { - ThreadPrio = ThreadPriority.Lowest; + throw new ObjectDisposedException(nameof(Process)); } - AThread Thread = new AThread(GetTranslator(), Memory, ThreadPrio, EntryPoint); + AThread Thread = new AThread(GetTranslator(), Memory, EntryPoint); HThread ThreadHnd = new HThread(Thread, ProcessorId, Priority); - int Handle = Ns.Os.Handles.GenerateId(ThreadHnd); + int Handle = HandleTable.OpenHandle(ThreadHnd); - int TlsSlot = GetFreeTlsSlot(Thread); + int ThreadId = GetFreeTlsSlot(Thread); - if (TlsSlot == -1 || Handle == -1) - { - return -1; - } - - long Tpidr = MemoryRegions.TlsPagesAddress + TlsSlot * TlsSize; + long Tpidr = MemoryRegions.TlsPagesAddress + ThreadId * TlsSize; Thread.ThreadState.Break += BreakHandler; Thread.ThreadState.SvcCall += SvcHandler.SvcCall; Thread.ThreadState.Undefined += UndefinedHandler; Thread.ThreadState.ProcessId = ProcessId; - Thread.ThreadState.ThreadId = Ns.Os.IdGen.GenerateId(); + Thread.ThreadState.ThreadId = ThreadId; Thread.ThreadState.Tpidr = Tpidr; Thread.ThreadState.X0 = (ulong)ArgsPtr; Thread.ThreadState.X1 = (ulong)Handle; @@ -224,7 +228,7 @@ namespace Ryujinx.Core.OsHle foreach (Executable Exe in Executables) { foreach (KeyValuePair KV in Exe.SymbolTable) - { + { SymbolTable.TryAdd(Exe.ImageBase + KV.Key, KV.Value); } } @@ -274,16 +278,28 @@ namespace Ryujinx.Core.OsHle } } - return -1; + throw new InvalidOperationException(); } private void ThreadFinished(object sender, EventArgs e) { if (sender is AThread Thread) { - TlsSlots.TryRemove(GetTlsSlot(Thread.ThreadState.Tpidr), out _); + Logging.Info($"Thread {Thread.ThreadId} exiting..."); - Ns.Os.IdGen.DeleteId(Thread.ThreadId); + TlsSlots.TryRemove(GetTlsSlot(Thread.ThreadState.Tpidr), out _); + } + + if (TlsSlots.Count == 0) + { + if (ShouldDispose) + { + Dispose(); + } + + Logging.Info($"No threads running, now exiting Process {ProcessId}..."); + + Ns.Os.ExitProcess(ProcessId); } } @@ -309,9 +325,30 @@ namespace Ryujinx.Core.OsHle protected virtual void Dispose(bool Disposing) { - if (Disposing) + if (Disposing && !Disposed) { + //If there is still some thread running, disposing the objects is not + //safe as the thread may try to access those resources. Instead, we set + //the flag to have the Process disposed when all threads finishes. + //Note: This may not happen if the guest code gets stuck on a infinite loop. + if (TlsSlots.Count > 0) + { + ShouldDispose = true; + + Logging.Info($"Process {ProcessId} waiting all threads terminate..."); + + return; + } + + Disposed = true; + + Services.Dispose(); + HandleTable.Dispose(); Scheduler.Dispose(); + SvcHandler.Dispose(); + Memory.Dispose(); + + Logging.Info($"Process {ProcessId} exiting..."); } } } diff --git a/Ryujinx.Core/OsHle/ServiceCtx.cs b/Ryujinx.Core/OsHle/ServiceCtx.cs index 31ecce3de..60c378d5a 100644 --- a/Ryujinx.Core/OsHle/ServiceCtx.cs +++ b/Ryujinx.Core/OsHle/ServiceCtx.cs @@ -8,6 +8,7 @@ namespace Ryujinx.Core.OsHle class ServiceCtx { public Switch Ns { get; private set; } + public Process Process { get; private set; } public AMemory Memory { get; private set; } public HSession Session { get; private set; } public IpcMessage Request { get; private set; } @@ -17,6 +18,7 @@ namespace Ryujinx.Core.OsHle public ServiceCtx( Switch Ns, + Process Process, AMemory Memory, HSession Session, IpcMessage Request, @@ -25,6 +27,7 @@ namespace Ryujinx.Core.OsHle BinaryWriter ResponseData) { this.Ns = Ns; + this.Process = Process; this.Memory = Memory; this.Session = Session; this.Request = Request; diff --git a/Ryujinx.Core/OsHle/ServiceMgr.cs b/Ryujinx.Core/OsHle/ServiceMgr.cs new file mode 100644 index 000000000..cbf6386f9 --- /dev/null +++ b/Ryujinx.Core/OsHle/ServiceMgr.cs @@ -0,0 +1,109 @@ +using Ryujinx.Core.OsHle.IpcServices; +using Ryujinx.Core.OsHle.IpcServices.Acc; +using Ryujinx.Core.OsHle.IpcServices.Am; +using Ryujinx.Core.OsHle.IpcServices.Apm; +using Ryujinx.Core.OsHle.IpcServices.Aud; +using Ryujinx.Core.OsHle.IpcServices.Bsd; +using Ryujinx.Core.OsHle.IpcServices.Friend; +using Ryujinx.Core.OsHle.IpcServices.FspSrv; +using Ryujinx.Core.OsHle.IpcServices.Hid; +using Ryujinx.Core.OsHle.IpcServices.Lm; +using Ryujinx.Core.OsHle.IpcServices.Nifm; +using Ryujinx.Core.OsHle.IpcServices.Ns; +using Ryujinx.Core.OsHle.IpcServices.NvServices; +using Ryujinx.Core.OsHle.IpcServices.Pctl; +using Ryujinx.Core.OsHle.IpcServices.Pl; +using Ryujinx.Core.OsHle.IpcServices.Set; +using Ryujinx.Core.OsHle.IpcServices.Sfdnsres; +using Ryujinx.Core.OsHle.IpcServices.Sm; +using Ryujinx.Core.OsHle.IpcServices.Ssl; +using Ryujinx.Core.OsHle.IpcServices.Time; +using Ryujinx.Core.OsHle.IpcServices.Vi; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle +{ + class ServiceMgr : IDisposable + { + private Dictionary Services; + + public ServiceMgr() + { + Services = new Dictionary(); + } + + public IIpcService GetService(string Name) + { + lock (Services) + { + if (!Services.TryGetValue(Name, out IIpcService Service)) + { + switch (Name) + { + case "acc:u0": Service = new ServiceAcc(); break; + case "aoc:u": Service = new ServiceNs(); break; + case "apm": Service = new ServiceApm(); break; + case "apm:p": Service = new ServiceApm(); break; + case "appletOE": Service = new ServiceAppletOE(); break; + case "audout:u": Service = new ServiceAudOut(); break; + case "audren:u": Service = new ServiceAudRen(); break; + case "bsd:u": Service = new ServiceBsd(); break; + case "friend:a": Service = new ServiceFriend(); break; + case "fsp-srv": Service = new ServiceFspSrv(); break; + case "hid": Service = new ServiceHid(); break; + case "lm": Service = new ServiceLm(); break; + case "nifm:u": Service = new ServiceNifm(); break; + case "nvdrv": Service = new ServiceNvDrv(); break; + case "nvdrv:a": Service = new ServiceNvDrv(); break; + case "pctl:a": Service = new ServicePctl(); break; + case "pl:u": Service = new ServicePl(); break; + case "set": Service = new ServiceSet(); break; + case "set:sys": Service = new ServiceSetSys(); break; + case "sfdnsres": Service = new ServiceSfdnsres(); break; + case "sm:": Service = new ServiceSm(); break; + case "ssl": Service = new ServiceSsl(); break; + case "time:s": Service = new ServiceTime(); break; + case "time:u": Service = new ServiceTime(); break; + case "vi:m": Service = new ServiceVi(); break; + case "vi:s": Service = new ServiceVi(); break; + case "vi:u": Service = new ServiceVi(); break; + } + + if (Service == null) + { + throw new NotImplementedException(Name); + } + + Services.Add(Name, Service); + } + + return Service; + } + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool Disposing) + { + if (Disposing) + { + lock (Services) + { + foreach (IIpcService Service in Services.Values) + { + if (Service is IDisposable DisposableSrv) + { + DisposableSrv.Dispose(); + } + } + + Services.Clear(); + } + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs index c58d9e804..2312920f6 100644 --- a/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs +++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs @@ -139,7 +139,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud public long RegisterBufferEvent(ServiceCtx Context) { - int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + int Handle = Context.Process.HandleTable.OpenHandle(new HEvent()); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs index bfde0b65b..4d29371fb 100644 --- a/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs +++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs @@ -56,7 +56,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud public long QuerySystemEvent(ServiceCtx Context) { - int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + int Handle = Context.Process.HandleTable.OpenHandle(new HEvent()); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); diff --git a/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs index d22e0ff23..ef437c022 100644 --- a/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs @@ -10,21 +10,23 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid public IReadOnlyDictionary Commands => m_Commands; - private HSharedMem Handle; + private HSharedMem HidSharedMem; - public IAppletResource(HSharedMem Handle) + public IAppletResource(HSharedMem HidSharedMem) { m_Commands = new Dictionary() { { 0, GetSharedMemoryHandle } }; - this.Handle = Handle; + this.HidSharedMem = HidSharedMem; } - public static long GetSharedMemoryHandle(ServiceCtx Context) + public long GetSharedMemoryHandle(ServiceCtx Context) { - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.HidHandle); + int Handle = Context.Process.HandleTable.OpenHandle(HidSharedMem); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); return 0; } diff --git a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs index cc30a771e..b1f930725 100644 --- a/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs @@ -1,4 +1,3 @@ -using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; @@ -32,9 +31,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid public long CreateAppletResource(ServiceCtx Context) { - HSharedMem HidHndData = Context.Ns.Os.Handles.GetData(Context.Ns.Os.HidHandle); - - MakeObject(Context, new IAppletResource(HidHndData)); + MakeObject(Context, new IAppletResource(Context.Ns.Os.HidSharedMem)); return 0; } diff --git a/Ryujinx.Core/OsHle/Services/Nv/NvFd.cs b/Ryujinx.Core/OsHle/Services/Nv/NvFd.cs new file mode 100644 index 000000000..dbce74adf --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Nv/NvFd.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.Core.OsHle.IpcServices.NvServices +{ + class NvFd + { + public string Name { get; private set; } + + public NvFd(string Name) + { + this.Name = Name; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs new file mode 100644 index 000000000..ca844f9f2 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.Core.OsHle.IpcServices.NvServices +{ + class NvMap + { + public int Handle; + public int Id; + public int Size; + public int Align; + public int Kind; + public long Address; + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs index 3c0c46fec..67ad44919 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs @@ -1,5 +1,4 @@ using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; using Ryujinx.Core.OsHle.Utilities; using Ryujinx.Graphics.Gpu; @@ -12,41 +11,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices { private delegate long ServiceProcessIoctl(ServiceCtx Context); - private static Dictionary<(string, int), ServiceProcessIoctl> IoctlCmds = - new Dictionary<(string, int), ServiceProcessIoctl>() - { - { ("/dev/nvhost-as-gpu", 0x4101), NvGpuAsIoctlBindChannel }, - { ("/dev/nvhost-as-gpu", 0x4102), NvGpuAsIoctlAllocSpace }, - { ("/dev/nvhost-as-gpu", 0x4106), NvGpuAsIoctlMapBufferEx }, - { ("/dev/nvhost-as-gpu", 0x4108), NvGpuAsIoctlGetVaRegions }, - { ("/dev/nvhost-as-gpu", 0x4109), NvGpuAsIoctlInitializeEx }, - { ("/dev/nvhost-ctrl", 0x001b), NvHostIoctlCtrlGetConfig }, - { ("/dev/nvhost-ctrl", 0x001d), NvHostIoctlCtrlEventWait }, - { ("/dev/nvhost-ctrl-gpu", 0x4701), NvGpuIoctlZcullGetCtxSize }, - { ("/dev/nvhost-ctrl-gpu", 0x4702), NvGpuIoctlZcullGetInfo }, - { ("/dev/nvhost-ctrl-gpu", 0x4705), NvGpuIoctlGetCharacteristics }, - { ("/dev/nvhost-ctrl-gpu", 0x4706), NvGpuIoctlGetTpcMasks }, - { ("/dev/nvhost-ctrl-gpu", 0x4714), NvGpuIoctlZbcGetActiveSlotMask }, - { ("/dev/nvhost-gpu", 0x4714), NvMapIoctlChannelSetUserData }, - { ("/dev/nvhost-gpu", 0x4801), NvMapIoctlChannelSetNvMap }, - { ("/dev/nvhost-gpu", 0x4808), NvMapIoctlChannelSubmitGpFifo }, - { ("/dev/nvhost-gpu", 0x4809), NvMapIoctlChannelAllocObjCtx }, - { ("/dev/nvhost-gpu", 0x480b), NvMapIoctlChannelZcullBind }, - { ("/dev/nvhost-gpu", 0x480c), NvMapIoctlChannelSetErrorNotifier }, - { ("/dev/nvhost-gpu", 0x480d), NvMapIoctlChannelSetPriority }, - { ("/dev/nvhost-gpu", 0x481a), NvMapIoctlChannelAllocGpFifoEx2 }, - { ("/dev/nvmap", 0x0101), NvMapIocCreate }, - { ("/dev/nvmap", 0x0103), NvMapIocFromId }, - { ("/dev/nvmap", 0x0104), NvMapIocAlloc }, - { ("/dev/nvmap", 0x0105), NvMapIocFree }, - { ("/dev/nvmap", 0x0109), NvMapIocParam }, - { ("/dev/nvmap", 0x010e), NvMapIocGetId }, - }; - private Dictionary m_Commands; public IReadOnlyDictionary Commands => m_Commands; + private Dictionary<(string, int), ServiceProcessIoctl> IoctlCmds; + + private IdDictionary Fds; + + private IdDictionary NvMaps; + private IdDictionary NvMapsById; + public ServiceNvDrv() { m_Commands = new Dictionary() @@ -58,15 +33,50 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices { 4, QueryEvent }, { 8, SetClientPid }, }; + + IoctlCmds = new Dictionary<(string, int), ServiceProcessIoctl>() + { + { ("/dev/nvhost-as-gpu", 0x4101), NvGpuAsIoctlBindChannel }, + { ("/dev/nvhost-as-gpu", 0x4102), NvGpuAsIoctlAllocSpace }, + { ("/dev/nvhost-as-gpu", 0x4106), NvGpuAsIoctlMapBufferEx }, + { ("/dev/nvhost-as-gpu", 0x4108), NvGpuAsIoctlGetVaRegions }, + { ("/dev/nvhost-as-gpu", 0x4109), NvGpuAsIoctlInitializeEx }, + { ("/dev/nvhost-ctrl", 0x001b), NvHostIoctlCtrlGetConfig }, + { ("/dev/nvhost-ctrl", 0x001d), NvHostIoctlCtrlEventWait }, + { ("/dev/nvhost-ctrl-gpu", 0x4701), NvGpuIoctlZcullGetCtxSize }, + { ("/dev/nvhost-ctrl-gpu", 0x4702), NvGpuIoctlZcullGetInfo }, + { ("/dev/nvhost-ctrl-gpu", 0x4705), NvGpuIoctlGetCharacteristics }, + { ("/dev/nvhost-ctrl-gpu", 0x4706), NvGpuIoctlGetTpcMasks }, + { ("/dev/nvhost-ctrl-gpu", 0x4714), NvGpuIoctlZbcGetActiveSlotMask }, + { ("/dev/nvhost-gpu", 0x4714), NvMapIoctlChannelSetUserData }, + { ("/dev/nvhost-gpu", 0x4801), NvMapIoctlChannelSetNvMap }, + { ("/dev/nvhost-gpu", 0x4808), NvMapIoctlChannelSubmitGpFifo }, + { ("/dev/nvhost-gpu", 0x4809), NvMapIoctlChannelAllocObjCtx }, + { ("/dev/nvhost-gpu", 0x480b), NvMapIoctlChannelZcullBind }, + { ("/dev/nvhost-gpu", 0x480c), NvMapIoctlChannelSetErrorNotifier }, + { ("/dev/nvhost-gpu", 0x480d), NvMapIoctlChannelSetPriority }, + { ("/dev/nvhost-gpu", 0x481a), NvMapIoctlChannelAllocGpFifoEx2 }, + { ("/dev/nvmap", 0x0101), NvMapIocCreate }, + { ("/dev/nvmap", 0x0103), NvMapIocFromId }, + { ("/dev/nvmap", 0x0104), NvMapIocAlloc }, + { ("/dev/nvmap", 0x0105), NvMapIocFree }, + { ("/dev/nvmap", 0x0109), NvMapIocParam }, + { ("/dev/nvmap", 0x010e), NvMapIocGetId }, + }; + + Fds = new IdDictionary(); + + NvMaps = new IdDictionary(); + NvMapsById = new IdDictionary(); } - public static long Open(ServiceCtx Context) + public long Open(ServiceCtx Context) { long NamePtr = Context.Request.SendBuff[0].Position; string Name = AMemoryHelper.ReadAsciiString(Context.Memory, NamePtr); - int Fd = Context.Ns.Os.Fds.GenerateId(new FileDesc(Name)); + int Fd = Fds.Add(new NvFd(Name)); Context.ResponseData.Write(Fd); Context.ResponseData.Write(0); @@ -74,12 +84,12 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - public static long Ioctl(ServiceCtx Context) + public long Ioctl(ServiceCtx Context) { int Fd = Context.RequestData.ReadInt32(); int Cmd = Context.RequestData.ReadInt32() & 0xffff; - FileDesc FdData = Context.Ns.Os.Fds.GetData(Fd); + NvFd FdData = Fds.GetData(Fd); long Position = Context.Request.GetSendBuffPtr(); @@ -95,18 +105,18 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices } } - public static long Close(ServiceCtx Context) + public long Close(ServiceCtx Context) { int Fd = Context.RequestData.ReadInt32(); - Context.Ns.Os.Fds.Delete(Fd); + Fds.Delete(Fd); Context.ResponseData.Write(0); return 0; } - public static long Initialize(ServiceCtx Context) + public long Initialize(ServiceCtx Context) { long TransferMemSize = Context.RequestData.ReadInt64(); int TransferMemHandle = Context.Request.HandleDesc.ToCopy[0]; @@ -116,7 +126,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - public static long QueryEvent(ServiceCtx Context) + public long QueryEvent(ServiceCtx Context) { int Fd = Context.RequestData.ReadInt32(); int EventId = Context.RequestData.ReadInt32(); @@ -128,7 +138,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - public static long SetClientPid(ServiceCtx Context) + public long SetClientPid(ServiceCtx Context) { long Pid = Context.RequestData.ReadInt64(); @@ -137,7 +147,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuAsIoctlBindChannel(ServiceCtx Context) + private long NvGpuAsIoctlBindChannel(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -146,7 +156,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuAsIoctlAllocSpace(ServiceCtx Context) + private long NvGpuAsIoctlAllocSpace(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -172,7 +182,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuAsIoctlMapBufferEx(ServiceCtx Context) + private long NvGpuAsIoctlMapBufferEx(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -186,18 +196,29 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices long MapSize = Reader.ReadInt64(); long Offset = Reader.ReadInt64(); - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); - - if (NvMap != null) + if (Handle == 0) { - if ((Flags & 1) != 0) - { - Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, Offset, NvMap.Size); - } - else - { - Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, NvMap.Size); - } + //Handle 0 is valid here, but it refers to something else. + //TODO: Figure out what, for now just return success. + return 0; + } + + NvMap Map = NvMaps.GetData(Handle); + + if (Map == null) + { + Logging.Warn($"Trying to use invalid NvMap Handle {Handle}!"); + + return -1; //TODO: Corrent error code. + } + + if ((Flags & 1) != 0) + { + Offset = Context.Ns.Gpu.MapMemory(Map.Address, Offset, Map.Size); + } + else + { + Offset = Context.Ns.Gpu.MapMemory(Map.Address, Map.Size); } Context.Memory.WriteInt64(Position + 0x20, Offset); @@ -205,7 +226,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuAsIoctlGetVaRegions(ServiceCtx Context) + private long NvGpuAsIoctlGetVaRegions(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -235,7 +256,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuAsIoctlInitializeEx(ServiceCtx Context) + private long NvGpuAsIoctlInitializeEx(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -252,7 +273,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvHostIoctlCtrlGetConfig(ServiceCtx Context) + private long NvHostIoctlCtrlGetConfig(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -267,7 +288,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvHostIoctlCtrlEventWait(ServiceCtx Context) + private long NvHostIoctlCtrlEventWait(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -283,7 +304,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context) + private long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -292,7 +313,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuIoctlZcullGetInfo(ServiceCtx Context) + private long NvGpuIoctlZcullGetInfo(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -312,7 +333,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuIoctlGetCharacteristics(ServiceCtx Context) + private long NvGpuIoctlGetCharacteristics(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -374,7 +395,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuIoctlGetTpcMasks(ServiceCtx Context) + private long NvGpuIoctlGetTpcMasks(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -388,7 +409,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context) + private long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -398,14 +419,14 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIoctlChannelSetUserData(ServiceCtx Context) + private long NvMapIoctlChannelSetUserData(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); return 0; } - private static long NvMapIoctlChannelSetNvMap(ServiceCtx Context) + private long NvMapIoctlChannelSetNvMap(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -414,7 +435,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context) + private long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -453,7 +474,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context) + private long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -465,7 +486,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIoctlChannelZcullBind(ServiceCtx Context) + private long NvMapIoctlChannelZcullBind(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -478,7 +499,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context) + private long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -492,7 +513,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIoctlChannelSetPriority(ServiceCtx Context) + private long NvMapIoctlChannelSetPriority(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -501,7 +522,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context) + private long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -521,47 +542,46 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIocCreate(ServiceCtx Context) + private long NvMapIocCreate(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); int Size = Context.Memory.ReadInt32(Position); - int Id = Context.Ns.Os.NvMapIds.GenerateId(); + NvMap Map = new NvMap() { Size = Size }; - int Handle = Context.Ns.Os.Handles.GenerateId(new HNvMap(Id, Size)); + Map.Handle = NvMaps.Add(Map); - Context.Memory.WriteInt32(Position + 4, Handle); + Map.Id = NvMapsById.Add(Map); - Logging.Info($"NvMap {Id} created with size {Size:x8}!"); + Context.Memory.WriteInt32(Position + 4, Map.Handle); + + Logging.Info($"NvMap {Map.Id} created with size {Size:x8}!"); return 0; } - private static long NvMapIocFromId(ServiceCtx Context) + private long NvMapIocFromId(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); int Id = Context.Memory.ReadInt32(Position); - int Handle = -1; + NvMap Map = NvMapsById.GetData(Id); - foreach (KeyValuePair KV in Context.Ns.Os.Handles) + if (Map == null) { - if (KV.Value is HNvMap NvMap && NvMap.Id == Id) - { - Handle = KV.Key; - - break; - } + Logging.Warn($"Trying to use invalid NvMap Id {Id}!"); + + return -1; //TODO: Corrent error code. } - Context.Memory.WriteInt32(Position + 4, Handle); + Context.Memory.WriteInt32(Position + 4, Map.Handle); return 0; } - private static long NvMapIocAlloc(ServiceCtx Context) + private long NvMapIocAlloc(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -574,38 +594,49 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices byte Kind = (byte)Reader.ReadInt64(); long Addr = Reader.ReadInt64(); - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + NvMap Map = NvMaps.GetData(Handle); - if (NvMap != null) + if (Map == null) { - NvMap.Address = Addr; - NvMap.Align = Align; - NvMap.Kind = Kind; + Logging.Warn($"Trying to use invalid NvMap Handle {Handle}!"); + + return -1; //TODO: Corrent error code. } + Map.Address = Addr; + Map.Align = Align; + Map.Kind = Kind; + return 0; } - private static long NvMapIocFree(ServiceCtx Context) + private long NvMapIocFree(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position + 8); - int Handle = Reader.ReadInt32(); - int Padding = Reader.ReadInt32(); + int Handle = Reader.ReadInt32(); + int Padding = Reader.ReadInt32(); - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + NvMap Map = NvMaps.GetData(Handle); + + if (Map == null) + { + Logging.Warn($"Trying to use invalid NvMap Handle {Handle}!"); + + return -1; //TODO: Corrent error code. + } Writer.WriteInt64(0); - Writer.WriteInt32(NvMap.Size); + Writer.WriteInt32(Map.Size); Writer.WriteInt32(0); return 0; } - private static long NvMapIocParam(ServiceCtx Context) + private long NvMapIocParam(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); @@ -614,16 +645,23 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices int Handle = Reader.ReadInt32(); int Param = Reader.ReadInt32(); - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + NvMap Map = NvMaps.GetData(Handle); + + if (Map == null) + { + Logging.Warn($"Trying to use invalid NvMap Handle {Handle}!"); + + return -1; //TODO: Corrent error code. + } int Response = 0; - + switch (Param) { - case 1: Response = NvMap.Size; break; - case 2: Response = NvMap.Align; break; - case 4: Response = 0x40000000; break; - case 5: Response = NvMap.Kind; break; + case 1: Response = Map.Size; break; + case 2: Response = Map.Align; break; + case 4: Response = 0x40000000; break; + case 5: Response = Map.Kind; break; } Context.Memory.WriteInt32(Position + 8, Response); @@ -631,17 +669,29 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices return 0; } - private static long NvMapIocGetId(ServiceCtx Context) + private long NvMapIocGetId(ServiceCtx Context) { long Position = Context.Request.GetSendBuffPtr(); int Handle = Context.Memory.ReadInt32(Position + 4); - HNvMap NvMap = Context.Ns.Os.Handles.GetData(Handle); + NvMap Map = NvMaps.GetData(Handle); - Context.Memory.WriteInt32(Position, NvMap.Id); + if (Map == null) + { + Logging.Warn($"Trying to use invalid NvMap Handle {Handle}!"); + + return -1; //TODO: Corrent error code. + } + + Context.Memory.WriteInt32(Position, Map.Id); return 0; } + + public NvMap GetNvMap(int Handle) + { + return NvMaps.GetData(Handle); + } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/ObjHelper.cs b/Ryujinx.Core/OsHle/Services/ObjHelper.cs index ff71838a6..89d986aeb 100644 --- a/Ryujinx.Core/OsHle/Services/ObjHelper.cs +++ b/Ryujinx.Core/OsHle/Services/ObjHelper.cs @@ -9,13 +9,13 @@ namespace Ryujinx.Core.OsHle.IpcServices { if (Context.Session is HDomain Dom) { - Context.Response.ResponseObjIds.Add(Dom.GenerateObjectId(Obj)); + Context.Response.ResponseObjIds.Add(Dom.Add(Obj)); } else { HSessionObj HndData = new HSessionObj(Context.Session, Obj); - int VHandle = Context.Ns.Os.Handles.GenerateId(HndData); + int VHandle = Context.Process.HandleTable.OpenHandle(HndData); Context.Response.HandleDesc = IpcHandleDesc.MakeMove(VHandle); } diff --git a/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs b/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs index abc34ed21..bb795f3f4 100644 --- a/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs +++ b/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs @@ -20,30 +20,32 @@ namespace Ryujinx.Core.OsHle.IpcServices.Pl }; } - public static long GetLoadState(ServiceCtx Context) + public long GetLoadState(ServiceCtx Context) { Context.ResponseData.Write(1); //Loaded return 0; } - public static long GetFontSize(ServiceCtx Context) + public long GetFontSize(ServiceCtx Context) { Context.ResponseData.Write(Horizon.FontSize); return 0; } - public static long GetSharedMemoryAddressOffset(ServiceCtx Context) + public long GetSharedMemoryAddressOffset(ServiceCtx Context) { Context.ResponseData.Write(0); return 0; } - public static long GetSharedMemoryNativeHandle(ServiceCtx Context) + public long GetSharedMemoryNativeHandle(ServiceCtx Context) { - Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.FontHandle); + int Handle = Context.Process.HandleTable.OpenHandle(Context.Ns.Os.FontSharedMem); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); return 0; } diff --git a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs deleted file mode 100644 index 2b855d25b..000000000 --- a/Ryujinx.Core/OsHle/Services/ServiceFactory.cs +++ /dev/null @@ -1,64 +0,0 @@ -using Ryujinx.Core.OsHle.IpcServices.Acc; -using Ryujinx.Core.OsHle.IpcServices.Am; -using Ryujinx.Core.OsHle.IpcServices.Apm; -using Ryujinx.Core.OsHle.IpcServices.Aud; -using Ryujinx.Core.OsHle.IpcServices.Bsd; -using Ryujinx.Core.OsHle.IpcServices.Friend; -using Ryujinx.Core.OsHle.IpcServices.FspSrv; -using Ryujinx.Core.OsHle.IpcServices.Hid; -using Ryujinx.Core.OsHle.IpcServices.Lm; -using Ryujinx.Core.OsHle.IpcServices.Nifm; -using Ryujinx.Core.OsHle.IpcServices.Ns; -using Ryujinx.Core.OsHle.IpcServices.NvServices; -using Ryujinx.Core.OsHle.IpcServices.Pctl; -using Ryujinx.Core.OsHle.IpcServices.Pl; -using Ryujinx.Core.OsHle.IpcServices.Set; -using Ryujinx.Core.OsHle.IpcServices.Sfdnsres; -using Ryujinx.Core.OsHle.IpcServices.Sm; -using Ryujinx.Core.OsHle.IpcServices.Ssl; -using Ryujinx.Core.OsHle.IpcServices.Time; -using Ryujinx.Core.OsHle.IpcServices.Vi; -using System; - -namespace Ryujinx.Core.OsHle.IpcServices -{ - static class ServiceFactory - { - public static IIpcService MakeService(string Name) - { - switch (Name) - { - case "acc:u0": return new ServiceAcc(); - case "aoc:u": return new ServiceNs(); - case "apm": return new ServiceApm(); - case "apm:p": return new ServiceApm(); - case "appletOE": return new ServiceAppletOE(); - case "audout:u": return new ServiceAudOut(); - case "audren:u": return new ServiceAudRen(); - case "bsd:s": return new ServiceBsd(); - case "bsd:u": return new ServiceBsd(); - case "friend:a": return new ServiceFriend(); - case "fsp-srv": return new ServiceFspSrv(); - case "hid": return new ServiceHid(); - case "lm": return new ServiceLm(); - case "nifm:u": return new ServiceNifm(); - case "nvdrv": return new ServiceNvDrv(); - case "nvdrv:a": return new ServiceNvDrv(); - case "pctl:a": return new ServicePctl(); - case "pl:u": return new ServicePl(); - case "set": return new ServiceSet(); - case "set:sys": return new ServiceSetSys(); - case "sfdnsres": return new ServiceSfdnsres(); - case "sm:": return new ServiceSm(); - case "ssl": return new ServiceSsl(); - case "time:s": return new ServiceTime(); - case "time:u": return new ServiceTime(); - case "vi:m": return new ServiceVi(); - case "vi:s": return new ServiceVi(); - case "vi:u": return new ServiceVi(); - } - - throw new NotImplementedException(Name); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs b/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs index a5f1b329b..cb745e373 100644 --- a/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs +++ b/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs @@ -55,9 +55,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Sm return 0; } - HSession Session = new HSession(ServiceFactory.MakeService(Name)); + HSession Session = new HSession(Context.Process.Services.GetService(Name)); - int Handle = Context.Ns.Os.Handles.GenerateId(Session); + int Handle = Context.Process.HandleTable.OpenHandle(Session); Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle); diff --git a/Ryujinx.Core/OsHle/Display.cs b/Ryujinx.Core/OsHle/Services/Vi/Display.cs similarity index 79% rename from Ryujinx.Core/OsHle/Display.cs rename to Ryujinx.Core/OsHle/Services/Vi/Display.cs index 590841fc5..ceadc3931 100644 --- a/Ryujinx.Core/OsHle/Display.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/Display.cs @@ -1,4 +1,4 @@ -namespace Ryujinx.Core.OsHle +namespace Ryujinx.Core.OsHle.IpcServices.Vi { class Display { diff --git a/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs index 4e40b99b3..0ff1f9099 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs @@ -15,6 +15,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi public IReadOnlyDictionary Commands => m_Commands; + private IdDictionary Displays; + public IApplicationDisplayService() { m_Commands = new Dictionary() @@ -28,14 +30,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi { 2020, OpenLayer }, { 2021, CloseLayer }, { 2030, CreateStrayLayer }, + { 2031, DestroyStrayLayer }, { 2101, SetLayerScalingMode }, { 5202, GetDisplayVSyncEvent } }; + + Displays = new IdDictionary(); } public long GetRelayService(ServiceCtx Context) { - MakeObject(Context, new IHOSBinderDriver()); + MakeObject(Context, new IHOSBinderDriver(Context.Ns.Gpu.Renderer)); return 0; } @@ -56,7 +61,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi public long GetIndirectDisplayTransactionService(ServiceCtx Context) { - MakeObject(Context, new IHOSBinderDriver()); + MakeObject(Context, new IHOSBinderDriver(Context.Ns.Gpu.Renderer)); return 0; } @@ -65,7 +70,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi { string Name = GetDisplayName(Context); - long DisplayId = Context.Ns.Os.Displays.GenerateId(new Display(Name)); + long DisplayId = Displays.Add(new Display(Name)); Context.ResponseData.Write(DisplayId); @@ -76,7 +81,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi { int DisplayId = Context.RequestData.ReadInt32(); - Context.Ns.Os.Displays.Delete(DisplayId); + Displays.Delete(DisplayId); return 0; } @@ -99,6 +104,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi public long CloseLayer(ServiceCtx Context) { + long LayerId = Context.RequestData.ReadInt64(); + return 0; } @@ -109,7 +116,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi long ParcelPtr = Context.Request.ReceiveBuff[0].Position; - Display Disp = Context.Ns.Os.Displays.GetData((int)DisplayId); + Display Disp = Displays.GetData((int)DisplayId); byte[] Parcel = MakeIGraphicsBufferProducer(ParcelPtr); @@ -121,6 +128,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi return 0; } + public long DestroyStrayLayer(ServiceCtx Context) + { + return 0; + } + public long SetLayerScalingMode(ServiceCtx Context) { int ScalingMode = Context.RequestData.ReadInt32(); @@ -133,7 +145,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi { string Name = GetDisplayName(Context); - int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + int Handle = Context.Process.HandleTable.OpenHandle(new HEvent()); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); diff --git a/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs index a89c1df82..b24a773bf 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs @@ -1,6 +1,7 @@ using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Ipc; using Ryujinx.Core.OsHle.IpcServices.Android; +using Ryujinx.Graphics.Gal; using System; using System.Collections.Generic; @@ -14,7 +15,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi private NvFlinger Flinger; - public IHOSBinderDriver() + public IHOSBinderDriver(IGalRenderer Renderer) { m_Commands = new Dictionary() { @@ -23,7 +24,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Vi { 2, GetNativeHandle } }; - Flinger = new NvFlinger(); + Flinger = new NvFlinger(Renderer); } public long TransactParcel(ServiceCtx Context) diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 1d394fb4a..5309dcabb 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -1,5 +1,6 @@ using ChocolArm64.Memory; -using Ryujinx.Core.OsHle.Handles; +using Ryujinx.Core.OsHle.IpcServices.NvServices; +using Ryujinx.Graphics.Gal; using System; using System.IO; using System.Collections.Generic; @@ -54,18 +55,27 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android public GbpBuffer Data; } + private IGalRenderer Renderer; + private BufferEntry[] BufferQueue; private ManualResetEvent WaitBufferFree; + + private object RenderQueueLock; + + private int RenderQueueCount; + + private bool NvFlingerDisposed; private bool KeepRunning; - public NvFlinger() + public NvFlinger(IGalRenderer Renderer) { Commands = new Dictionary<(string, int), ServiceProcessParcel>() { { ("android.gui.IGraphicBufferProducer", 0x1), GbpRequestBuffer }, { ("android.gui.IGraphicBufferProducer", 0x3), GbpDequeueBuffer }, + { ("android.gui.IGraphicBufferProducer", 0x4), GbpDetachBuffer }, { ("android.gui.IGraphicBufferProducer", 0x7), GbpQueueBuffer }, { ("android.gui.IGraphicBufferProducer", 0x8), GbpCancelBuffer }, { ("android.gui.IGraphicBufferProducer", 0x9), GbpQuery }, @@ -74,10 +84,14 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android { ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer } }; + this.Renderer = Renderer; + BufferQueue = new BufferEntry[0x40]; WaitBufferFree = new ManualResetEvent(false); + RenderQueueLock = new object(); + KeepRunning = true; } @@ -193,6 +207,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); } + private long GbpDetachBuffer(ServiceCtx Context, BinaryReader ParcelReader) + { + return MakeReplyParcel(Context, 0); + } + private long GbpCancelBuffer(ServiceCtx Context, BinaryReader ParcelReader) { //TODO: Errors. @@ -266,7 +285,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android long FbSize = (uint)FbWidth * FbHeight * 4; - HNvMap NvMap = GetNvMap(Context, Slot); + NvMap NvMap = GetNvMap(Context, Slot); if ((ulong)(NvMap.Address + FbSize) > AMemoryMgr.AddrSize) { @@ -330,7 +349,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android Rotate = -MathF.PI * 0.5f; } - byte* Fb = (byte*)Context.Ns.Memory.Ram + NvMap.Address; + lock (RenderQueueLock) + { + if (NvFlingerDisposed) + { + return; + } + + Interlocked.Increment(ref RenderQueueCount); + } + + byte* Fb = (byte*)Context.Memory.Ram + NvMap.Address; Context.Ns.Gpu.Renderer.QueueAction(delegate() { @@ -346,6 +375,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android BufferQueue[Slot].State = BufferState.Free; + Interlocked.Decrement(ref RenderQueueCount); + lock (WaitBufferFree) { WaitBufferFree.Set(); @@ -353,7 +384,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android }); } - private HNvMap GetNvMap(ServiceCtx Context, int Slot) + private NvMap GetNvMap(ServiceCtx Context, int Slot) { int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c); @@ -366,7 +397,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android NvMapHandle = BitConverter.ToInt32(RawValue, 0); } - return Context.Ns.Os.Handles.GetData(NvMapHandle); + ServiceNvDrv NvDrv = (ServiceNvDrv)Context.Process.Services.GetService("nvdrv"); + + return NvDrv.GetNvMap(NvMapHandle); } private int GetFreeSlotBlocking(int Width, int Height) @@ -432,10 +465,24 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android Dispose(true); } - protected virtual void Dispose(bool disposing) + protected virtual void Dispose(bool Disposing) { - if (disposing) + if (Disposing && !NvFlingerDisposed) { + lock (RenderQueueLock) + { + NvFlingerDisposed = true; + } + + //Ensure that all pending actions was sent before + //we can safely assume that the class was disposed. + while (RenderQueueCount > 0) + { + Thread.Yield(); + } + + Renderer.ResetFrameBuffer(); + lock (WaitBufferFree) { KeepRunning = false; diff --git a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs index b3e6262db..3ce56a3cd 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs @@ -1,12 +1,13 @@ using ChocolArm64.Events; using ChocolArm64.Memory; using ChocolArm64.State; +using Ryujinx.Core.OsHle.Handles; using System; using System.Collections.Generic; namespace Ryujinx.Core.OsHle.Svc { - partial class SvcHandler + partial class SvcHandler : IDisposable { private delegate void SvcFunc(AThreadState ThreadState); @@ -16,10 +17,12 @@ namespace Ryujinx.Core.OsHle.Svc private Process Process; private AMemory Memory; - private static Random Rng; - + private HashSet<(HSharedMem, long)> MappedSharedMems; + private ulong CurrentHeapSize; + private static Random Rng; + public SvcHandler(Switch Ns, Process Process) { SvcFuncs = new Dictionary() @@ -32,6 +35,7 @@ namespace Ryujinx.Core.OsHle.Svc { 0x07, SvcExitProcess }, { 0x08, SvcCreateThread }, { 0x09, SvcStartThread }, + { 0x0a, SvcExitThread }, { 0x0b, SvcSleepThread }, { 0x0c, SvcGetThreadPriority }, { 0x0d, SvcSetThreadPriority }, @@ -60,6 +64,8 @@ namespace Ryujinx.Core.OsHle.Svc this.Ns = Ns; this.Process = Process; this.Memory = Process.Memory; + + MappedSharedMems = new HashSet<(HSharedMem, long)>(); } static SvcHandler() @@ -84,5 +90,26 @@ namespace Ryujinx.Core.OsHle.Svc throw new NotImplementedException(e.Id.ToString("x4")); } } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool Disposing) + { + if (Disposing) + { + lock (MappedSharedMems) + { + foreach ((HSharedMem SharedMem, long Position) in MappedSharedMems) + { + SharedMem.RemoveVirtualPosition(Memory, Position); + } + + MappedSharedMems.Clear(); + } + } + } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index c15f449bf..80f24d2bd 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -165,7 +165,7 @@ namespace Ryujinx.Core.OsHle.Svc return; } - HSharedMem SharedMem = Ns.Os.Handles.GetData(Handle); + HSharedMem SharedMem = Process.HandleTable.GetData(Handle); if (SharedMem != null) { @@ -175,7 +175,12 @@ namespace Ryujinx.Core.OsHle.Svc Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm); - SharedMem.AddVirtualPosition(Src); + lock (MappedSharedMems) + { + MappedSharedMems.Add((SharedMem, Src)); + } + + SharedMem.AddVirtualPosition(Memory, Src); ThreadState.X0 = 0; } @@ -198,12 +203,19 @@ namespace Ryujinx.Core.OsHle.Svc return; } - HSharedMem HndData = Ns.Os.Handles.GetData(Handle); + HSharedMem SharedMem = Process.HandleTable.GetData(Handle); - if (HndData != null) + if (SharedMem != null) { Memory.Manager.Unmap(Src, Size, (int)MemoryType.SharedMemory); + SharedMem.RemoveVirtualPosition(Memory, Src); + + lock (MappedSharedMems) + { + MappedSharedMems.Remove((SharedMem, Src)); + } + ThreadState.X0 = 0; } @@ -229,12 +241,12 @@ namespace Ryujinx.Core.OsHle.Svc Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm); - HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Src, Size); + HTransferMem TMem = new HTransferMem(Memory, MapInfo.Perm, Src, Size); - int Handle = Ns.Os.Handles.GenerateId(HndData); - - ThreadState.X1 = (ulong)Handle; + ulong Handle = (ulong)Process.HandleTable.OpenHandle(TMem); + ThreadState.X0 = 0; + ThreadState.X1 = Handle; } private static bool IsValidPosition(long Position) diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index f70090352..671a32d36 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -3,7 +3,6 @@ using ChocolArm64.State; using Ryujinx.Core.OsHle.Exceptions; using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; -using Ryujinx.Core.OsHle.IpcServices; using System; using System.Threading; @@ -35,7 +34,7 @@ namespace Ryujinx.Core.OsHle.Svc { int Handle = (int)ThreadState.X0; - Ns.Os.CloseHandle(Handle); + Process.HandleTable.CloseHandle(Handle); ThreadState.X0 = 0; } @@ -80,10 +79,12 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Validate that app has perms to access the service, and that the service //actually exists, return error codes otherwise. - HSession Session = new HSession(ServiceFactory.MakeService(Name)); + HSession Session = new HSession(Process.Services.GetService(Name)); - ThreadState.X1 = (ulong)Ns.Os.Handles.GenerateId(Session); + ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session); + ThreadState.X0 = 0; + ThreadState.X1 = Handle; } private void SvcSendSyncRequest(AThreadState ThreadState) @@ -119,13 +120,21 @@ namespace Ryujinx.Core.OsHle.Svc byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size); - HSession Session = Ns.Os.Handles.GetData(Handle); + HSession Session = Process.HandleTable.GetData(Handle); IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr, Session is HDomain); if (Session != null) { - IpcHandler.IpcCall(Ns, Memory, Session, Cmd, ThreadState.ThreadId, CmdPtr, Handle); + IpcHandler.IpcCall( + Ns, + Process, + Memory, + Session, + Cmd, + ThreadState.ThreadId, + CmdPtr, + Handle); byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size); diff --git a/Ryujinx.Core/OsHle/Svc/SvcThread.cs b/Ryujinx.Core/OsHle/Svc/SvcThread.cs index 6afd2e610..231ee2a23 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcThread.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThread.cs @@ -39,7 +39,7 @@ namespace Ryujinx.Core.OsHle.Svc { int Handle = (int)ThreadState.X0; - HThread Thread = Ns.Os.Handles.GetData(Handle); + HThread Thread = Process.HandleTable.GetData(Handle); if (Thread != null) { @@ -51,6 +51,13 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Error codes. } + private void SvcExitThread(AThreadState ThreadState) + { + HThread CurrThread = Process.GetThread(ThreadState.Tpidr); + + CurrThread.Thread.StopExecution(); + } + private void SvcSleepThread(AThreadState ThreadState) { ulong NanoSecs = ThreadState.X0; @@ -71,7 +78,7 @@ namespace Ryujinx.Core.OsHle.Svc { int Handle = (int)ThreadState.X1; - HThread Thread = Ns.Os.Handles.GetData(Handle); + HThread Thread = Process.HandleTable.GetData(Handle); if (Thread != null) { @@ -87,7 +94,7 @@ namespace Ryujinx.Core.OsHle.Svc int Handle = (int)ThreadState.X1; int Prio = (int)ThreadState.X0; - HThread Thread = Ns.Os.Handles.GetData(Handle); + HThread Thread = Process.HandleTable.GetData(Handle); if (Thread != null) { @@ -110,7 +117,7 @@ namespace Ryujinx.Core.OsHle.Svc { int Handle = (int)ThreadState.X0; - HThread Thread = Ns.Os.Handles.GetData(Handle); + HThread Thread = Process.HandleTable.GetData(Handle); if (Thread != null) { diff --git a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs index 6e488da58..38356073e 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Core.OsHle.Svc long MutexAddress = (long)ThreadState.X1; int RequestingThreadHandle = (int)ThreadState.X2; - HThread RequestingThread = Ns.Os.Handles.GetData(RequestingThreadHandle); + HThread RequestingThread = Process.HandleTable.GetData(RequestingThreadHandle); Mutex M = new Mutex(Process, MutexAddress, OwnerThreadHandle); @@ -43,7 +43,7 @@ namespace Ryujinx.Core.OsHle.Svc int ThreadHandle = (int)ThreadState.X2; long Timeout = (long)ThreadState.X3; - HThread Thread = Ns.Os.Handles.GetData(ThreadHandle); + HThread Thread = Process.HandleTable.GetData(ThreadHandle); Mutex M = new Mutex(Process, MutexAddress, ThreadHandle); diff --git a/Ryujinx.Core/OsHle/Utilities/IdPool.cs b/Ryujinx.Core/OsHle/Utilities/IdPool.cs deleted file mode 100644 index a7e181fa2..000000000 --- a/Ryujinx.Core/OsHle/Utilities/IdPool.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; - -namespace Ryujinx.Core.OsHle.Utilities -{ - class IdPool - { - private HashSet Ids; - - private int CurrId; - private int MinId; - private int MaxId; - - public IdPool(int Min, int Max) - { - Ids = new HashSet(); - - CurrId = Min; - MinId = Min; - MaxId = Max; - } - - public IdPool() : this(1, int.MaxValue) { } - - public int GenerateId() - { - lock (Ids) - { - for (int Cnt = MinId; Cnt < MaxId; Cnt++) - { - if (Ids.Add(CurrId)) - { - return CurrId; - } - - if (CurrId++ == MaxId) - { - CurrId = MinId; - } - } - - return -1; - } - } - - public bool DeleteId(int Id) - { - lock (Ids) - { - return Ids.Remove(Id); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index f7ce109f6..487f3bdb9 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -1,4 +1,3 @@ -using ChocolArm64.Memory; using Ryujinx.Core.Input; using Ryujinx.Core.OsHle; using Ryujinx.Core.Settings; @@ -10,8 +9,6 @@ namespace Ryujinx.Core { public class Switch : IDisposable { - internal AMemory Memory { get; private set; } - internal NsGpu Gpu { get; private set; } internal Horizon Os { get; private set; } internal VirtualFs VFs { get; private set; } @@ -24,13 +21,11 @@ namespace Ryujinx.Core public Switch(IGalRenderer Renderer) { - Memory = new AMemory(); - Gpu = new NsGpu(Renderer); VFs = new VirtualFs(); - Hid = new Hid(Memory); + Hid = new Hid(); Statistics = new PerformanceStatistics(); @@ -42,11 +37,6 @@ namespace Ryujinx.Core Settings = new SetSys(); } - public void FinalizeAllProcesses() - { - Os.FinalizeAllProcesses(); - } - public void LoadCart(string ExeFsDir, string RomFsFile = null) { Os.LoadCart(ExeFsDir, RomFsFile); @@ -67,12 +57,11 @@ namespace Ryujinx.Core Dispose(true); } - protected virtual void Dispose(bool disposing) + protected virtual void Dispose(bool Disposing) { - if (disposing) + if (Disposing) { - Memory.Dispose(); - + Os.Dispose(); VFs.Dispose(); } } diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index 83d2c699f..aa4eac4e1 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -8,6 +8,7 @@ namespace Ryujinx.Graphics.Gal void RunActions(); void InitializeFrameBuffer(); + void ResetFrameBuffer(); void Render(); void SetWindowSize(int Width, int Height); void SetFrameBuffer( diff --git a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs index 7dc4bffe3..b761811f6 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs @@ -24,6 +24,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL private byte* FbPtr; + private object FbPtrLock; + public FrameBuffer(int Width, int Height) { if (Width < 0) @@ -36,6 +38,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL throw new ArgumentOutOfRangeException(nameof(Height)); } + FbPtrLock = new object(); + TexWidth = Width; TexHeight = Height; @@ -152,7 +156,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL throw new ArgumentOutOfRangeException(nameof(Height)); } - FbPtr = Fb; + lock (FbPtrLock) + { + FbPtr = Fb; + } if (Width != TexWidth || Height != TexHeight) @@ -178,17 +185,28 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.Uniform2(OffsetUniformLocation, Offs); } + public void Reset() + { + lock (FbPtrLock) + { + FbPtr = null; + } + } + public void Render() { - if (FbPtr == null) + lock (FbPtrLock) { - return; - } + if (FbPtr == null) + { + return; + } - for (int Y = 0; Y < TexHeight; Y++) - for (int X = 0; X < TexWidth; X++) - { - Pixels[X + Y * TexWidth] = *((int*)(FbPtr + GetSwizzleOffset(X, Y))); + for (int Y = 0; Y < TexHeight; Y++) + for (int X = 0; X < TexWidth; X++) + { + Pixels[X + Y * TexWidth] = *((int*)(FbPtr + GetSwizzleOffset(X, Y))); + } } GL.BindTexture(TextureTarget.Texture2D, TexHandle); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index bdedfc1a8..002e54dad 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -43,6 +43,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL FbRenderer = new FrameBuffer(1280, 720); } + public void ResetFrameBuffer() + { + FbRenderer.Reset(); + } + public void QueueAction(Action ActionMthd) { ActionsQueue.Enqueue(ActionMthd); diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index 0b35a7a6c..b5bbdbc17 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -28,7 +28,7 @@ namespace Ryujinx.Tests.Cpu ATranslator Translator = new ATranslator(); Memory = new AMemory(); Memory.Manager.Map(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute); - Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint); + Thread = new AThread(Translator, Memory, EntryPoint); } [TearDown] From 8cb23c133baf2a371f6dfaaba0c7db7216c2efd1 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 12 Mar 2018 01:15:39 -0300 Subject: [PATCH 66/67] Add bsd:s service variant again --- Ryujinx.Core/OsHle/ServiceMgr.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Ryujinx.Core/OsHle/ServiceMgr.cs b/Ryujinx.Core/OsHle/ServiceMgr.cs index cbf6386f9..f59647afe 100644 --- a/Ryujinx.Core/OsHle/ServiceMgr.cs +++ b/Ryujinx.Core/OsHle/ServiceMgr.cs @@ -48,6 +48,7 @@ namespace Ryujinx.Core.OsHle case "appletOE": Service = new ServiceAppletOE(); break; case "audout:u": Service = new ServiceAudOut(); break; case "audren:u": Service = new ServiceAudRen(); break; + case "bsd:s": Service = new ServiceBsd(); break; case "bsd:u": Service = new ServiceBsd(); break; case "friend:a": Service = new ServiceFriend(); break; case "fsp-srv": Service = new ServiceFspSrv(); break; From e32f27158fa314492af35800eb0c84ca0e7b5bd4 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 12 Mar 2018 02:07:48 -0300 Subject: [PATCH 67/67] Stub GetAudioRenderersProcessMasterVolume and avoid blowing up the stack inside HDomains Dispose method --- Ryujinx.Core/OsHle/Handles/HDomain.cs | 2 +- Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Ryujinx.Core/OsHle/Handles/HDomain.cs b/Ryujinx.Core/OsHle/Handles/HDomain.cs index ac99b03a6..26c604554 100644 --- a/Ryujinx.Core/OsHle/Handles/HDomain.cs +++ b/Ryujinx.Core/OsHle/Handles/HDomain.cs @@ -37,7 +37,7 @@ namespace Ryujinx.Core.OsHle.Handles { foreach (object Obj in Objects) { - if (Obj is IDisposable DisposableObj) + if (Obj != this && Obj is IDisposable DisposableObj) { DisposableObj.Dispose(); } diff --git a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs index eccc699c4..15bda04cc 100644 --- a/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs +++ b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs @@ -15,8 +15,9 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud { m_Commands = new Dictionary() { - { 0, OpenAudioRenderer }, - { 1, GetAudioRendererWorkBufferSize }, + { 0, OpenAudioRenderer }, + { 1, GetAudioRendererWorkBufferSize }, + { 2, GetAudioRenderersProcessMasterVolume } }; } @@ -47,5 +48,12 @@ namespace Ryujinx.Core.OsHle.IpcServices.Aud return 0; } + + public long GetAudioRenderersProcessMasterVolume(ServiceCtx Context) + { + Context.ResponseData.Write(0); + + return 0; + } } } \ No newline at end of file