| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- using Ryujinx.Common.Logging;
- using Ryujinx.HLE.Utilities;
- using System;
- using System.Buffers.Binary;
- using System.IO;
- using System.Text;
- namespace Ryujinx.HLE.HOS.Services.Prepo
- {
- [Service("prepo:a")]
- [Service("prepo:a2")]
- [Service("prepo:u")]
- class IPrepoService : IpcService
- {
- public IPrepoService(ServiceCtx context) { }
- [Command(10100)] // 1.0.0-5.1.0
- // SaveReport(u64, pid, buffer<u8, 9>, buffer<bytes, 5>)
- public ResultCode SaveReportOld(ServiceCtx context)
- {
- // We don't care about the differences since we don't use the play report.
- return ProcessReport(context, withUserID: false);
- }
- [Command(10101)] // 1.0.0-5.1.0
- // SaveReportWithUserOld(nn::account::Uid, u64, pid, buffer<u8, 9>, buffer<bytes, 5>)
- public ResultCode SaveReportWithUserOld(ServiceCtx context)
- {
- // We don't care about the differences since we don't use the play report.
- return ProcessReport(context, withUserID: true);
- }
- [Command(10102)] // 6.0.0+
- // SaveReport(u64, pid, buffer<u8, 9>, buffer<bytes, 5>)
- public ResultCode SaveReport(ServiceCtx context)
- {
- // We don't care about the differences since we don't use the play report.
- return ProcessReport(context, withUserID: false);
- }
- [Command(10103)] // 6.0.0+
- // SaveReportWithUser(nn::account::Uid, u64, pid, buffer<u8, 9>, buffer<bytes, 5>)
- public ResultCode SaveReportWithUser(ServiceCtx context)
- {
- // We don't care about the differences since we don't use the play report.
- return ProcessReport(context, withUserID: true);
- }
- private ResultCode ProcessReport(ServiceCtx context, bool withUserID)
- {
- UInt128 userId = withUserID ? new UInt128(context.RequestData.ReadBytes(0x10)) : new UInt128();
- string gameRoom = StringUtils.ReadUtf8String(context);
- if (withUserID)
- {
- if (userId.IsNull)
- {
- return ResultCode.InvalidArgument;
- }
- }
- if (gameRoom == string.Empty)
- {
- return ResultCode.InvalidState;
- }
- long inputPosition = context.Request.SendBuff[0].Position;
- long inputSize = context.Request.SendBuff[0].Size;
- if (inputSize == 0)
- {
- return ResultCode.InvalidBufferSize;
- }
- byte[] inputBuffer = context.Memory.ReadBytes(inputPosition, inputSize);
- Logger.PrintInfo(LogClass.ServicePrepo, ReadReportBuffer(inputBuffer, gameRoom, userId));
- return ResultCode.Success;
- }
- public string ReadReportBuffer(byte[] buffer, string room, UInt128 userId)
- {
- StringBuilder sb = new StringBuilder();
- sb.AppendLine();
- sb.AppendLine("PlayReport log:");
- if (!userId.IsNull)
- {
- sb.AppendLine($" UserId: {userId.ToString()}");
- }
- sb.AppendLine($" Room: {room}");
- try
- {
- using (MemoryStream stream = new MemoryStream(buffer))
- using (BinaryReader reader = new BinaryReader(stream))
- {
- byte unknown1 = reader.ReadByte(); // Version ?
- short unknown2 = reader.ReadInt16(); // Size ?
- bool isValue = false;
- string fieldStr = string.Empty;
- while (stream.Position != stream.Length)
- {
- byte descriptor = reader.ReadByte();
- if (!isValue)
- {
- byte[] key = reader.ReadBytes(descriptor - 0xA0);
- fieldStr = $" Key: {Encoding.ASCII.GetString(key)}";
- isValue = true;
- }
- else
- {
- if (descriptor > 0xD0) // Int value.
- {
- if (descriptor - 0xD0 == 1)
- {
- fieldStr += $", Value: {BinaryPrimitives.ReverseEndianness(reader.ReadUInt16())}";
- }
- else if (descriptor - 0xD0 == 2)
- {
- fieldStr += $", Value: {BinaryPrimitives.ReverseEndianness(reader.ReadInt32())}";
- }
- else if (descriptor - 0xD0 == 4)
- {
- fieldStr += $", Value: {BinaryPrimitives.ReverseEndianness(reader.ReadInt64())}";
- }
- else
- {
- // Unknown.
- break;
- }
- }
- else if (descriptor > 0xA0 && descriptor < 0xD0) // String value, max size = 0x20 bytes ?
- {
- int size = descriptor - 0xA0;
- string value = string.Empty;
- byte[] rawValues = new byte[0];
- for (int i = 0; i < size; i++)
- {
- byte chr = reader.ReadByte();
- if (chr >= 0x20 && chr < 0x7f)
- {
- value += (char)chr;
- }
- else
- {
- Array.Resize(ref rawValues, rawValues.Length + 1);
- rawValues[rawValues.Length - 1] = chr;
- }
- }
- if (value != string.Empty)
- {
- fieldStr += $", Value: {value}";
- }
- // TODO(Ac_K): Determine why there are non-alphanumeric values sometimes.
- if (rawValues.Length > 0)
- {
- fieldStr += $", RawValue: 0x{BitConverter.ToString(rawValues).Replace("-", "")}";
- }
- }
- else // Byte value.
- {
- fieldStr += $", Value: {descriptor}";
- }
- sb.AppendLine(fieldStr);
- isValue = false;
- }
- }
- }
- }
- catch (Exception)
- {
- sb.AppendLine(" Error while parsing the report buffer.");
- }
- return sb.ToString();
- }
- }
- }
|