This commit is contained in:
gdkchan 2018-02-04 20:08:20 -03:00
commit b7e1d9930d
230 changed files with 17548 additions and 0 deletions

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -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;
}
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.OsHle.Objects
{
class AmIAudioController
{
}
}

View file

@ -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;
}
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.OsHle.Objects
{
class AmIDebugFunctions
{
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.OsHle.Objects
{
class AmIDisplayController
{
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.OsHle.Objects
{
class AmILibraryAppletCreator
{
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.OsHle.Objects
{
class AmIParentalControlService
{
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.OsHle.Objects
{
class FriendIFriendService
{
}
}

View file

@ -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();
}
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.OsHle.Objects
{
class TimeISteadyClock
{
}
}

View file

@ -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;
}
}
}

View file

@ -0,0 +1,7 @@
namespace Ryujinx.OsHle.Objects
{
class TimeITimeZoneService
{
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -0,0 +1,10 @@
namespace Ryujinx.OsHle.Objects
{
class ViISystemDisplayService
{
public static long SetLayerZ(ServiceCtx Context)
{
return 0;
}
}
}