コード例 #1
0
    internal static T?Parse <T>(GameBoxReader r, uint?classID = null, IProgress <GameBoxReadProgress>?progress = null) where T : CMwNod
    {
        if (!classID.HasValue)
        {
            classID = r.ReadUInt32();
        }

        if (classID == uint.MaxValue)
        {
            return(null);
        }

        classID = Remap(classID.Value);

        if (!NodeCacheManager.AvailableClasses.TryGetValue(classID.Value, out Type? type))
        {
            throw new NotImplementedException($"Node ID 0x{classID.Value:X8} is not implemented. ({NodeCacheManager.Names.Where(x => x.Key == Chunk.Remap(classID.Value)).Select(x => x.Value).FirstOrDefault() ?? "unknown class"})");
        }

        NodeCacheManager.AvailableClassConstructors.TryGetValue(classID.Value, out Func <CMwNod>?constructor);

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

        var node = (T)constructor();

        node.SetIDAndChunks();

        Parse(node, r, progress);

        return(node);
    }
コード例 #2
0
        public static T Parse <T>(GameBoxReader r, uint?classID = null, IProgress <GameBoxReadProgress> progress = null) where T : CMwNod
        {
            if (!classID.HasValue)
            {
                classID = r.ReadUInt32();
            }

            if (classID == uint.MaxValue)
            {
                return(null);
            }

            classID = Remap(classID.Value);

            if (!NodeCacheManager.AvailableClasses.TryGetValue(classID.Value, out Type type))
            {
                throw new NotImplementedException($"Node ID 0x{classID.Value:X8} is not implemented. ({NodeCacheManager.Names.Where(x => x.Key == Chunk.Remap(classID.Value)).Select(x => x.Value).FirstOrDefault() ?? "unknown class"})");
            }

            var node = (T)Activator.CreateInstance(type);

            Parse(node, r, progress);

            return(node);
        }
コード例 #3
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);
    }
コード例 #4
0
ファイル: NadeoPakList.cs プロジェクト: ArkadySK/gbx-net
    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));
    }
コード例 #5
0
    public void Read(GameBoxReader r)
    {
        var classId = r.ReadUInt32();

        Version = r.ReadInt32();

        if (Version < 3)
        {
            return;
        }

        var typeCount = r.ReadByte();
        var types     = new ScriptVariable[typeCount];

        for (var i = 0; i < typeCount; i++)
        {
            var varType = r.ReadByte();

            types[i] = (ScriptType)varType switch
            {
                ScriptType.Array => ReadScriptArray(r),
                ScriptType.Struct => ReadScriptStruct(out int _, r),
                _ => new ScriptVariable((ScriptType)varType),
            };
        }

        var varCount = r.ReadByte();
        var metadata = new ScriptVariable[varCount];

        for (var i = 0; i < varCount; i++)
        {
            var metadataVarName = r.ReadString(StringLengthPrefix.Byte);
            var typeIndex       = r.ReadByte();

            var type = types[typeIndex];
            metadata[i]      = ReadType(type.Clone(), r);
            metadata[i].Name = metadataVarName;
        }

        Metadata = metadata.ToList();

        var facade = r.ReadUInt32();
    }
コード例 #6
0
            public override void Read(CGameCtnReplayRecord n, GameBoxReader r)
            {
                n.eventsDuration = r.ReadInt32();

                if (n.eventsDuration != 0)
                {
                    U01 = r.ReadInt32();

                    // All control names available in the game
                    var controlNames = r.ReadArray(r1 =>
                    {
                        // Maybe bindings
                        r1.ReadInt32();
                        r1.ReadInt32();

                        return(r1.ReadString()); // Input name
                    });

                    var numEntries = r.ReadInt32() - 1;

                    n.controlEntries = new ControlEntry[numEntries];

                    for (var i = 0; i < numEntries; i++)
                    {
                        var time             = TimeSpan.FromMilliseconds(r.ReadInt32() - 10000);
                        var controlNameIndex = r.ReadInt32();
                        var data             = r.ReadUInt32();

                        var name = controlNames[controlNameIndex];

                        switch (name)
                        {
                        case "Steer (analog)":     // Data is bugged
                            n.controlEntries[i] = new ControlEntryAnalog(true)
                            {
                                Name = name, Time = time, Data = data
                            };
                            break;

                        default:
                            n.controlEntries[i] = new ControlEntry()
                            {
                                Name = name, Time = time, Data = data
                            };
                            break;
                        }
                    }

                    Array.Reverse(n.controlEntries); // Inputs are originally reversed

                    U02 = r.ReadInt32();
                }
            }
コード例 #7
0
            public override void Read(CGameCtnReplayRecord n, GameBoxReader r)
            {
                n.eventsDuration = r.ReadInt32();

                if (n.eventsDuration != 0)
                {
                    U01 = r.ReadInt32();

                    var controlNames = r.ReadArray(r1 => r1.ReadId());

                    var numEntries = r.ReadInt32();
                    U02 = r.ReadInt32();

                    n.controlEntries = new ControlEntry[numEntries];

                    for (var i = 0; i < numEntries; i++)
                    {
                        var time             = TimeSpan.FromMilliseconds(r.ReadInt32() - 100000);
                        var controlNameIndex = r.ReadByte();
                        var data             = r.ReadUInt32();

                        var name = controlNames[controlNameIndex];

                        switch (name)
                        {
                        case "Steer":
                        case "Gas":
                        case "AccelerateReal":
                        case "BrakeReal":
                            n.controlEntries[i] = new ControlEntryAnalog()
                            {
                                Name = name, Time = time, Data = data
                            };
                            break;

                        default:
                            n.controlEntries[i] = new ControlEntry()
                            {
                                Name = name, Time = time, Data = data
                            };
                            break;
                        }
                    }
                }
            }
コード例 #8
0
        public override void Read(CGameCtnReplayRecord n, GameBoxReader r)
        {
            n.eventsDuration = r.ReadInt32();

            if (n.eventsDuration == 0)
            {
                return;
            }

            U01 = r.ReadInt32();

            var controlNames = r.ReadArray(r1 => r1.ReadId());

            var numEntries = r.ReadInt32();

            U02 = r.ReadInt32();

            n.controlEntries = new ControlEntry[numEntries];

            for (var i = 0; i < numEntries; i++)
            {
                var time             = TimeSpan.FromMilliseconds(r.ReadInt32() - 100000);
                var controlNameIndex = r.ReadByte();
                var data             = r.ReadUInt32();

                var name = controlNames[controlNameIndex];

                n.controlEntries[i] = (string)name switch
                {
                    "Steer" or "Gas" or "AccelerateReal" or "BrakeReal"
                    => new ControlEntryAnalog(name)
                    {
                        Time = time, Data = data
                    },
                    _ => new ControlEntry(name)
                    {
                        Time = time, Data = data
                    },
                };
            }
        }
コード例 #9
0
    private void ReadFiles(GameBoxReader r, NadeoPakFolder[] folders)
    {
        var numFiles = r.ReadInt32();
        var files    = new NadeoPakFile[numFiles];

        for (var i = 0; i < numFiles; i++)
        {
            var folderIndex      = r.ReadInt32(); // index into folders
            var name             = r.ReadString();
            var unknown          = r.ReadInt32();
            var uncompressedSize = r.ReadInt32();
            var compressedSize   = r.ReadInt32();
            var offset           = r.ReadInt32();
            var classID          = CMwNod.Remap(r.ReadUInt32()); // indicates the type of the file
            var flags            = r.ReadUInt64();

            var folder = folders.ElementAtOrDefault(folderIndex);

            var file = new NadeoPakFile(this, folder, name, uncompressedSize, compressedSize, offset, classID, flags)
            {
                U01 = unknown
            };

            files[i] = file;

            if (folder == null)
            {
                Files.Add(file);
            }
            else
            {
                folder.Files.Add(file);
            }
        }

        this.files = files;
    }
コード例 #10
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);
                }
            }
コード例 #11
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);
            }
        }
コード例 #12
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);
                            }
                });
            }
コード例 #13
0
        public void Read(GameBoxReader r)
        {
            var classId = r.ReadUInt32();

            Version = r.ReadInt32();

            var typeCount = r.ReadByte();
            var types     = new ScriptVariable[typeCount];

            for (var i = 0; i < typeCount; i++)
            {
                var varType = r.ReadByte();

                switch ((ScriptType)varType)
                {
                case ScriptType.Array:
                    types[i] = ReadScriptArray();
                    break;

                case ScriptType.Struct:
                    types[i] = ReadScriptStruct(out int defaultLength);
                    break;

                default:
                    types[i] = new ScriptVariable((ScriptType)varType);
                    break;
                }
            }

            var varCount = r.ReadByte();
            var metadata = new ScriptVariable[varCount];

            for (var i = 0; i < varCount; i++)
            {
                var metadataVarName = r.ReadString(StringLengthPrefix.Byte);
                var typeIndex       = r.ReadByte();

                var type = types[typeIndex];
                metadata[i]      = ReadType(type.Clone());
                metadata[i].Name = metadataVarName;
            }

            Metadata = metadata.ToList();

            var facade = r.ReadUInt32();

            ScriptArray ReadScriptArray()
            {
                ScriptVariable indexVar;

                var indexType = r.ReadByte(); // index

                if ((ScriptType)indexType == ScriptType.Struct)
                {
                    indexVar = ReadScriptStruct(out int defaultLength);
                }
                else
                {
                    indexVar = new ScriptVariable((ScriptType)indexType);
                }

                ScriptVariable valueVar;

                var arrayType = r.ReadByte(); // value

                if ((ScriptType)arrayType == ScriptType.Array)
                {
                    valueVar = ReadScriptArray();
                }
                else if ((ScriptType)arrayType == ScriptType.Struct)
                {
                    valueVar = ReadScriptStruct(out int defaultLength);
                }
                else
                {
                    valueVar = new ScriptVariable((ScriptType)arrayType);
                }

                ScriptArray array = new ScriptArray(new KeyValuePair <ScriptVariable, ScriptVariable>(indexVar, valueVar));

                int counterArray = 0;

                while (r.ReadByte() == 0)
                {
                    counterArray++;
                }
                r.BaseStream.Position -= 1;

                array.Unknown = counterArray;

                return(array);
            }

            ScriptStruct ReadScriptStruct(out int defaultLength)
            {
                var strc = new ScriptStruct();

                var numMembers = r.ReadByte();
                var structName = r.ReadString();

                strc.StructName = structName;
                strc.Members    = new ScriptVariable[numMembers];

                defaultLength = 0;

                for (var i = 0; i < numMembers; i++)
                {
                    ScriptVariable member;

                    var memberName = r.ReadString();
                    var memberType = r.ReadByte();

                    switch ((ScriptType)memberType)
                    {
                    case ScriptType.Array:
                        member = ReadScriptArray();
                        break;

                    case ScriptType.Struct:
                        member         = ReadScriptStruct(out int defLength);
                        defaultLength += defLength;
                        break;

                    default:
                        member = new ScriptVariable((ScriptType)memberType);
                        break;
                    }

                    switch (member.Type)
                    {
                    case ScriptType.Integer:
                        r.ReadInt32();
                        defaultLength += 4;
                        break;

                    case ScriptType.Real:
                        r.ReadSingle();
                        defaultLength += 4;
                        break;

                    case ScriptType.Vec2:
                        r.ReadVec2();
                        defaultLength += 8;
                        break;

                    case ScriptType.Vec3:
                        r.ReadVec3();
                        defaultLength += 12;
                        break;

                    case ScriptType.Int3:
                        r.ReadInt3();
                        defaultLength += 12;
                        break;

                    case ScriptType.Int2:
                        r.ReadInt2();
                        defaultLength += 8;
                        break;

                    case ScriptType.Array:
                        break;

                    case ScriptType.Struct:
                        break;

                    default:
                        r.ReadByte();
                        defaultLength += 1;
                        break;
                    }

                    member.Name = memberName;

                    strc.Members[i] = member;
                }

                int counter = 0;

                while (r.ReadByte() == 0)
                {
                    counter++;
                }
                r.BaseStream.Position -= 1;

                //int counter = 0;
                //while (r.ReadByte() == 0) counter++; // probably size of the struct in byte count?
                //r.BaseStream.Position -= 1;
                strc.Size    = defaultLength + counter; //
                strc.Unknown = counter;

                //Progress += defaultLength;

                return(strc);
            }

            ScriptVariable ReadType(ScriptVariable type)
            {
                switch (type.Type)
                {
                case ScriptType.Boolean:
                    type.Value = Convert.ToBoolean(r.ReadBoolean(true));
                    break;

                case ScriptType.Integer:
                    type.Value = r.ReadInt32();
                    break;

                case ScriptType.Real:
                    type.Value = r.ReadSingle();
                    break;

                case ScriptType.Text:
                    type.Value = r.ReadString(StringLengthPrefix.Byte);
                    break;

                case ScriptType.Vec2:
                    type.Value = r.ReadVec2();
                    break;

                case ScriptType.Vec3:
                    type.Value = r.ReadVec3();
                    break;

                case ScriptType.Int3:
                    type.Value = r.ReadInt3();
                    break;

                case ScriptType.Int2:
                    type.Value = r.ReadInt2();
                    break;

                case ScriptType.Array:
                    var array = type as ScriptArray;

                    var numElements = r.ReadByte();
                    if (numElements > 0)
                    {
                        ScriptVariable key;
                        if (array.Reference.Key.Type == ScriptType.Void)
                        {
                            for (var i = 0; i < numElements; i++)
                            {
                                array.Elements[new ScriptVariable(ScriptType.Void)
                                               {
                                                   Value = i
                                               }] = ReadType(array.Reference.Value.Clone());
                            }
                        }
                        else
                        {
                            key = ReadType(array.Reference.Key.Clone());
                            for (var i = 0; i < numElements; i++)
                            {
                                array.Elements[key] = ReadType(array.Reference.Value.Clone());
                            }
                        }
                    }
                    break;

                case ScriptType.Struct:
                    var strc = type as ScriptStruct;
                    for (var i = 0; i < strc.Members.Length; i++)
                    {
                        strc.Members[i] = ReadType(strc.Members[i]);
                    }
                    break;

                default:
                    throw new Exception(type.Type.ToString());
                }

                return(type);
            }
        }
コード例 #14
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);
            });
        }