aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs
blob: df9209e60b6047a0dc60f6045bdda1e056e1b87d (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using LibHac;
using LibHac.Fs;
using System;

namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
{
    class IFile : IpcService, IDisposable
    {
        private LibHac.Fs.IFile _baseFile;

        public IFile(LibHac.Fs.IFile baseFile)
        {
            _baseFile = baseFile;
        }

        [Command(0)]
        // Read(u32 readOption, u64 offset, u64 size) -> (u64 out_size, buffer<u8, 0x46, 0> out_buf)
        public ResultCode Read(ServiceCtx context)
        {
            long position = context.Request.ReceiveBuff[0].Position;

            ReadOption readOption = (ReadOption)context.RequestData.ReadInt32();
            context.RequestData.BaseStream.Position += 4;

            long offset = context.RequestData.ReadInt64();
            long size   = context.RequestData.ReadInt64();

            byte[] data = new byte[size];
            int readSize;

            try
            {
                readSize = _baseFile.Read(data, offset, readOption);
            }
            catch (HorizonResultException ex)
            {
                return (ResultCode)ex.ResultValue.Value;
            }

            context.Memory.WriteBytes(position, data);

            context.ResponseData.Write((long)readSize);

            return ResultCode.Success;
        }

        [Command(1)]
        // Write(u32 writeOption, u64 offset, u64 size, buffer<u8, 0x45, 0>)
        public ResultCode Write(ServiceCtx context)
        {
            long position = context.Request.SendBuff[0].Position;

            WriteOption writeOption = (WriteOption)context.RequestData.ReadInt32();
            context.RequestData.BaseStream.Position += 4;

            long offset = context.RequestData.ReadInt64();
            long size   = context.RequestData.ReadInt64();

            byte[] data = context.Memory.ReadBytes(position, size);

            try
            {
                _baseFile.Write(data, offset, writeOption);
            }
            catch (HorizonResultException ex)
            {
                return (ResultCode)ex.ResultValue.Value;
            }

            return ResultCode.Success;
        }

        [Command(2)]
        // Flush()
        public ResultCode Flush(ServiceCtx context)
        {
            try
            {
                _baseFile.Flush();
            }
            catch (HorizonResultException ex)
            {
                return (ResultCode)ex.ResultValue.Value;
            }

            return ResultCode.Success;
        }

        [Command(3)]
        // SetSize(u64 size)
        public ResultCode SetSize(ServiceCtx context)
        {
            try
            {
                long size = context.RequestData.ReadInt64();

                _baseFile.SetSize(size);
            }
            catch (HorizonResultException ex)
            {
                return (ResultCode)ex.ResultValue.Value;
            }

            return ResultCode.Success;
        }

        [Command(4)]
        // GetSize() -> u64 fileSize
        public ResultCode GetSize(ServiceCtx context)
        {
            try
            {
                context.ResponseData.Write(_baseFile.GetSize());
            }
            catch (HorizonResultException ex)
            {
                return (ResultCode)ex.ResultValue.Value;
            }

            return ResultCode.Success;
        }

        public void Dispose()
        {
            Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _baseFile?.Dispose();
            }
        }
    }
}