aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Vic/StructUnpacker.cs
blob: 62777aadd2de44535b0008b4d2d1a225a490d2e4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using Ryujinx.Graphics.Memory;
using System;

namespace Ryujinx.Graphics.Vic
{
    class StructUnpacker
    {
        private NvGpuVmm Vmm;

        private long Position;

        private ulong Buffer;
        private int   BuffPos;

        public StructUnpacker(NvGpuVmm Vmm, long Position)
        {
            this.Vmm      = Vmm;
            this.Position = Position;

            BuffPos = 64;
        }

        public int Read(int Bits)
        {
            if ((uint)Bits > 32)
            {
                throw new ArgumentOutOfRangeException(nameof(Bits));
            }

            int Value = 0;

            while (Bits > 0)
            {
                RefillBufferIfNeeded();

                int ReadBits = Bits;

                int MaxReadBits = 64 - BuffPos;

                if (ReadBits > MaxReadBits)
                {
                    ReadBits = MaxReadBits;
                }

                Value <<= ReadBits;

                Value |= (int)(Buffer >> BuffPos) & (int)(0xffffffff >> (32 - ReadBits));

                BuffPos += ReadBits;

                Bits -= ReadBits;
            }

            return Value;
        }

        private void RefillBufferIfNeeded()
        {
            if (BuffPos >= 64)
            {
                Buffer = Vmm.ReadUInt64(Position);

                Position += 8;

                BuffPos = 0;
            }
        }
    }
}