示例#1
0
        [CommandHipc(8)] // 9.0.0+
        // ParseTimeZoneBinary(buffer<nn::time::TimeZoneBinary, 0x21> timeZoneBinary) -> buffer<nn::time::TimeZoneRule, 0x16>
        public ResultCode ParseTimeZoneBinary(ServiceCtx context)
        {
            (ulong bufferPosition, ulong bufferSize) = context.Request.GetBufferType0x21();

            ulong timeZoneRuleBufferPosition = context.Request.ReceiveBuff[0].Position;
            ulong timeZoneRuleBufferSize     = context.Request.ReceiveBuff[0].Size;

            if (timeZoneRuleBufferSize != 0x4000)
            {
                // TODO: find error code here
                Logger.Error?.Print(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{timeZoneRuleBufferSize:x} (expected 0x4000)");

                throw new InvalidOperationException();
            }

            ResultCode result;

            byte[] temp = new byte[bufferSize];

            context.Memory.Read(bufferPosition, temp);

            using (MemoryStream timeZoneBinaryStream = new MemoryStream(temp))
            {
                using (WritableRegion region = context.Memory.GetWritableRegion(timeZoneRuleBufferPosition, Unsafe.SizeOf <TimeZoneRule>()))
                {
                    ref TimeZoneRule rule = ref MemoryMarshal.Cast <byte, TimeZoneRule>(region.Memory.Span)[0];

                    result = _timeZoneManager.ParseTimeZoneRuleBinary(ref rule, timeZoneBinaryStream);
                }
            }
示例#2
0
文件: IClient.cs 项目: mailwl/Ryujinx
        // Read(u32 fd) -> (i32 ret, u32 bsd_errno, buffer<i8, 0x22, 0> message)
        public ResultCode Read(ServiceCtx context)
        {
            int fd = context.RequestData.ReadInt32();

            (ulong receivePosition, ulong receiveLength) = context.Request.GetBufferType0x22();

            WritableRegion receiveRegion = context.Memory.GetWritableRegion(receivePosition, (int)receiveLength);

            LinuxError      errno  = LinuxError.EBADF;
            IFileDescriptor file   = _context.RetrieveFileDescriptor(fd);
            int             result = -1;

            if (file != null)
            {
                errno = file.Read(out result, receiveRegion.Memory.Span);

                if (errno == LinuxError.SUCCESS)
                {
                    SetResultErrno(file, result);

                    receiveRegion.Dispose();
                }
            }

            return(WriteBsdResult(context, result, errno));
        }
示例#3
0
文件: IClient.cs 项目: mailwl/Ryujinx
        // RecvFrom(u32 sock, u32 flags) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<i8, 0x22, 0> message, buffer<nn::socket::sockaddr_in, 0x22, 0x10>)
        public ResultCode RecvFrom(ServiceCtx context)
        {
            int            socketFd    = context.RequestData.ReadInt32();
            BsdSocketFlags socketFlags = (BsdSocketFlags)context.RequestData.ReadInt32();

            (ulong receivePosition, ulong receiveLength)       = context.Request.GetBufferType0x22(0);
            (ulong sockAddrOutPosition, ulong sockAddrOutSize) = context.Request.GetBufferType0x22(1);

            WritableRegion receiveRegion = context.Memory.GetWritableRegion(receivePosition, (int)receiveLength);

            LinuxError errno  = LinuxError.EBADF;
            ISocket    socket = _context.RetrieveSocket(socketFd);
            int        result = -1;

            if (socket != null)
            {
                errno = socket.ReceiveFrom(out result, receiveRegion.Memory.Span, receiveRegion.Memory.Span.Length, socketFlags, out IPEndPoint endPoint);

                if (errno == LinuxError.SUCCESS)
                {
                    SetResultErrno(socket, result);

                    receiveRegion.Dispose();

                    context.Memory.Write(sockAddrOutPosition, BsdSockAddr.FromIPEndPoint(endPoint));
                }
            }

            return(WriteBsdResult(context, result, errno));
        }
示例#4
0
        // DoHandshakeGetServerCert() -> (u32, u32, buffer<bytes, 6>)
        public ResultCode DoHandshakeGetServerCert(ServiceCtx context)
        {
            if (_connection == null)
            {
                return(ResultCode.NoSocket);
            }

            ResultCode result = _connection.Handshake(_hostName);

            if (result == ResultCode.Success)
            {
                if (_getServerCertChain)
                {
                    using (WritableRegion region = context.Memory.GetWritableRegion(context.Request.ReceiveBuff[0].Position, (int)context.Request.ReceiveBuff[0].Size))
                    {
                        result = _connection.GetServerCertificate(_hostName, region.Memory.Span, out uint bufferSize, out uint certificateCount);

                        context.ResponseData.Write(bufferSize);
                        context.ResponseData.Write(certificateCount);
                    }
                }
                else
                {
                    context.ResponseData.Write(0);
                    context.ResponseData.Write(0);
                }
            }

            return(result);
        }
示例#5
0
        private static int SerializeAddrInfos(ServiceCtx context, ulong responseBufferPosition, ulong responseBufferSize, IPHostEntry hostEntry, int port)
        {
            ulong originalBufferPosition = responseBufferPosition;
            ulong bufferPosition         = originalBufferPosition;

            byte[] hostName = Encoding.ASCII.GetBytes(hostEntry.HostName + '\0');

            using (WritableRegion region = context.Memory.GetWritableRegion(responseBufferPosition, (int)responseBufferSize))
            {
                Span <byte> data = region.Memory.Span;

                for (int i = 0; i < hostEntry.AddressList.Length; i++)
                {
                    IPAddress ip = hostEntry.AddressList[i];

                    if (ip.AddressFamily != AddressFamily.InterNetwork)
                    {
                        continue;
                    }

                    // NOTE: 0 = Any
                    AddrInfoSerializedHeader header = new AddrInfoSerializedHeader(ip, 0);
                    AddrInfo4          addr         = new AddrInfo4(ip, (short)port);
                    AddrInfoSerialized info         = new AddrInfoSerialized(header, addr, null, hostEntry.HostName);

                    data = info.Write(data);
                }

                uint sentinel = 0;
                MemoryMarshal.Write(data, ref sentinel);
                data = data[sizeof(uint)..];
示例#6
0
        [CommandHipc(9)] // 3.0.0+
        // GetReleasedAudioInBuffersAuto() -> (u32 count, buffer<u64, 0x22> tags)
        public ResultCode GetReleasedAudioInBuffersAuto(ServiceCtx context)
        {
            (long position, long size) = context.Request.GetBufferType0x22();

            using (WritableRegion outputRegion = context.Memory.GetWritableRegion((ulong)position, (int)size))
            {
                ResultCode result = _impl.GetReleasedBuffers(MemoryMarshal.Cast <byte, ulong>(outputRegion.Memory.Span), out uint releasedCount);

                context.ResponseData.Write(releasedCount);

                return(result);
            }
        }
示例#7
0
        // GetReleasedAudioOutBuffers() -> (u32 count, buffer<u64, 6> tags)
        public ResultCode GetReleasedAudioOutBuffers(ServiceCtx context)
        {
            long position = context.Request.ReceiveBuff[0].Position;
            long size     = context.Request.ReceiveBuff[0].Size;

            using (WritableRegion outputRegion = context.Memory.GetWritableRegion((ulong)position, (int)size))
            {
                ResultCode result = _impl.GetReleasedBuffers(MemoryMarshal.Cast <byte, ulong>(outputRegion.Memory.Span), out uint releasedCount);

                context.ResponseData.Write(releasedCount);

                return(result);
            }
        }
示例#8
0
        // GetCertificates(buffer<CaCertificateId, 5> ids) -> (u32 certificates_count, buffer<bytes, 6> certificates)
        public ResultCode GetCertificates(ServiceCtx context)
        {
            ReadOnlySpan <CaCertificateId> ids = MemoryMarshal.Cast <byte, CaCertificateId>(context.Memory.GetSpan(context.Request.SendBuff[0].Position, (int)context.Request.SendBuff[0].Size));

            if (!BuiltInCertificateManager.Instance.TryGetCertificates(ids, out BuiltInCertificateManager.CertStoreEntry[] entries))
            {
                throw new InvalidOperationException();
            }

            if (ComputeCertificateBufferSizeRequired(entries) > context.Request.ReceiveBuff[0].Size)
            {
                return(ResultCode.InvalidCertBufSize);
            }

            using (WritableRegion region = context.Memory.GetWritableRegion(context.Request.ReceiveBuff[0].Position, (int)context.Request.ReceiveBuff[0].Size))
            {
                Span <byte> rawData = region.Memory.Span;
                Span <BuiltInCertificateInfo> infos = MemoryMarshal.Cast <byte, BuiltInCertificateInfo>(rawData)[..entries.Length];
示例#9
0
        // Write(buffer<bytes, 5>) -> s32
        public ResultCode Write(ServiceCtx context)
        {
            if (_connection == null)
            {
                return(ResultCode.NoSocket);
            }

            // We don't dispose as this isn't supposed to be modified
            WritableRegion region = context.Memory.GetWritableRegion(context.Request.SendBuff[0].Position, (int)context.Request.SendBuff[0].Size);

            // TODO: Better error management.
            ResultCode result = _connection.Write(out int writtenCount, region.Memory);

            if (result == ResultCode.Success)
            {
                context.ResponseData.Write(writtenCount);
            }

            return(result);
        }
示例#10
0
        // LoadTimeZoneRule(nn::time::LocationName locationName) -> buffer<nn::time::TimeZoneRule, 0x16>
        public ResultCode LoadTimeZoneRule(ServiceCtx context)
        {
            ulong bufferPosition = context.Request.ReceiveBuff[0].Position;
            ulong bufferSize     = context.Request.ReceiveBuff[0].Size;

            if (bufferSize != 0x4000)
            {
                // TODO: find error code here
                Logger.Error?.Print(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{bufferSize:x} (expected 0x4000)");

                throw new InvalidOperationException();
            }

            string locationName = StringUtils.ReadInlinedAsciiString(context.RequestData, 0x24);

            using (WritableRegion region = context.Memory.GetWritableRegion(bufferPosition, Unsafe.SizeOf <TimeZoneRule>()))
            {
                ref TimeZoneRule rules = ref MemoryMarshal.Cast <byte, TimeZoneRule>(region.Memory.Span)[0];

                return(_timeZoneContentManager.LoadTimeZoneRule(ref rules, locationName));
            }
示例#11
0
        // Peek() -> (s32, buffer<bytes, 6>)
        public ResultCode Peek(ServiceCtx context)
        {
            if (_connection == null)
            {
                return(ResultCode.NoSocket);
            }

            ResultCode result;

            using (WritableRegion region = context.Memory.GetWritableRegion(context.Request.ReceiveBuff[0].Position, (int)context.Request.ReceiveBuff[0].Size))
            {
                // TODO: Better error management.
                result = _connection.Peek(out int peekCount, region.Memory);

                if (result == ResultCode.Success)
                {
                    context.ResponseData.Write(peekCount);
                }
            }

            return(result);
        }
示例#12
0
文件: IClient.cs 项目: mailwl/Ryujinx
        // GetSockOpt(u32 socket, u32 level, u32 option_name) -> (i32 ret, u32 bsd_errno, u32, buffer<unknown, 0x22, 0>)
        public ResultCode GetSockOpt(ServiceCtx context)
        {
            int socketFd             = context.RequestData.ReadInt32();
            SocketOptionLevel level  = (SocketOptionLevel)context.RequestData.ReadInt32();
            BsdSocketOption   option = (BsdSocketOption)context.RequestData.ReadInt32();

            (ulong bufferPosition, ulong bufferSize) = context.Request.GetBufferType0x22();
            WritableRegion optionValue = context.Memory.GetWritableRegion(bufferPosition, (int)bufferSize);

            LinuxError errno  = LinuxError.EBADF;
            ISocket    socket = _context.RetrieveSocket(socketFd);

            if (socket != null)
            {
                errno = socket.GetSocketOption(option, level, optionValue.Memory.Span);

                if (errno == LinuxError.SUCCESS)
                {
                    optionValue.Dispose();
                }
            }

            return(WriteBsdResult(context, 0, errno));
        }
示例#13
0
        public ResultCode Initialize(ref AudioRendererConfiguration parameter, uint processHandle, CpuAddress workBuffer, ulong workBufferSize, int sessionId, ulong appletResourceId, IVirtualMemoryManager memoryManager)
        {
            if (!BehaviourContext.CheckValidRevision(parameter.Revision))
            {
                return(ResultCode.OperationFailed);
            }

            if (GetWorkBufferSize(ref parameter) > workBufferSize)
            {
                return(ResultCode.WorkBufferTooSmall);
            }

            Debug.Assert(parameter.RenderingDevice == AudioRendererRenderingDevice.Dsp && parameter.ExecutionMode == AudioRendererExecutionMode.Auto);

            Logger.Info?.Print(LogClass.AudioRenderer, $"Initializing with REV{BehaviourContext.GetRevisionNumber(parameter.Revision)}");

            _behaviourContext.SetUserRevision(parameter.Revision);

            _sampleRate           = parameter.SampleRate;
            _sampleCount          = parameter.SampleCount;
            _mixBufferCount       = parameter.MixBufferCount;
            _voiceChannelCountMax = Constants.VoiceChannelCountMax;
            _upsamplerCount       = parameter.SinkCount + parameter.SubMixBufferCount;
            _appletResourceId     = appletResourceId;
            _memoryPoolCount      = parameter.EffectCount + parameter.VoiceCount * Constants.VoiceWaveBufferCount;
            _executionMode        = parameter.ExecutionMode;
            _sessionId            = sessionId;
            MemoryManager         = memoryManager;

            if (memoryManager is IRefCounted rc)
            {
                rc.IncrementReferenceCount();
            }

            WorkBufferAllocator workBufferAllocator;

            _workBufferRegion = MemoryManager.GetWritableRegion(workBuffer, (int)workBufferSize);
            _workBufferRegion.Memory.Span.Fill(0);
            _workBufferMemoryPin = _workBufferRegion.Memory.Pin();

            workBufferAllocator = new WorkBufferAllocator(_workBufferRegion.Memory);

            PoolMapper poolMapper = new PoolMapper(processHandle, false);

            poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize);

            _mixBuffer = workBufferAllocator.Allocate <float>(_sampleCount * (_voiceChannelCountMax + _mixBufferCount), 0x10);

            if (_mixBuffer.IsEmpty)
            {
                return(ResultCode.WorkBufferTooSmall);
            }

            Memory <float> upSamplerWorkBuffer = workBufferAllocator.Allocate <float>(Constants.TargetSampleCount * (_voiceChannelCountMax + _mixBufferCount) * _upsamplerCount, 0x10);

            if (upSamplerWorkBuffer.IsEmpty)
            {
                return(ResultCode.WorkBufferTooSmall);
            }

            _depopBuffer = workBufferAllocator.Allocate <float>((ulong)BitUtils.AlignUp(parameter.MixBufferCount, Constants.BufferAlignment), Constants.BufferAlignment);

            if (_depopBuffer.IsEmpty)
            {
                return(ResultCode.WorkBufferTooSmall);
            }

            // Invalidate DSP cache on what was currently allocated with workBuffer.
            AudioProcessorMemoryManager.InvalidateDspCache(_dspMemoryPoolState.Translate(workBuffer, workBufferAllocator.Offset), workBufferAllocator.Offset);

            Debug.Assert((workBufferAllocator.Offset % Constants.BufferAlignment) == 0);

            Memory <VoiceState> voices = workBufferAllocator.Allocate <VoiceState>(parameter.VoiceCount, VoiceState.Alignment);

            if (voices.IsEmpty)
            {
                return(ResultCode.WorkBufferTooSmall);
            }

            foreach (ref VoiceState voice in voices.Span)
            {
                voice.Initialize();
            }

            // A pain to handle as we can't have VoiceState*, use indices to be a bit more safe
            Memory <int> sortedVoices = workBufferAllocator.Allocate <int>(parameter.VoiceCount, 0x10);

            if (sortedVoices.IsEmpty)
            {
                return(ResultCode.WorkBufferTooSmall);
            }

            // Clear memory (use -1 as it's an invalid index)
            sortedVoices.Span.Fill(-1);

            Memory <VoiceChannelResource> voiceChannelResources = workBufferAllocator.Allocate <VoiceChannelResource>(parameter.VoiceCount, VoiceChannelResource.Alignment);

            if (voiceChannelResources.IsEmpty)
            {
                return(ResultCode.WorkBufferTooSmall);
            }

            for (uint id = 0; id < voiceChannelResources.Length; id++)
            {
                ref VoiceChannelResource voiceChannelResource = ref voiceChannelResources.Span[(int)id];

                voiceChannelResource.Id     = id;
                voiceChannelResource.IsUsed = false;
            }
示例#14
0
        /// <summary>
        /// Performs a full data copy between two textures, reading and writing guest memory directly.
        /// The textures must have a matching layout, size, and bytes per pixel.
        /// </summary>
        /// <param name="src">The source texture</param>
        /// <param name="dst">The destination texture</param>
        /// <param name="w">Copy width</param>
        /// <param name="h">Copy height</param>
        /// <param name="bpp">Bytes per pixel</param>
        private void UnscaledFullCopy(TwodTexture src, TwodTexture dst, int w, int h, int bpp)
        {
            var srcCalculator = new OffsetCalculator(
                w,
                h,
                src.Stride,
                src.LinearLayout,
                src.MemoryLayout.UnpackGobBlocksInY(),
                src.MemoryLayout.UnpackGobBlocksInZ(),
                bpp);

            (int _, int srcSize) = srcCalculator.GetRectangleRange(0, 0, w, h);

            var memoryManager = _channel.MemoryManager;

            ulong srcGpuVa = src.Address.Pack();
            ulong dstGpuVa = dst.Address.Pack();

            ReadOnlySpan <byte> srcSpan = memoryManager.GetSpan(srcGpuVa, srcSize, true);

            int width;
            int height = src.Height;

            if (src.LinearLayout)
            {
                width = src.Stride / bpp;
            }
            else
            {
                width = src.Width;
            }

            // If the copy is not equal to the width and height of the texture, we will need to copy partially.
            // It's worth noting that it has already been established that the src and dst are the same size.

            if (w == width && h == height)
            {
                memoryManager.Write(dstGpuVa, srcSpan);
            }
            else
            {
                using WritableRegion dstRegion = memoryManager.GetWritableRegion(dstGpuVa, srcSize, true);
                Span <byte> dstSpan = dstRegion.Memory.Span;

                if (src.LinearLayout)
                {
                    int stride   = src.Stride;
                    int offset   = 0;
                    int lineSize = width * bpp;

                    for (int y = 0; y < height; y++)
                    {
                        srcSpan.Slice(offset, lineSize).CopyTo(dstSpan.Slice(offset));

                        offset += stride;
                    }
                }
                else
                {
                    // Copy with the block linear layout in mind.
                    // Recreate the offset calculate with bpp 1 for copy.

                    int stride = w * bpp;

                    srcCalculator = new OffsetCalculator(
                        stride,
                        h,
                        0,
                        false,
                        src.MemoryLayout.UnpackGobBlocksInY(),
                        src.MemoryLayout.UnpackGobBlocksInZ(),
                        1);

                    int strideTrunc = BitUtils.AlignDown(stride, 16);

                    ReadOnlySpan <Vector128 <byte> > srcVec = MemoryMarshal.Cast <byte, Vector128 <byte> >(srcSpan);
                    Span <Vector128 <byte> >         dstVec = MemoryMarshal.Cast <byte, Vector128 <byte> >(dstSpan);

                    for (int y = 0; y < h; y++)
                    {
                        int x = 0;

                        srcCalculator.SetY(y);

                        for (; x < strideTrunc; x += 16)
                        {
                            int offset = srcCalculator.GetOffset(x) >> 4;

                            dstVec[offset] = srcVec[offset];
                        }

                        for (; x < stride; x++)
                        {
                            int offset = srcCalculator.GetOffset(x);

                            dstSpan[offset] = srcSpan[offset];
                        }
                    }
                }
            }
        }