Ryujinx/Ryujinx.Graphics/Gpu/NsGpuPBEntry.cs

79 lines
2.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
namespace Ryujinx.Graphics.Gpu
{
public struct NsGpuPBEntry
{
public NsGpuRegister Register { get; private set; }
public int SubChannel { get; private set; }
private int[] m_Arguments;
public ReadOnlyCollection<int> Arguments => Array.AsReadOnly(m_Arguments);
public NsGpuPBEntry(NsGpuRegister Register, int SubChannel, params int[] Arguments)
{
this.Register = Register;
this.SubChannel = SubChannel;
this.m_Arguments = Arguments;
}
public static NsGpuPBEntry[] DecodePushBuffer(byte[] Data)
{
using (MemoryStream MS = new MemoryStream(Data))
{
BinaryReader Reader = new BinaryReader(MS);
List<NsGpuPBEntry> GpFifos = new List<NsGpuPBEntry>();
bool CanRead() => MS.Position + 4 <= MS.Length;
while (CanRead())
{
int Packed = Reader.ReadInt32();
int Reg = (Packed << 2) & 0x7ffc;
int SubC = (Packed >> 13) & 7;
int Args = (Packed >> 16) & 0x1fff;
int Mode = (Packed >> 29) & 7;
if (Mode == 4)
{
//Inline Mode.
GpFifos.Add(new NsGpuPBEntry((NsGpuRegister)Reg, SubC, Args));
}
else
{
//Word mode.
if (Mode == 1)
{
//Sequential Mode.
for (int Index = 0; Index < Args && CanRead(); Index++, Reg += 4)
{
GpFifos.Add(new NsGpuPBEntry((NsGpuRegister)Reg, SubC, Reader.ReadInt32()));
}
}
else
{
//Non-Sequential Mode.
int[] Arguments = new int[Args];
for (int Index = 0; Index < Args && CanRead(); Index++)
{
Arguments[Index] = Reader.ReadInt32();
}
GpFifos.Add(new NsGpuPBEntry((NsGpuRegister)Reg, SubC, Arguments));
}
}
}
return GpFifos.ToArray();
}
}
}
}