예제 #1
0
    private void ReadEncrypted(GameBoxReader r)
    {
        var headerMD5 = r.ReadBytes(16);

        MetadataStart = r.ReadInt32(); // offset to metadata section
        DataStart     = r.ReadInt32();

        if (Version >= 2)
        {
            var gbxHeadersSize      = r.ReadInt32();
            var gbxHeadersComprSize = r.ReadInt32();
        }

        if (Version >= 3)
        {
            r.ReadBytes(16); // unused
        }
        var flags = r.ReadInt32();

        var folders = ReadFolders(r);

        ReadFiles(r, folders);

        ReadMetadata();
    }
예제 #2
0
        public override void Read(CGameCtnReplayRecord n, GameBoxReader r)
        {
            var size = r.ReadInt32();

            if (size <= 0)
            {
                throw new Exception();
            }

            var trackGbx = r.ReadBytes(size);

            n.challenge = Task.Run(() =>
            {
                using var ms = new MemoryStream(trackGbx);
                return(GameBox.ParseNode <CGameCtnChallenge>(ms));
            });

#if DEBUG
            n.challenge.ContinueWith(x =>
            {
                if (!x.IsFaulted)
                {
                    return;
                }

                var e = x.Exception?.InnerException;
                Debug.WriteLine(e?.Message);
                Debug.WriteLine(e?.StackTrace);
            });
#endif
        }
예제 #3
0
            public override void Read(CGameCtnReplayRecord n, GameBoxReader r, GameBoxWriter unknownW)
            {
                var size = r.ReadInt32();

                if (size > 0)
                {
                    var trackGbx = r.ReadBytes(size);

                    n.Challenge = Task.Run(() =>
                    {
                        using (var ms = new MemoryStream(trackGbx))
                            return(GameBox.Parse <CGameCtnChallenge>(ms));
                    });

                    n.Challenge.ContinueWith(x =>
                    {
#if DEBUG
                        if (x.IsFaulted)
                        {
                            var e = x.Exception.InnerException;
                            Debug.WriteLine(e.Message);
                            Debug.WriteLine(e.StackTrace);
                        }
#endif
                    });
                }
            }
예제 #4
0
    /// <exception cref="TextFormatNotSupportedException">Text-formatted GBX files are not supported.</exception>
    internal bool Read(GameBoxReader reader)
    {
        if (!reader.HasMagic(GameBox.Magic))
        {
            Log.Write("GBX magic missing! Corrupted file or not a GBX file.", ConsoleColor.Red);
            return(false);
        }

        Log.Write("GBX recognized!", ConsoleColor.Green);

        Version = reader.ReadInt16();
        Log.Write("- Version: " + Version.ToString());

        if (Version >= 3)
        {
            ByteFormat = (GameBoxByteFormat)reader.ReadByte();
            Log.Write("- Byte format: " + ByteFormat.ToString());

            if (ByteFormat == GameBoxByteFormat.Text)
            {
                throw new TextFormatNotSupportedException();
            }

            CompressionOfRefTable = (GameBoxCompression)reader.ReadByte();
            Log.Write("- Ref. table compression: " + CompressionOfRefTable.ToString());

            CompressionOfBody = (GameBoxCompression)reader.ReadByte();
            Log.Write("- Body compression: " + CompressionOfBody.ToString());

            if (Version >= 4)
            {
                UnknownByte = (char)reader.ReadByte();
                Log.Write("- Unknown byte: " + UnknownByte.ToString());
            }

            ID = CMwNod.Remap(reader.ReadUInt32());
            Log.Write("- Class ID: 0x" + ID.Value.ToString("X8"));

            if (Version >= 6)
            {
                var userDataSize = reader.ReadInt32();
                Log.Write($"- User data size: {(userDataSize / 1024f).ToString()} kB");

                if (userDataSize > 0)
                {
                    UserData = reader.ReadBytes(userDataSize);
                }
            }

            NumNodes = reader.ReadInt32();
            Log.Write("- Number of nodes: " + NumNodes.ToString());
        }

        Log.Write("Header completed!", ConsoleColor.Green);

        return(true);
    }
예제 #5
0
    public static NadeoPakList Parse(Stream stream)
    {
        using var r = new GameBoxReader(stream);

        var version  = r.ReadByte();
        var numPacks = r.ReadByte();
        var crc32    = r.ReadUInt32();
        var salt     = r.ReadUInt32();

        var nameKey = ComputeMD5("6611992868945B0B59536FC3226F3FD0" + salt);

        var packs = new NadeoPakListItem[numPacks];

        for (var i = 0; i < numPacks; i++)
        {
            var flags              = r.ReadByte();
            var nameLength         = r.ReadByte();
            var encryptedName      = r.ReadBytes(nameLength);
            var encryptedKeyString = r.ReadBytes(32);

            for (var j = 0; j < encryptedName.Length; j++)
            {
                encryptedName[j] ^= nameKey[j % nameKey.Length];
            }

            var name = Encoding.ASCII.GetString(encryptedName);

            var keyStringKey = ComputeMD5(name + salt + "B97C1205648A66E04F86A1B5D5AF9862");

            for (var j = 0; j < encryptedKeyString.Length; j++)
            {
                encryptedKeyString[j] ^= keyStringKey[j % keyStringKey.Length];
            }

            var key = ComputeMD5(Encoding.ASCII.GetString(encryptedKeyString) + "NadeoPak");

            packs[i] = new NadeoPakListItem(name, flags, key);
        }

        var signature = r.ReadBytes(0x10);

        return(new NadeoPakList(version, crc32, salt, packs, signature));
    }
예제 #6
0
    public byte[]? GetData()
    {
        if (data is not null)
        {
            return(data);
        }

        owner.Stream.Position = owner.DataStart + Offset;

        var roundedDataSize = 8 + CompressedSize;

        if ((roundedDataSize & 7) != 0)
        {
            roundedDataSize = (roundedDataSize & ~7) + 8;
        }

        var buffer = new byte[roundedDataSize];

        owner.Stream.Read(buffer, 0, buffer.Length);

        using var ms = new MemoryStream(buffer);
        using var r  = new GameBoxReader(ms);

        var iv = r.ReadUInt64();

        using var blowfish = new BlowfishCBCStream(ms, owner.Key, iv);

        if (IsCompressed)
        {
            using var deflate = new CompressedStream(blowfish, CompressionMode.Decompress);
            using var rr      = new GameBoxReader(deflate);

            try
            {
                data = rr.ReadBytes(UncompressedSize); // CopyTo nefunguje xd
            }
            catch (InvalidDataException)
            {
            }
        }
        else
        {
            using var rr = new GameBoxReader(blowfish);
            data         = rr.ReadBytes(UncompressedSize); // CopyTo nefunguje xd
        }

        return(data);
    }
예제 #7
0
 public override void Read(CGameCtnCollection n, GameBoxReader r, GameBoxWriter unknownW)
 {
     Version        = r.ReadByte();
     n.CollectionID = r.ReadByte();
     _ = r.ReadBytes(6);
     n.CollectionPackMask = r.ReadByte();
     n.DisplayName        = r.ReadString();
     _ = r.ReadInt32();
     n.CollectionIcon = r.ReadString();
     _ = r.ReadArray <int>(2);
     n.BlockInfoFlat = r.ReadId(this);
     n.Vehicle       = r.ReadIdent(this);
     _ = r.ReadInt32();
     _ = r.ReadArray <float>(4);
     n.LoadingScreen = r.ReadString();
     _ = r.ReadArray <int>(7);
     _ = r.ReadString();
     _ = r.ReadInt32();
 }
예제 #8
0
    internal static void Parse <T>(T node, GameBoxReader r, IProgress <GameBoxReadProgress>?progress = null) where T : CMwNod
    {
        var stopwatch = Stopwatch.StartNew();

        node.GBX = r.Body?.GBX;

        var type = node.GetType();

        uint?previousChunkId = null;

        while (!r.BaseStream.CanSeek || r.BaseStream.Position < r.BaseStream.Length)
        {
            if (r.BaseStream.CanSeek && r.BaseStream.Position + 4 > r.BaseStream.Length)
            {
                Debug.WriteLine($"Unexpected end of the stream: {r.BaseStream.Position.ToString()}/{r.BaseStream.Length.ToString()}");
                var bytes = r.ReadBytes((int)(r.BaseStream.Length - r.BaseStream.Position));
                break;
            }

            var chunkId = r.ReadUInt32();

            if (chunkId == 0xFACADE01) // no more chunks
            {
                break;
            }

            var logChunk = new StringBuilder("[")
                           .Append(node.ClassName)
                           .Append("] 0x")
                           .Append(chunkId.ToString("X8"));

            if (r.BaseStream.CanSeek) // Decompressed body can always seek
            {
                logChunk.Append(" (")
                .Append(((float)r.BaseStream.Position / r.BaseStream.Length).ToString("0.00%"))
                .Append(')');
            }

            if (node.GBX is null || !node.GBX.ID.HasValue || Remap(node.GBX.ID.Value) != node.ID)
            {
                logChunk.Insert(0, "~ ");
            }

            Log.Write(logChunk.ToString());

            Chunk chunk;

            chunkId = Chunk.Remap(chunkId);

            var reflected = NodeCacheManager.AvailableChunkClasses[type].TryGetValue(chunkId, out Type? chunkClass);

            if (reflected && chunkClass is null)
            {
                throw new ThisShouldNotHappenException();
            }

            var skippable = reflected && chunkClass !.BaseType !.GetGenericTypeDefinition() == typeof(SkippableChunk <>);

            // Unknown or skippable chunk
            if (!reflected || skippable)
            {
                var skip = r.ReadUInt32();

                if (skip != 0x534B4950)
                {
                    if (reflected)
                    {
                        break;
                    }

                    var logChunkError = $"[{node.ClassName}] 0x{chunkId.ToString("X8")} ERROR (wrong chunk format or unknown unskippable chunk)";
                    if (node.GBX is not null && node.GBX.ID.HasValue && Remap(node.GBX.ID.Value) == node.ID)
                    {
                        Log.Write(logChunkError, ConsoleColor.Red);
                    }
                    else
                    {
                        Log.Write("~ " + logChunkError, ConsoleColor.Red);
                    }

#if DEBUG
                    // Read the rest of the body

                    var streamPos          = r.BaseStream.Position;
                    var uncontrollableData = r.ReadToEnd();
                    r.BaseStream.Position = streamPos;
#endif

                    throw new ChunkParseException(chunkId, previousChunkId);

                    /* Usually breaks in the current state and causes confusion
                     *
                     * var buffer = BitConverter.GetBytes(chunkID);
                     * using (var restMs = new MemoryStream(ushort.MaxValue))
                     * {
                     *  restMs.Write(buffer, 0, buffer.Length);
                     *
                     *  while (r.PeekUInt32() != 0xFACADE01)
                     *      restMs.WriteByte(r.ReadByte());
                     *
                     *  node.Rest = restMs.ToArray();
                     * }
                     * Debug.WriteLine("FACADE found.");*/
                }

                var chunkDataSize = r.ReadInt32();
                var chunkData     = new byte[chunkDataSize];
                if (chunkDataSize > 0)
                {
                    r.Read(chunkData, 0, chunkDataSize);
                }

                if (reflected)
                {
                    var attributesAvailable = NodeCacheManager.AvailableChunkAttributes[type].TryGetValue(
                        chunkId, out IEnumerable <Attribute>?attributes);

                    if (!attributesAvailable)
                    {
                        throw new ThisShouldNotHappenException();
                    }

                    if (attributes is null)
                    {
                        throw new ThisShouldNotHappenException();
                    }

                    var ignoreChunkAttribute = default(IgnoreChunkAttribute);
                    var chunkAttribute       = default(ChunkAttribute);

                    foreach (var att in attributes)
                    {
                        if (att is IgnoreChunkAttribute ignoreChunkAtt)
                        {
                            ignoreChunkAttribute = ignoreChunkAtt;
                        }
                        if (att is ChunkAttribute chunkAtt)
                        {
                            chunkAttribute = chunkAtt;
                        }
                    }

                    if (chunkAttribute is null)
                    {
                        throw new ThisShouldNotHappenException();
                    }

                    NodeCacheManager.AvailableChunkConstructors[type].TryGetValue(chunkId,
                                                                                  out Func <Chunk>?constructor);

                    if (constructor is null)
                    {
                        throw new ThisShouldNotHappenException();
                    }

                    var c = constructor();
                    c.Node = node;
                    ((ISkippableChunk)c).Data = chunkData;
                    if (chunkData == null || chunkData.Length == 0)
                    {
                        ((ISkippableChunk)c).Discovered = true;
                    }
                    node.Chunks.Add(c);

#if DEBUG
                    c.Debugger.RawData = chunkData;
#endif

                    if (ignoreChunkAttribute == null)
                    {
                        c.OnLoad();

                        if (chunkAttribute.ProcessSync)
                        {
                            ((ISkippableChunk)c).Discover();
                        }
                    }

                    chunk = c;
                }
                else
                {
                    Debug.WriteLine("Unknown skippable chunk: " + chunkId.ToString("X"));
                    chunk = (Chunk)Activator.CreateInstance(typeof(SkippableChunk <>).MakeGenericType(type), node, chunkId, chunkData) !;
#if DEBUG
                    chunk.Debugger.RawData = chunkData;
#endif
                    node.Chunks.Add(chunk);
                }
            }
예제 #9
0
            public override void Read(CPlugEntRecordData n, GameBoxReader r)
            {
                Version          = r.ReadInt32();
                UncompressedSize = r.ReadInt32();
                CompressedSize   = r.ReadInt32();
                Data             = r.ReadBytes(CompressedSize);

                n.Samples = Task.Run(() =>
                {
                    var samples = new ObservableCollection <Sample>();

                    using (var ms = new MemoryStream(Data))
                        using (var cs = new CompressedStream(ms, CompressionMode.Decompress))
                            using (var gbxr = new GameBoxReader(cs))
                            {
                                var u01         = gbxr.ReadInt32();
                                var ghostLength = gbxr.ReadInt32(); // milliseconds
                                var objects     = gbxr.ReadArray <object>(r1 =>
                                {
                                    var nodeId = r1.ReadUInt32();
                                    NodeCacheManager.Names.TryGetValue(nodeId, out string nodeName);

                                    return(new
                                    {
                                        nodeId,
                                        nodeName,
                                        obj_u01 = r1.ReadInt32(),
                                        obj_u02 = r1.ReadInt32(),
                                        obj_u03 = r1.ReadInt32(),
                                        mwbuffer = r1.ReadInt32(),
                                        obj_u05 = r1.ReadInt32()
                                    });
                                });

                                if (Version >= 2)
                                {
                                    var objcts2 = gbxr.ReadArray <object>(r1 =>
                                    {
                                        var u02 = r1.ReadInt32();
                                        var u03 = r1.ReadInt32();

                                        uint?clas       = null;
                                        string clasName = null;
                                        if (Version >= 4)
                                        {
                                            clas = r1.ReadUInt32();
                                            NodeCacheManager.Names.TryGetValue(clas.Value, out clasName);
                                        }

                                        return(new
                                        {
                                            u02,
                                            u03,
                                            clas,
                                            clasName
                                        });
                                    });
                                }

                                var u04 = gbxr.ReadByte();
                                while (u04 != 0)
                                {
                                    var bufferType        = gbxr.ReadInt32();
                                    var u06               = gbxr.ReadInt32();
                                    var u07               = gbxr.ReadInt32();
                                    var ghostLengthFinish = gbxr.ReadInt32(); // ms

                                    if (Version < 6)
                                    {
                                        // temp_79f24995b2b->field_0x28 = temp_79f24995b2b->field_0xc
                                    }
                                    else
                                    {
                                        var u08 = gbxr.ReadInt32();
                                    }

                                    // Reads byte on every loop until the byte is 0, should be 1 otherwise
                                    for (byte x; (x = gbxr.ReadByte()) != 0;)
                                    {
                                        var timestamp = gbxr.ReadInt32();
                                        var buffer    = gbxr.ReadBytes(); // MwBuffer

                                        if (buffer.Length > 0)
                                        {
                                            var unknownData = new byte[buffer.Length];

                                            using (var bufMs = new MemoryStream(buffer))
                                                using (var bufR = new GameBoxReader(bufMs))
                                                {
                                                    var sampleProgress = (int)bufMs.Position;

                                                    Sample sample = new Sample()
                                                    {
                                                        BufferType = (byte)bufferType
                                                    };

                                                    switch (bufferType)
                                                    {
                                                    case 0:
                                                        break;

                                                    case 2:
                                                        var buf2unknownData = bufR.ReadBytes(5);
                                                        Buffer.BlockCopy(buf2unknownData, 0, unknownData, 0, buf2unknownData.Length);

                                                        var(position, rotation, speed, velocity) = bufR.ReadTransform(); // Only position matches

                                                        sample.Timestamp = TimeSpan.FromMilliseconds(timestamp);
                                                        sample.Position  = position;
                                                        sample.Rotation  = rotation;
                                                        sample.Speed     = speed * 3.6f;
                                                        sample.Velocity  = velocity;

                                                        break;

                                                    case 4:
                                                        var buf4unknownData = bufR.ReadBytes(47);
                                                        Buffer.BlockCopy(buf4unknownData, 0, unknownData, 0, buf4unknownData.Length);

                                                        var buf4transform = bufR.ReadTransform();

                                                        var buf4unknownData2 = bufR.ReadBytes(4);

                                                        sample.Timestamp = TimeSpan.FromMilliseconds(timestamp);
                                                        sample.Position  = buf4transform.position;
                                                        sample.Rotation  = buf4transform.rotation;
                                                        sample.Speed     = buf4transform.speed * 3.6f;
                                                        sample.Velocity  = buf4transform.velocity;
                                                        sample.Unknown   = buf4unknownData;

                                                        break;

                                                    case 10:
                                                        break;

                                                    default:
                                                        break;
                                                    }

                                                    sampleProgress = (int)(bufMs.Position - sampleProgress);

                                                    var moreUnknownData = bufR.ReadBytes((int)bufMs.Length - sampleProgress);
                                                    Buffer.BlockCopy(moreUnknownData, 0, unknownData, sampleProgress, moreUnknownData.Length);

                                                    sample.Unknown = unknownData;

                                                    samples.Add(sample);
                                                }
                                        }
                                    }

                                    u04 = gbxr.ReadByte();

                                    if (Version >= 2)
                                    {
                                        for (byte x; (x = gbxr.ReadByte()) != 0;)
                                        {
                                            var type      = gbxr.ReadInt32();
                                            var timestamp = gbxr.ReadInt32();
                                            var buffer    = gbxr.ReadBytes(); // MwBuffer
                                        }
                                    }
                                }

                                if (Version >= 3)
                                {
                                    for (byte x; (x = gbxr.ReadByte()) != 0;)
                                    {
                                        var u19 = gbxr.ReadInt32();
                                        var u20 = gbxr.ReadInt32();
                                        var u21 = gbxr.ReadBytes(); // MwBuffer
                                    }

                                    if (Version == 7)
                                    {
                                        for (byte x; (x = gbxr.ReadByte()) != 0;)
                                        {
                                            var u23 = gbxr.ReadInt32();
                                            var u24 = gbxr.ReadBytes(); // MwBuffer
                                        }
                                    }

                                    if (Version >= 8)
                                    {
                                        var u23 = gbxr.ReadInt32();

                                        if (u23 != 0)
                                        {
                                            if (Version == 8)
                                            {
                                                for (byte x; (x = gbxr.ReadByte()) != 0;)
                                                {
                                                    var u25 = gbxr.ReadInt32();
                                                    var u26 = gbxr.ReadBytes(); // MwBuffer
                                                }
                                            }
                                            else
                                            {
                                                for (byte x; (x = gbxr.ReadByte()) != 0;)
                                                {
                                                    var u28 = gbxr.ReadInt32();
                                                    var u29 = gbxr.ReadBytes(); // MwBuffer
                                                    var u30 = gbxr.ReadBytes(); // MwBuffer
                                                }

                                                if (Version >= 10)
                                                {
                                                    var period = gbxr.ReadInt32();
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                    return(samples);
                });
            }
예제 #10
0
        public static void Parse <T>(T node, GameBoxReader r, IProgress <GameBoxReadProgress> progress = null) where T : CMwNod
        {
            var stopwatch = Stopwatch.StartNew();

            node.GBX = r.GBX;

            var type = node.GetType();

            var chunks = new ChunkSet {
                Node = node
            };

            node.Chunks = chunks;

            uint?previousChunk = null;

            while (!r.BaseStream.CanSeek || r.BaseStream.Position < r.BaseStream.Length)
            {
                if (r.BaseStream.CanSeek && r.BaseStream.Position + 4 > r.BaseStream.Length)
                {
                    Debug.WriteLine($"Unexpected end of the stream: {r.BaseStream.Position}/{r.BaseStream.Length}");
                    var bytes = r.ReadBytes((int)(r.BaseStream.Length - r.BaseStream.Position));
                    break;
                }

                var chunkID = r.ReadUInt32();

                if (chunkID == 0xFACADE01) // no more chunks
                {
                    break;
                }
                else
                {
                    var logChunk = $"[{node.ClassName}] 0x{chunkID:X8}";
                    if (r.BaseStream.CanSeek)
                    {
                        logChunk += $" ({(float)r.BaseStream.Position / r.BaseStream.Length:0.00%})";
                    }

                    if (node.GBX?.ID.HasValue == true && Remap(node.GBX.ID.Value) == node.ID)
                    {
                        Log.Write(logChunk);
                    }
                    else
                    {
                        Log.Write($"~ {logChunk}");
                    }
                }

                Chunk chunk;

                var chunkRemapped = Chunk.Remap(chunkID);

                Type chunkClass = null;

                var reflected = ((chunkRemapped & 0xFFFFF000) == node.ID || NodeCacheManager.AvailableInheritanceClasses[type].Contains(chunkRemapped & 0xFFFFF000)) &&
                                (NodeCacheManager.AvailableChunkClasses[type].TryGetValue(chunkRemapped, out chunkClass) || NodeCacheManager.AvailableChunkClasses[type].TryGetValue(chunkID & 0xFFF, out chunkClass));

                var skippable = reflected && chunkClass.BaseType.GetGenericTypeDefinition() == typeof(SkippableChunk <>);

                // Unknown or skippable chunk
                if (!reflected || skippable)
                {
                    var skip = r.ReadUInt32();

                    if (skip != 0x534B4950)
                    {
                        if (chunkID != 0 && !reflected)
                        {
                            var logChunkError = $"[{node.ClassName}] 0x{chunkID:X8} ERROR (wrong chunk format or unknown unskippable chunk)";
                            if (node.GBX?.ID.HasValue == true && Remap(node.GBX.ID.Value) == node.ID)
                            {
                                Log.Write(logChunkError, ConsoleColor.Red);
                            }
                            else
                            {
                                Log.Write($"~ {logChunkError}", ConsoleColor.Red);
                            }

                            throw new Exception($"Wrong chunk format or unskippable chunk: 0x{chunkID:X8} (" +
                                                $"{NodeCacheManager.Names.Where(x => x.Key == Chunk.Remap(chunkID & 0xFFFFF000)).Select(x => x.Value).FirstOrDefault() ?? "unknown class"})" +
                                                $"\nPrevious chunk: 0x{previousChunk ?? 0:X8} (" +
                                                $"{(previousChunk.HasValue ? (NodeCacheManager.Names.Where(x => x.Key == Chunk.Remap(previousChunk.Value & 0xFFFFF000)).Select(x => x.Value).FirstOrDefault() ?? "unknown class") : "not a class")})");

                            /* Usually breaks in the current state and causes confusion
                             *
                             * var buffer = BitConverter.GetBytes(chunkID);
                             * using (var restMs = new MemoryStream(ushort.MaxValue))
                             * {
                             *  restMs.Write(buffer, 0, buffer.Length);
                             *
                             *  while (r.PeekUInt32() != 0xFACADE01)
                             *      restMs.WriteByte(r.ReadByte());
                             *
                             *  node.Rest = restMs.ToArray();
                             * }
                             * Debug.WriteLine("FACADE found.");*/
                        }
                        break;
                    }

                    var chunkDataSize = r.ReadInt32();
                    var chunkData     = new byte[chunkDataSize];
                    if (chunkDataSize > 0)
                    {
                        r.Read(chunkData, 0, chunkDataSize);
                    }

                    if (reflected)
                    {
                        var ignoreChunkAttribute = chunkClass.GetCustomAttribute <IgnoreChunkAttribute>();

                        var constructor = Array.Find(chunkClass.GetConstructors(), x => x.GetParameters().Length == 0);
                        if (constructor == null)
                        {
                            throw new ArgumentException($"{type.FullName} doesn't have a parameterless constructor.");
                        }

                        var c = (Chunk)constructor.Invoke(new object[0]);
                        c.Node = node;
                        c.GBX  = node.GBX;
                        ((ISkippableChunk)c).Data = chunkData;
                        if (chunkData == null || chunkData.Length == 0)
                        {
                            ((ISkippableChunk)c).Discovered = true;
                        }
                        chunks.Add(c);

                        if (ignoreChunkAttribute == null)
                        {
                            c.OnLoad();

                            if (chunkClass.GetCustomAttribute <ChunkAttribute>().ProcessSync)
                            {
                                ((ISkippableChunk)c).Discover();
                            }
                        }

                        chunk = c;
                    }
                    else
                    {
                        Debug.WriteLine("Unknown skippable chunk: " + chunkID.ToString("X"));
                        chunk     = (Chunk)Activator.CreateInstance(typeof(SkippableChunk <>).MakeGenericType(type), node, chunkRemapped, chunkData);
                        chunk.GBX = node.GBX;
                        chunks.Add(chunk);
                    }
                }
                else // Known or unskippable chunk
                {
                    var constructor = Array.Find(chunkClass.GetConstructors(), x => x.GetParameters().Length == 0);

                    if (constructor == null)
                    {
                        throw new ArgumentException($"{type.FullName} doesn't have a parameterless constructor.");
                    }

                    var c = (Chunk)constructor.Invoke(new object[0]);
                    c.Node = node;

                    c.OnLoad();

                    chunks.Add(c);

                    //r.Chunk = (Chunk)c; // Set chunk temporarily for reading

                    var posBefore = r.BaseStream.Position;

                    GameBoxReaderWriter gbxrw = new GameBoxReaderWriter(r);

                    var attributes                  = chunkClass.GetCustomAttributes();
                    var ignoreChunkAttribute        = default(IgnoreChunkAttribute);
                    var autoReadWriteChunkAttribute = default(AutoReadWriteChunkAttribute);

                    foreach (var att in attributes)
                    {
                        if (att is IgnoreChunkAttribute ignoreChunkAtt)
                        {
                            ignoreChunkAttribute = ignoreChunkAtt;
                        }
                        if (att is AutoReadWriteChunkAttribute autoReadWriteChunkAtt)
                        {
                            autoReadWriteChunkAttribute = autoReadWriteChunkAtt;
                        }
                    }

                    try
                    {
                        if (ignoreChunkAttribute == null)
                        {
                            if (autoReadWriteChunkAttribute == null)
                            {
                                c.ReadWrite(node, gbxrw);
                            }
                            else
                            {
                                var unknown     = new GameBoxWriter(c.Unknown, r.Lookbackable);
                                var unknownData = r.ReadUntilFacade();
                                unknown.Write(unknownData, 0, unknownData.Length);
                            }
                        }
                        else
                        {
                            throw new Exception($"Chunk 0x{chunkID & 0xFFF:x3} from class {node.ClassName} is known but its content is unknown to read.");
                        }
                    }
                    catch (EndOfStreamException)
                    {
                        Debug.WriteLine($"Unexpected end of the stream while reading the chunk.");
                    }

                    c.Progress = (int)(r.BaseStream.Position - posBefore);

                    chunk = c;
                }

                progress?.Report(new GameBoxReadProgress(GameBoxReadProgressStage.Body, (float)r.BaseStream.Position / r.BaseStream.Length, node.GBX, chunk));

                previousChunk = chunkID;
            }

            stopwatch.Stop();

            var logNodeCompletion = $"[{node.ClassName}] DONE! ({stopwatch.Elapsed.TotalMilliseconds}ms)";

            if (node.GBX.ID.HasValue == true && Remap(node.GBX.ID.Value) == node.ID)
            {
                Log.Write(logNodeCompletion, ConsoleColor.Green);
            }
            else
            {
                Log.Write($"~ {logNodeCompletion}", ConsoleColor.Green);
            }
        }
예제 #11
0
            public override void Read(CPlugEntRecordData n, GameBoxReader r, GameBoxWriter unknownW)
            {
                Version          = r.ReadInt32();
                UncompressedSize = r.ReadInt32();
                CompressedSize   = r.ReadInt32();
                Data             = r.ReadBytes(CompressedSize);

                // ... WIP ...

                Task.Run(() =>
                {
                    using (var ms = new MemoryStream(Data))
                        using (var cs = new CompressedStream(ms, System.IO.Compression.CompressionMode.Decompress))
                            using (var gbxr = new GameBoxReader(cs))
                            {
                                var u01        = gbxr.ReadInt32();
                                var numSamples = gbxr.ReadInt32();
                                var objects    = gbxr.ReadArray <object>(i =>
                                {
                                    var nodeId = gbxr.ReadUInt32();
                                    Names.TryGetValue(nodeId, out string nodeName);

                                    return(new
                                    {
                                        id = nodeId,
                                        name = nodeName,
                                        rest = gbxr.ReadArray <int>(5)
                                    });
                                });

                                if (Version >= 2)
                                {
                                    var objcts2 = gbxr.ReadArray <object>(i =>
                                    {
                                        var u02 = gbxr.ReadInt32();
                                        var u03 = gbxr.ReadInt32();

                                        uint?clas       = null;
                                        string clasName = null;
                                        if (Version >= 4)
                                        {
                                            clas = gbxr.ReadUInt32();
                                            Names.TryGetValue(clas.Value, out clasName);
                                        }

                                        return(new object[]
                                        {
                                            u02,
                                            u03,
                                            clas,
                                            clasName
                                        });
                                    });
                                }

                                var u04 = gbxr.ReadByte();
                                var u05 = gbxr.ReadArray <int>(4);

                                if (Version >= 6)
                                {
                                    //var u06 = gbxr.ReadUInt32();
                                }

                                var u07 = gbxr.ReadByte();
                                var u08 = gbxr.ReadByte();
                                if (Version >= 2)
                                {
                                    var u09 = gbxr.ReadByte();
                                    var u10 = gbxr.ReadArray <int>(3);
                                    var u11 = gbxr.ReadByte();

                                    if (Version >= 3)
                                    {
                                        var u12 = gbxr.ReadByte();

                                        if (Version == 7)
                                        {
                                        }

                                        if (Version >= 8)
                                        {
                                            var u13 = gbxr.ReadInt32();
                                        }
                                    }
                                }

                                var u14 = gbxr.ReadArray <int>(5);
                            }
                });
            }
예제 #12
0
        public override void Read(CPlugEntRecordData n, GameBoxReader r)
        {
            Version          = r.ReadInt32(); // 10
            UncompressedSize = r.ReadInt32();
            CompressedSize   = r.ReadInt32();
            data             = r.ReadBytes(CompressedSize);

            n.samples = Task.Run(() =>
            {
                var samples = new ObservableCollection <Sample>();

                using var ms = new MemoryStream(data);
                using var cs = new CompressedStream(ms, CompressionMode.Decompress);
                using var r  = new GameBoxReader(cs);

                var u01         = r.ReadInt32();
                var ghostLength = r.ReadInt32(); // milliseconds
                var objects     = r.ReadArray <object>(r =>
                {
                    var nodeId = r.ReadUInt32();
                    NodeCacheManager.Names.TryGetValue(nodeId, out string?nodeName);

                    return(new
                    {
                        nodeId,
                        nodeName,
                        obj_u01 = r.ReadInt32(),
                        obj_u02 = r.ReadInt32(),
                        obj_u03 = r.ReadInt32(),
                        mwbuffer = r.ReadInt32(),
                        obj_u05 = r.ReadInt32()
                    });
                });

                if (Version >= 2)
                {
                    var objcts2 = r.ReadArray <object>(r =>
                    {
                        var u02 = r.ReadInt32();
                        var u03 = r.ReadInt32();

                        uint?clas       = null;
                        string?clasName = null;

                        if (Version >= 4)
                        {
                            clas = r.ReadUInt32();
                            NodeCacheManager.Names.TryGetValue(clas.Value, out clasName);
                        }

                        return(new
                        {
                            u02,
                            u03,
                            clas,
                            clasName
                        });
                    });
                }

                var u04 = r.ReadByte();
                while (u04 != 0)
                {
                    var bufferType        = r.ReadInt32();
                    var u06               = r.ReadInt32();
                    var u07               = r.ReadInt32();
                    var ghostLengthFinish = r.ReadInt32(); // ms

                    if (Version < 6)
                    {
                        // temp_79f24995b2b->field_0x28 = temp_79f24995b2b->field_0xc
                    }
                    else
                    {
                        var u08 = r.ReadInt32();
                    }

                    // Reads byte on every loop until the byte is 0, should be 1 otherwise
                    for (byte x; (x = r.ReadByte()) != 0;)
                    {
                        var timestamp = r.ReadInt32();
                        var buffer    = r.ReadBytes(); // MwBuffer

                        if (buffer.Length > 0)
                        {
                            using var bufferMs = new MemoryStream(buffer);
                            using var bufferR  = new GameBoxReader(bufferMs);

                            var sampleProgress = (int)bufferMs.Position;

                            var sample = new Sample(buffer)
                            {
                                BufferType = (byte)bufferType
                            };

                            switch (bufferType)
                            {
                            case 0:
                                break;

                            case 2:
                                {
                                    bufferMs.Position = 5;

                                    var(position, rotation, speed, velocity) = bufferR.ReadTransform();      // Only position matches

                                    sample.Timestamp = TimeSpan.FromMilliseconds(timestamp);
                                    sample.Position  = position;
                                    sample.Rotation  = rotation;
                                    sample.Speed     = speed * 3.6f;
                                    sample.Velocity  = velocity;

                                    break;
                                }

                            case 4:
                                {
                                    bufferMs.Position = 5;
                                    var rpmByte       = bufferR.ReadByte();

                                    bufferMs.Position = 14;
                                    var steerByte     = bufferR.ReadByte();
                                    var steer         = ((steerByte / 255f) - 0.5f) * 2;

                                    bufferMs.Position = 91;
                                    var gearByte      = bufferR.ReadByte();
                                    var gear          = gearByte / 5f;

                                    sample.Gear  = gear;
                                    sample.RPM   = rpmByte;
                                    sample.Steer = steer;

                                    bufferMs.Position = 15;
                                    var u15           = bufferR.ReadByte();

                                    bufferMs.Position = 18;
                                    var brakeByte     = bufferR.ReadByte();
                                    var brake         = brakeByte / 255f;
                                    var gas           = u15 / 255f + brake;

                                    sample.Brake = brake;
                                    sample.Gas   = gas;

                                    bufferMs.Position = 47;

                                    var(position, rotation, speed, velocity) = bufferR.ReadTransform();

                                    sample.Timestamp = TimeSpan.FromMilliseconds(timestamp);
                                    sample.Position  = position;
                                    sample.Rotation  = rotation;
                                    sample.Speed     = speed * 3.6f;
                                    sample.Velocity  = velocity;

                                    break;
                                }

                            case 10:
                                break;

                            default:
                                break;
                            }

                            samples.Add(sample);
                        }
                    }

                    u04 = r.ReadByte();

                    if (Version >= 2)
                    {
                        while (r.ReadByte() != 0)
                        {
                            var type      = r.ReadInt32();
                            var timestamp = r.ReadInt32();
                            var buffer    = r.ReadBytes(); // MwBuffer
                        }
                    }
                }

                if (Version >= 3)
                {
                    while (r.ReadByte() != 0)
                    {
                        var u19 = r.ReadInt32();
                        var u20 = r.ReadInt32();
                        var u21 = r.ReadBytes(); // MwBuffer
                    }

                    if (Version == 7)
                    {
                        while (r.ReadByte() != 0)
                        {
                            var u23 = r.ReadInt32();
                            var u24 = r.ReadBytes(); // MwBuffer
                        }
                    }

                    if (Version >= 8)
                    {
                        var u23 = r.ReadInt32();

                        if (u23 != 0)
                        {
                            if (Version == 8)
                            {
                                while (r.ReadByte() != 0)
                                {
                                    var u25 = r.ReadInt32();
                                    var u26 = r.ReadBytes(); // MwBuffer
                                }
                            }
                            else
                            {
                                while (r.ReadByte() != 0)
                                {
                                    var u28 = r.ReadInt32();
                                    var u29 = r.ReadBytes(); // MwBuffer
                                    var u30 = r.ReadBytes(); // MwBuffer
                                }

                                if (Version >= 10)
                                {
                                    var period = r.ReadInt32();
                                }
                            }
                        }
                    }
                }

                return(samples);
            });
        }