diff options
Diffstat (limited to 'Ryujinx/OsHle/Objects')
30 files changed, 1130 insertions, 0 deletions
diff --git a/Ryujinx/OsHle/Objects/AccIManagerForApplication.cs b/Ryujinx/OsHle/Objects/AccIManagerForApplication.cs new file mode 100644 index 00000000..8e2a002b --- /dev/null +++ b/Ryujinx/OsHle/Objects/AccIManagerForApplication.cs @@ -0,0 +1,17 @@ +namespace Ryujinx.OsHle.Objects +{ + class AccIManagerForApplication + { + public static long CheckAvailability(ServiceCtx Context) + { + return 0; + } + + public static long GetAccountId(ServiceCtx Context) + { + Context.ResponseData.Write(0xcafeL); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AccIProfile.cs b/Ryujinx/OsHle/Objects/AccIProfile.cs new file mode 100644 index 00000000..2dbe189d --- /dev/null +++ b/Ryujinx/OsHle/Objects/AccIProfile.cs @@ -0,0 +1,18 @@ +namespace Ryujinx.OsHle.Objects +{ + class AccIProfile + { + public static long GetBase(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + Context.ResponseData.Write(0L); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIApplicationFunctions.cs b/Ryujinx/OsHle/Objects/AmIApplicationFunctions.cs new file mode 100644 index 00000000..e174f943 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIApplicationFunctions.cs @@ -0,0 +1,56 @@ +using System.IO; + +using static Ryujinx.OsHle.Objects.ObjHelper; + +namespace Ryujinx.OsHle.Objects +{ + class AmIApplicationFunctions + { + private const uint LaunchParamsMagic = 0xc79497ca; + + public static long PopLaunchParameter(ServiceCtx Context) + { + //Only the first 0x18 bytes of the Data seems to be actually used. + MakeObject(Context, new AmIStorage(MakeLaunchParams())); + + return 0; + } + + public static long EnsureSaveData(ServiceCtx Context) + { + long UIdLow = Context.RequestData.ReadInt64(); + long UIdHigh = Context.RequestData.ReadInt64(); + + Context.ResponseData.Write(0L); + + return 0; + } + + public static long GetDesiredLanguage(ServiceCtx Context) + { + //This is an enumerator where each number is a differnet language. + //0 is Japanese and 1 is English, need to figure out the other codes. + Context.ResponseData.Write(1L); + + return 0; + } + + private static byte[] MakeLaunchParams() + { + //Size needs to be at least 0x88 bytes otherwise application errors. + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + MS.SetLength(0x88); + + Writer.Write(LaunchParamsMagic); + Writer.Write(1); //IsAccountSelected? Only lower 8 bits actually used. + Writer.Write(1L); //User Id Low (note: User Id needs to be != 0) + Writer.Write(0L); //User Id High + + return MS.ToArray(); + } + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIApplicationProxy.cs b/Ryujinx/OsHle/Objects/AmIApplicationProxy.cs new file mode 100644 index 00000000..2b0bc346 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIApplicationProxy.cs @@ -0,0 +1,63 @@ +using static Ryujinx.OsHle.Objects.ObjHelper; + +namespace Ryujinx.OsHle.Objects +{ + class AmIApplicationProxy + { + public static long GetCommonStateGetter(ServiceCtx Context) + { + MakeObject(Context, new AmICommonStateGetter()); + + return 0; + } + + public static long GetSelfController(ServiceCtx Context) + { + MakeObject(Context, new AmISelfController()); + + return 0; + } + + public static long GetWindowController(ServiceCtx Context) + { + MakeObject(Context, new AmIWindowController()); + + return 0; + } + + public static long GetAudioController(ServiceCtx Context) + { + MakeObject(Context, new AmIAudioController()); + + return 0; + } + + public static long GetDisplayController(ServiceCtx Context) + { + MakeObject(Context, new AmIDisplayController()); + + return 0; + } + + public static long GetLibraryAppletCreator(ServiceCtx Context) + { + MakeObject(Context, new AmILibraryAppletCreator()); + + return 0; + } + + public static long GetApplicationFunctions(ServiceCtx Context) + { + MakeObject(Context, new AmIApplicationFunctions()); + + return 0; + } + + public static long GetDebugFunctions(ServiceCtx Context) + { + MakeObject(Context, new AmIDebugFunctions()); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIAudioController.cs b/Ryujinx/OsHle/Objects/AmIAudioController.cs new file mode 100644 index 00000000..59d94bda --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIAudioController.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.OsHle.Objects +{ + class AmIAudioController + { + + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmICommonStateGetter.cs b/Ryujinx/OsHle/Objects/AmICommonStateGetter.cs new file mode 100644 index 00000000..32f065c8 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmICommonStateGetter.cs @@ -0,0 +1,55 @@ +namespace Ryujinx.OsHle.Objects +{ + class AmICommonStateGetter + { + private enum FocusState + { + InFocus = 1, + OutOfFocus = 2 + } + + private enum OperationMode + { + Handheld = 0, + Docked = 1 + } + + public static long GetEventHandle(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + + return 0; + } + + public static long ReceiveMessage(ServiceCtx Context) + { + //Program expects 0xF at 0x17ae70 on puyo sdk, + //otherwise runs on a infinite loop until it reads said value. + //What it means is still unknown. + Context.ResponseData.Write(0xfL); + + return 0; //0x680; + } + + public static long GetOperationMode(ServiceCtx Context) + { + Context.ResponseData.Write((byte)OperationMode.Handheld); + + return 0; + } + + public static long GetPerformanceMode(ServiceCtx Context) + { + Context.ResponseData.Write((byte)0); + + return 0; + } + + public static long GetCurrentFocusState(ServiceCtx Context) + { + Context.ResponseData.Write((byte)FocusState.InFocus); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIDebugFunctions.cs b/Ryujinx/OsHle/Objects/AmIDebugFunctions.cs new file mode 100644 index 00000000..9794c43f --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIDebugFunctions.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.OsHle.Objects +{ + class AmIDebugFunctions + { + + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIDisplayController.cs b/Ryujinx/OsHle/Objects/AmIDisplayController.cs new file mode 100644 index 00000000..be36ca0c --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIDisplayController.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.OsHle.Objects +{ + class AmIDisplayController + { + + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmILibraryAppletCreator.cs b/Ryujinx/OsHle/Objects/AmILibraryAppletCreator.cs new file mode 100644 index 00000000..585df9e9 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmILibraryAppletCreator.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.OsHle.Objects +{ + class AmILibraryAppletCreator + { + + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIParentalControlService.cs b/Ryujinx/OsHle/Objects/AmIParentalControlService.cs new file mode 100644 index 00000000..12c3c2a9 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIParentalControlService.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.OsHle.Objects +{ + class AmIParentalControlService + { + + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmISelfController.cs b/Ryujinx/OsHle/Objects/AmISelfController.cs new file mode 100644 index 00000000..33cde095 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmISelfController.cs @@ -0,0 +1,28 @@ +namespace Ryujinx.OsHle.Objects +{ + class AmISelfController + { + public static long SetOperationModeChangedNotification(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + + public static long SetPerformanceModeChangedNotification(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + + public static long SetFocusHandlingMode(ServiceCtx Context) + { + bool Flag1 = Context.RequestData.ReadByte() != 0 ? true : false; + bool Flag2 = Context.RequestData.ReadByte() != 0 ? true : false; + bool Flag3 = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIStorage.cs b/Ryujinx/OsHle/Objects/AmIStorage.cs new file mode 100644 index 00000000..7e608ac8 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIStorage.cs @@ -0,0 +1,23 @@ +using static Ryujinx.OsHle.Objects.ObjHelper; + +namespace Ryujinx.OsHle.Objects +{ + class AmIStorage + { + public byte[] Data { get; private set; } + + public AmIStorage(byte[] Data) + { + this.Data = Data; + } + + public static long Open(ServiceCtx Context) + { + AmIStorage Storage = Context.GetObject<AmIStorage>(); + + MakeObject(Context, new AmIStorageAccessor(Storage)); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIStorageAccessor.cs b/Ryujinx/OsHle/Objects/AmIStorageAccessor.cs new file mode 100644 index 00000000..62007ef8 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIStorageAccessor.cs @@ -0,0 +1,56 @@ +using ChocolArm64.Memory; +using System; + +namespace Ryujinx.OsHle.Objects +{ + class AmIStorageAccessor + { + public AmIStorage Storage { get; private set; } + + public AmIStorageAccessor(AmIStorage Storage) + { + this.Storage = Storage; + } + + public static long GetSize(ServiceCtx Context) + { + AmIStorageAccessor Accessor = Context.GetObject<AmIStorageAccessor>(); + + Context.ResponseData.Write((long)Accessor.Storage.Data.Length); + + return 0; + } + + public static long Read(ServiceCtx Context) + { + AmIStorageAccessor Accessor = Context.GetObject<AmIStorageAccessor>(); + + AmIStorage Storage = Accessor.Storage; + + long ReadPosition = Context.RequestData.ReadInt64(); + + if (Context.Request.RecvListBuff.Count > 0) + { + long Position = Context.Request.RecvListBuff[0].Position; + short Size = Context.Request.RecvListBuff[0].Size; + + byte[] Data; + + if (Storage.Data.Length > Size) + { + Data = new byte[Size]; + + Buffer.BlockCopy(Storage.Data, 0, Data, 0, Size); + } + else + { + Data = Storage.Data; + } + + AMemoryHelper.WriteBytes(Context.Memory, Position, Data); + } + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AmIWindowController.cs b/Ryujinx/OsHle/Objects/AmIWindowController.cs new file mode 100644 index 00000000..ea967ae8 --- /dev/null +++ b/Ryujinx/OsHle/Objects/AmIWindowController.cs @@ -0,0 +1,17 @@ +namespace Ryujinx.OsHle.Objects +{ + class AmIWindowController + { + public static long GetAppletResourceUserId(ServiceCtx Context) + { + Context.ResponseData.Write(0L); + + return 0; + } + + public static long AcquireForegroundRights(ServiceCtx Context) + { + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/ApmISession.cs b/Ryujinx/OsHle/Objects/ApmISession.cs new file mode 100644 index 00000000..2b2c0351 --- /dev/null +++ b/Ryujinx/OsHle/Objects/ApmISession.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.OsHle.Objects +{ + class ApmISession + { + public static long SetPerformanceConfiguration(ServiceCtx Context) + { + int PerfMode = Context.RequestData.ReadInt32(); + int PerfConfig = Context.RequestData.ReadInt32(); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs b/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs new file mode 100644 index 00000000..b451d07b --- /dev/null +++ b/Ryujinx/OsHle/Objects/AudIAudioRenderer.cs @@ -0,0 +1,36 @@ +namespace Ryujinx.OsHle.Objects +{ + class AudIAudioRenderer + { + public static long RequestUpdateAudioRenderer(ServiceCtx Context) + { + long Position = Context.Request.ReceiveBuff[0].Position; + + //0x40 bytes header + Context.Memory.WriteInt32(Position + 0x4, 0xb0); //Behavior Out State Size? (note: this is the last section) + Context.Memory.WriteInt32(Position + 0x8, 0x18e0); //Memory Pool Out State Size? + Context.Memory.WriteInt32(Position + 0xc, 0x600); //Voice Out State Size? + Context.Memory.WriteInt32(Position + 0x14, 0xe0); //Effect Out State Size? + Context.Memory.WriteInt32(Position + 0x1c, 0x20); //Sink Out State Size? + Context.Memory.WriteInt32(Position + 0x20, 0x10); //Performance Out State Size? + Context.Memory.WriteInt32(Position + 0x3c, 0x20e0); //Total Size (including 0x40 bytes header) + + for (int Offset = 0x40; Offset < 0x40 + 0x18e0; Offset += 0x10) + { + Context.Memory.WriteInt32(Position + Offset, 5); + } + + return 0; + } + + public static long StartAudioRenderer(ServiceCtx Context) + { + return 0; + } + + public static long QuerySystemEvent(ServiceCtx Context) + { + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/FriendIFriendService.cs b/Ryujinx/OsHle/Objects/FriendIFriendService.cs new file mode 100644 index 00000000..9a39380a --- /dev/null +++ b/Ryujinx/OsHle/Objects/FriendIFriendService.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.OsHle.Objects +{ + class FriendIFriendService + { + + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/FspSrvIFile.cs b/Ryujinx/OsHle/Objects/FspSrvIFile.cs new file mode 100644 index 00000000..4b9f8c37 --- /dev/null +++ b/Ryujinx/OsHle/Objects/FspSrvIFile.cs @@ -0,0 +1,72 @@ +using ChocolArm64.Memory; +using System; + +using System.IO; + +namespace Ryujinx.OsHle.Objects +{ + class FspSrvIFile : IDisposable + { + public Stream BaseStream { get; private set; } + + public FspSrvIFile(Stream BaseStream) + { + this.BaseStream = BaseStream; + } + + public static long Read(ServiceCtx Context) + { + FspSrvIFile File = Context.GetObject<FspSrvIFile>(); + + long Position = Context.Request.ReceiveBuff[0].Position; + + long Zero = Context.RequestData.ReadInt64(); + long Offset = Context.RequestData.ReadInt64(); + long Size = Context.RequestData.ReadInt64(); + + byte[] Data = new byte[Size]; + + int ReadSize = File.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); + + return 0; + } + + public static long Write(ServiceCtx Context) + { + FspSrvIFile File = Context.GetObject<FspSrvIFile>(); + + long Position = Context.Request.SendBuff[0].Position; + + long Zero = Context.RequestData.ReadInt64(); + long Offset = Context.RequestData.ReadInt64(); + long Size = Context.RequestData.ReadInt64(); + + byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, Position, (int)Size); + + File.BaseStream.Seek(Offset, SeekOrigin.Begin); + File.BaseStream.Write(Data, 0, (int)Size); + + return 0; + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && BaseStream != null) + { + BaseStream.Dispose(); + } + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/FspSrvIFileSystem.cs b/Ryujinx/OsHle/Objects/FspSrvIFileSystem.cs new file mode 100644 index 00000000..fed1c55a --- /dev/null +++ b/Ryujinx/OsHle/Objects/FspSrvIFileSystem.cs @@ -0,0 +1,70 @@ +using ChocolArm64.Memory; +using System.IO; + +using static Ryujinx.OsHle.Objects.ObjHelper; + +namespace Ryujinx.OsHle.Objects +{ + class FspSrvIFileSystem + { + public string FilePath { get; private set; } + + public FspSrvIFileSystem(string Path) + { + this.FilePath = Path; + } + + public static long GetEntryType(ServiceCtx Context) + { + FspSrvIFileSystem FileSystem = Context.GetObject<FspSrvIFileSystem>(); + + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string FileName = Context.Ns.VFs.GetFullPath(FileSystem.FilePath, Name); + + if (FileName == null) + { + //TODO: Correct error code. + return -1; + } + + bool IsFile = File.Exists(FileName); + + Context.ResponseData.Write(IsFile ? 1 : 0); + + return 0; + } + + public static long OpenFile(ServiceCtx Context) + { + FspSrvIFileSystem FileSystem = Context.GetObject<FspSrvIFileSystem>(); + + long Position = Context.Request.PtrBuff[0].Position; + + int FilterFlags = Context.RequestData.ReadInt32(); + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + string FileName = Context.Ns.VFs.GetFullPath(FileSystem.FilePath, Name); + + if (FileName == null) + { + //TODO: Correct error code. + return -1; + } + + FileStream Stream = new FileStream(FileName, FileMode.OpenOrCreate); + + MakeObject(Context, new FspSrvIFile(Stream)); + + return 0; + } + + public static long Commit(ServiceCtx Context) + { + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/FspSrvIStorage.cs b/Ryujinx/OsHle/Objects/FspSrvIStorage.cs new file mode 100644 index 00000000..76ad8917 --- /dev/null +++ b/Ryujinx/OsHle/Objects/FspSrvIStorage.cs @@ -0,0 +1,44 @@ +using ChocolArm64.Memory; +using Ryujinx.OsHle.Ipc; +using System.IO; + +namespace Ryujinx.OsHle.Objects +{ + class FspSrvIStorage + { + public Stream BaseStream { get; private set; } + + public FspSrvIStorage(Stream BaseStream) + { + this.BaseStream = BaseStream; + } + + public static long Read(ServiceCtx Context) + { + FspSrvIStorage Storage = Context.GetObject<FspSrvIStorage>(); + + long Offset = Context.RequestData.ReadInt64(); + long Size = Context.RequestData.ReadInt64(); + + if (Context.Request.ReceiveBuff.Count > 0) + { + IpcBuffDesc BuffDesc = Context.Request.ReceiveBuff[0]; + + //Use smaller length to avoid overflows. + if (Size > BuffDesc.Size) + { + Size = BuffDesc.Size; + } + + byte[] Data = new byte[Size]; + + Storage.BaseStream.Seek(Offset, SeekOrigin.Begin); + Storage.BaseStream.Read(Data, 0, Data.Length); + + AMemoryHelper.WriteBytes(Context.Memory, BuffDesc.Position, Data); + } + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/HidIAppletResource.cs b/Ryujinx/OsHle/Objects/HidIAppletResource.cs new file mode 100644 index 00000000..73b948df --- /dev/null +++ b/Ryujinx/OsHle/Objects/HidIAppletResource.cs @@ -0,0 +1,22 @@ +using Ryujinx.OsHle.Handles; +using Ryujinx.OsHle.Ipc; + +namespace Ryujinx.OsHle.Objects +{ + class HidIAppletResource + { + public HSharedMem Handle; + + public HidIAppletResource(HSharedMem Handle) + { + this.Handle = Handle; + } + + public static long GetSharedMemoryHandle(ServiceCtx Context) + { + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.HidHandle); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/ObjHelper.cs b/Ryujinx/OsHle/Objects/ObjHelper.cs new file mode 100644 index 00000000..e37f5320 --- /dev/null +++ b/Ryujinx/OsHle/Objects/ObjHelper.cs @@ -0,0 +1,24 @@ +using Ryujinx.OsHle.Handles; +using Ryujinx.OsHle.Ipc; + +namespace Ryujinx.OsHle.Objects +{ + static class ObjHelper + { + public static void MakeObject(ServiceCtx Context, object Obj) + { + if (Context.Session is HDomain Dom) + { + Context.Response.ResponseObjIds.Add(Dom.GenertateObjectId(Obj)); + } + else + { + HSessionObj HndData = new HSessionObj(Context.Session, Obj); + + int VHandle = Context.Ns.Os.Handles.GenerateId(HndData); + + Context.Response.HandleDesc = IpcHandleDesc.MakeMove(VHandle); + } + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/Parcel.cs b/Ryujinx/OsHle/Objects/Parcel.cs new file mode 100644 index 00000000..0d322bab --- /dev/null +++ b/Ryujinx/OsHle/Objects/Parcel.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; + +namespace Ryujinx.OsHle.Objects.Android +{ + static class Parcel + { + public static byte[] GetParcelData(byte[] Parcel) + { + if (Parcel == null) + { + throw new ArgumentNullException(nameof(Parcel)); + } + + using (MemoryStream MS = new MemoryStream(Parcel)) + { + BinaryReader Reader = new BinaryReader(MS); + + int DataSize = Reader.ReadInt32(); + int DataOffset = Reader.ReadInt32(); + int ObjsSize = Reader.ReadInt32(); + int ObjsOffset = Reader.ReadInt32(); + + MS.Seek(DataOffset - 0x10, SeekOrigin.Current); + + return Reader.ReadBytes(DataSize); + } + } + + public static byte[] MakeParcel(byte[] Data, byte[] Objs) + { + if (Data == null) + { + throw new ArgumentNullException(nameof(Data)); + } + + if (Objs == null) + { + throw new ArgumentNullException(nameof(Objs)); + } + + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + Writer.Write(Data.Length); + Writer.Write(0x10); + Writer.Write(Objs.Length); + Writer.Write(Data.Length + 0x10); + + Writer.Write(Data); + Writer.Write(Objs); + + return MS.ToArray(); + } + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/TimeISteadyClock.cs b/Ryujinx/OsHle/Objects/TimeISteadyClock.cs new file mode 100644 index 00000000..ead8c41a --- /dev/null +++ b/Ryujinx/OsHle/Objects/TimeISteadyClock.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.OsHle.Objects +{ + class TimeISteadyClock + { + + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/TimeISystemClock.cs b/Ryujinx/OsHle/Objects/TimeISystemClock.cs new file mode 100644 index 00000000..d9a3a073 --- /dev/null +++ b/Ryujinx/OsHle/Objects/TimeISystemClock.cs @@ -0,0 +1,16 @@ +using System; + +namespace Ryujinx.OsHle.Objects +{ + class TimeISystemClock + { + private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + public static long GetCurrentTime(ServiceCtx Context) + { + Context.ResponseData.Write((long)(DateTime.Now - Epoch).TotalSeconds); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/TimeITimeZoneService.cs b/Ryujinx/OsHle/Objects/TimeITimeZoneService.cs new file mode 100644 index 00000000..af5490a6 --- /dev/null +++ b/Ryujinx/OsHle/Objects/TimeITimeZoneService.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.OsHle.Objects +{ + class TimeITimeZoneService + { + + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/ViIApplicationDisplayService.cs b/Ryujinx/OsHle/Objects/ViIApplicationDisplayService.cs new file mode 100644 index 00000000..81616ae1 --- /dev/null +++ b/Ryujinx/OsHle/Objects/ViIApplicationDisplayService.cs @@ -0,0 +1,148 @@ +using ChocolArm64.Memory; +using Ryujinx.OsHle.Handles; +using Ryujinx.OsHle.Ipc; +using System.IO; + +using static Ryujinx.OsHle.Objects.Android.Parcel; +using static Ryujinx.OsHle.Objects.ObjHelper; + +namespace Ryujinx.OsHle.Objects +{ + class ViIApplicationDisplayService + { + public static long GetRelayService(ServiceCtx Context) + { + MakeObject(Context, new ViIHOSBinderDriver()); + + return 0; + } + + public static long GetSystemDisplayService(ServiceCtx Context) + { + MakeObject(Context, new ViISystemDisplayService()); + + return 0; + } + + public static long GetManagerDisplayService(ServiceCtx Context) + { + MakeObject(Context, new ViIManagerDisplayService()); + + return 0; + } + + public static long OpenDisplay(ServiceCtx Context) + { + string Name = GetDisplayName(Context); + + long DisplayId = Context.Ns.Os.Displays.GenerateId(new Display(Name)); + + Context.ResponseData.Write(DisplayId); + + return 0; + } + + public static long OpenLayer(ServiceCtx Context) + { + long LayerId = Context.RequestData.ReadInt64(); + long UserId = Context.RequestData.ReadInt64(); + + long ParcelPtr = Context.Request.ReceiveBuff[0].Position; + + byte[] Parcel = MakeIGraphicsBufferProducer(ParcelPtr); + + AMemoryHelper.WriteBytes(Context.Memory, ParcelPtr, Parcel); + + Context.ResponseData.Write((long)Parcel.Length); + + return 0; + } + + public static long CreateStrayLayer(ServiceCtx Context) + { + long LayerFlags = Context.RequestData.ReadInt64(); + long DisplayId = Context.RequestData.ReadInt64(); + + long ParcelPtr = Context.Request.ReceiveBuff[0].Position; + + Display Disp = Context.Ns.Os.Displays.GetData<Display>((int)DisplayId); + + byte[] Parcel = MakeIGraphicsBufferProducer(ParcelPtr); + + AMemoryHelper.WriteBytes(Context.Memory, ParcelPtr, Parcel); + + Context.ResponseData.Write(0L); + Context.ResponseData.Write((long)Parcel.Length); + + return 0; + } + + public static long SetLayerScalingMode(ServiceCtx Context) + { + int ScalingMode = Context.RequestData.ReadInt32(); + long Unknown = Context.RequestData.ReadInt64(); + + return 0; + } + + public static long GetDisplayVSyncEvent(ServiceCtx Context) + { + string Name = GetDisplayName(Context); + + int Handle = Context.Ns.Os.Handles.GenerateId(new HEvent()); + + Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle); + + return 0; + } + + private static byte[] MakeIGraphicsBufferProducer(long BasePtr) + { + long Id = 0x20; + long CookiePtr = 0L; + + using (MemoryStream MS = new MemoryStream()) + { + BinaryWriter Writer = new BinaryWriter(MS); + + //flat_binder_object (size is 0x28) + Writer.Write(2); //Type (BINDER_TYPE_WEAK_BINDER) + Writer.Write(0); //Flags + Writer.Write((int)(Id >> 0)); + Writer.Write((int)(Id >> 32)); + Writer.Write((int)(CookiePtr >> 0)); + Writer.Write((int)(CookiePtr >> 32)); + Writer.Write((byte)'d'); + Writer.Write((byte)'i'); + Writer.Write((byte)'s'); + Writer.Write((byte)'p'); + Writer.Write((byte)'d'); + Writer.Write((byte)'r'); + Writer.Write((byte)'v'); + Writer.Write((byte)'\0'); + Writer.Write(0L); //Pad + + return MakeParcel(MS.ToArray(), new byte[] { 0, 0, 0, 0 }); + } + } + + private static string GetDisplayName(ServiceCtx Context) + { + string Name = string.Empty; + + for (int Index = 0; Index < 8 && + Context.RequestData.BaseStream.Position < + Context.RequestData.BaseStream.Length; Index++) + { + byte Chr = Context.RequestData.ReadByte(); + + if (Chr >= 0x20 && Chr < 0x7f) + { + Name += (char)Chr; + } + } + + return Name; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/ViIHOSBinderDriver.cs b/Ryujinx/OsHle/Objects/ViIHOSBinderDriver.cs new file mode 100644 index 00000000..72a472ae --- /dev/null +++ b/Ryujinx/OsHle/Objects/ViIHOSBinderDriver.cs @@ -0,0 +1,211 @@ +using ChocolArm64.Memory; +using Ryujinx.OsHle.Handles; +using Ryujinx.OsHle.Ipc; +using Ryujinx.OsHle.Utilities; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +using static Ryujinx.OsHle.Objects.Android.Parcel; + +namespace Ryujinx.OsHle.Objects +{ + class ViIHOSBinderDriver + { + private delegate long ServiceProcessRequest(ServiceCtx Context, byte[] ParcelData); + + private static Dictionary<(string, int), ServiceProcessRequest> InterfaceMthd = + new Dictionary<(string, int), ServiceProcessRequest>() + { + { ("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 }, + }; + + private class BufferObj + { + + } + + public IdPoolWithObj BufferSlots { get; private set; } + + public byte[] Gbfr; + + public ViIHOSBinderDriver() + { + BufferSlots = new IdPoolWithObj(); + } + + public static long TransactParcel(ServiceCtx Context) + { + int Id = Context.RequestData.ReadInt32(); + int Code = Context.RequestData.ReadInt32(); + + long DataPos = Context.Request.SendBuff[0].Position; + long DataSize = Context.Request.SendBuff[0].Size; + + byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, DataPos, (int)DataSize); + + Data = 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 (InterfaceMthd.TryGetValue((InterfaceName, Code), out ServiceProcessRequest ProcReq)) + { + return ProcReq(Context, Data); + } + else + { + throw new NotImplementedException($"{InterfaceName} {Code}"); + } + } + } + + private static long GraphicBufferProducerRequestBuffer(ServiceCtx Context, byte[] ParcelData) + { + ViIHOSBinderDriver BinderDriver = Context.GetObject<ViIHOSBinderDriver>(); + + int GbfrSize = BinderDriver.Gbfr?.Length ?? 0; + + byte[] Data = new byte[GbfrSize + 4]; + + if (BinderDriver.Gbfr != null) + { + Buffer.BlockCopy(BinderDriver.Gbfr, 0, Data, 0, GbfrSize); + } + + return MakeReplyParcel(Context, Data); + } + + private static long GraphicBufferProducerDequeueBuffer(ServiceCtx Context, byte[] ParcelData) + { + ViIHOSBinderDriver BinderDriver = Context.GetObject<ViIHOSBinderDriver>(); + + //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 = BinderDriver.BufferSlots.GenerateId(new BufferObj()); + + return MakeReplyParcel(Context, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + + private static long GraphicBufferProducerQueueBuffer(ServiceCtx Context, byte[] ParcelData) + { + return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); + } + + private static long GraphicBufferProducerCancelBuffer(ServiceCtx Context, byte[] ParcelData) + { + ViIHOSBinderDriver BinderDriver = Context.GetObject<ViIHOSBinderDriver>(); + + using (MemoryStream MS = new MemoryStream(ParcelData)) + { + BinaryReader Reader = new BinaryReader(MS); + + MS.Seek(0x50, SeekOrigin.Begin); + + int Slot = Reader.ReadInt32(); + + BinderDriver.BufferSlots.Delete(Slot); + + return MakeReplyParcel(Context, 0); + } + } + + private static long GraphicBufferProducerQuery(ServiceCtx Context, byte[] ParcelData) + { + return MakeReplyParcel(Context, 0, 0); + } + + private static long GraphicBufferProducerConnect(ServiceCtx Context, byte[] ParcelData) + { + return MakeReplyParcel(Context, 1280, 720, 0, 0, 0); + } + + private static long GraphicBufferPreallocateBuffer(ServiceCtx Context, byte[] ParcelData) + { + ViIHOSBinderDriver BinderDriver = Context.GetObject<ViIHOSBinderDriver>(); + + int GbfrSize = ParcelData.Length - 0x54; + + BinderDriver.Gbfr = new byte[GbfrSize]; + + Buffer.BlockCopy(ParcelData, 0x54, BinderDriver.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<HNvMap>(Handle); + + Context.Ns.Gpu.Renderer.FrameBufferPtr = + Context.Memory.Manager.GetPhys(NvMap.Address, AMemoryPerm.Read); + } + + return MakeReplyParcel(Context, 0); + } + + private static 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 static 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; + } + + public static long AdjustRefcount(ServiceCtx Context) + { + int Id = Context.RequestData.ReadInt32(); + int AddVal = Context.RequestData.ReadInt32(); + int Type = Context.RequestData.ReadInt32(); + + return 0; + } + + public static long GetNativeHandle(ServiceCtx Context) + { + int Id = Context.RequestData.ReadInt32(); + uint Unk = Context.RequestData.ReadUInt32(); + + Context.Response.HandleDesc = IpcHandleDesc.MakeMove(0xbadcafe); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/ViIManagerDisplayService.cs b/Ryujinx/OsHle/Objects/ViIManagerDisplayService.cs new file mode 100644 index 00000000..0fdca3ba --- /dev/null +++ b/Ryujinx/OsHle/Objects/ViIManagerDisplayService.cs @@ -0,0 +1,17 @@ +namespace Ryujinx.OsHle.Objects +{ + class ViIManagerDisplayService + { + public static long CreateManagedLayer(ServiceCtx Context) + { + Context.ResponseData.Write(0L); //LayerId + + return 0; + } + + public static long AddToLayerStack(ServiceCtx Context) + { + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx/OsHle/Objects/ViISystemDisplayService.cs b/Ryujinx/OsHle/Objects/ViISystemDisplayService.cs new file mode 100644 index 00000000..8d3a51f4 --- /dev/null +++ b/Ryujinx/OsHle/Objects/ViISystemDisplayService.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.OsHle.Objects +{ + class ViISystemDisplayService + { + public static long SetLayerZ(ServiceCtx Context) + { + return 0; + } + } +}
\ No newline at end of file |
