public GameBoxReader(Stream input, ILookbackable lookbackable) : this(input) { Lookbackable = lookbackable; if (lookbackable is GameBoxBody b) { Body = b; } }
public Id ReadId(ILookbackable lookbackable) { if (!lookbackable.IdVersion.HasValue) { lookbackable.IdVersion = ReadInt32(); if ((lookbackable.IdVersion & 0xC0000000) > 10) // Edge-case scenario where Id doesn't have a version for whatever reason (can be multiple) { lookbackable.IdVersion = 3; if (BaseStream.CanSeek) { BaseStream.Seek(-4, SeekOrigin.Current); } else { throw new NotSupportedException("GBX has the first Id presented without a version. Solution exists, but the stream does not support seeking."); } } } var index = ReadUInt32(); if ((index & 0x3FFF) == 0 && (index >> 30 == 1 || index >> 30 == 2)) { var str = ReadString(); lookbackable.IdStrings.Add(str); return(new Id(str, lookbackable)); } else if ((index & 0x3FFF) == 0x3FFF) { switch (index >> 30) { case 2: return(new Id("Unassigned", lookbackable)); case 3: return(new Id("", lookbackable)); default: throw new Exception(); } } else if (index >> 30 == 0) { return(new Id(index.ToString(), lookbackable)); } else if (lookbackable.IdStrings.Count > (index & 0x3FFF) - 1) { return(new Id(lookbackable.IdStrings[(int)(index & 0x3FFF) - 1], lookbackable)); } else { return(new Id("", lookbackable)); } }
public void Write(GameBoxWriter w, ClassIDRemap remap) { var stopwatch = Stopwatch.StartNew(); int counter = 0; foreach (Chunk chunk in Chunks) { counter++; var logChunk = $"[{ClassName}] 0x{chunk.ID:X8} ({(float)counter / Chunks.Count:0.00%})"; if (Body?.GBX.ClassID.HasValue == true && Remap(Body.GBX.ClassID.Value) == ID) { Log.Write(logChunk); } else { Log.Write($"~ {logChunk}"); } ((IChunk)chunk).Node = this; chunk.Unknown.Position = 0; ILookbackable lb = chunk.Lookbackable; if (chunk is ILookbackable l) { l.IdWritten = false; l.IdStrings.Clear(); lb = l; } if (lb == null) { if (ParentChunk is ILookbackable l2) { lb = l2; } else { lb = w.Lookbackable; } } using (var ms = new MemoryStream()) using (var msW = new GameBoxWriter(ms, lb)) { var rw = new GameBoxReaderWriter(msW); msW.Chunk = chunk; try { if (chunk is ISkippableChunk s && !s.Discovered) { s.Write(msW); } else if (chunk.GetType().GetCustomAttribute <AutoReadWriteChunkAttribute>() == null) { ((IChunk)chunk).ReadWrite(this, rw); } else { msW.Write(chunk.Unknown.ToArray(), 0, (int)chunk.Unknown.Length); } w.Write(Chunk.Remap(chunk.ID, remap)); if (chunk is ISkippableChunk) { w.Write(0x534B4950); w.Write((int)ms.Length); } w.Write(ms.ToArray(), 0, (int)ms.Length); }
public void Write(Ident ident, ILookbackable lookbackable) { Write(new Id(ident.ID, lookbackable)); Write(ident.Collection.ToId(lookbackable)); Write(new Id(ident.Author, lookbackable)); }
/// <exception cref="IOException">An I/O error occurs.</exception> /// <exception cref="ObjectDisposedException">The stream is closed.</exception> public void Write(Ident?ident, ILookbackable lookbackable) { Write(new Id(ident?.ID, lookbackable)); Write(ident?.Collection.ToId(lookbackable) ?? new Id(null, lookbackable)); Write(new Id(ident?.Author, lookbackable)); }
public GameBoxWriter(Stream input, ILookbackable lookbackable) : this(input) { Lookbackable = lookbackable; }