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(); }
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 }
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 }); } }
/// <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); }
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)); }
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); }
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(); }
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); } }
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); }); }
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); } }
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); } }); }
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); }); }