public void Write(BinBuffer bb, int startPos, int count, int offset = 0) { var p = bb.Position; bb.Position = offset; Write(bb.ReadBytes(count), startPos, count); bb.Position = p; }
public void Write(BinBuffer bb) { Write(bb, 0, bb.Size); }
public static byte[] WriteFile(string baseDir, JsonData projFile, GMFile f) { Console.WriteLine($"Preparing strings..."); var stringsChunkBuilder = new StringsChunkBuilder(); stringsChunkBuilder.AddStrings(f.Strings); var texpChunk = new BBData(new BinBuffer(), new int[0]); Console.WriteLine($"Preparing textures..."); int[] texPagOffsets = SectionWriter.WriteTexturePages(texpChunk, f.TexturePages); var codeChunk = new BBData(new BinBuffer(), new int[0]); Console.WriteLine($"Preparing code..."); var codeChunkStringOffsetOffsets = Assembler.WriteCodes(codeChunk, f, stringsChunkBuilder); var offsets = new int[0]; BBData writer = new BBData(new BinBuffer(), offsets); writer.Buffer.Write(SectionHeaders.Form); writer.Buffer.Write(0); var stringOffsetOffsets = new List <int>(); int stringsDataPosition = 0; var texpOffsetOffsets = new List <int>(); int texpChunkPosition = 0; var codeOffsetOffsets = new List <int>(); int codeChunkPosition = 0; foreach (SectionHeaders chunkId in f.ChunkOrder) { Console.WriteLine($"Writing {chunkId}..."); BBData chunk = new BBData(new BinBuffer(), new int[0]); int[] chunkStringOffsetOffsets = null; int[] chunkTexpOffsetOffsets = null; int[] chunkCodeOffsetOffsets = null; switch (chunkId) { case SectionHeaders.General: chunkStringOffsetOffsets = SectionWriter.WriteGeneral(chunk, f.General, f.Rooms, stringsChunkBuilder); break; case SectionHeaders.Options: chunkStringOffsetOffsets = SectionWriter.WriteOptions(chunk, f.Options, stringsChunkBuilder); break; case SectionHeaders.Sounds: chunkStringOffsetOffsets = SectionWriter.WriteSounds(chunk, f.Sound, stringsChunkBuilder, f.AudioGroups); break; case SectionHeaders.AudioGroup: chunkStringOffsetOffsets = SectionWriter.WriteAudioGroups(chunk, f.AudioGroups, stringsChunkBuilder); break; case SectionHeaders.Sprites: SectionWriter.WriteSprites(chunk, f.Sprites, stringsChunkBuilder, texPagOffsets, out chunkStringOffsetOffsets, out chunkTexpOffsetOffsets); break; case SectionHeaders.Backgrounds: SectionWriter.WriteBackgrounds(chunk, f.Backgrounds, stringsChunkBuilder, texPagOffsets, out chunkStringOffsetOffsets, out chunkTexpOffsetOffsets); break; case SectionHeaders.Paths: chunkStringOffsetOffsets = SectionWriter.WritePaths(chunk, f.Paths, stringsChunkBuilder); break; case SectionHeaders.Scripts: chunkStringOffsetOffsets = SectionWriter.WriteScripts(chunk, f.Scripts, stringsChunkBuilder); break; case SectionHeaders.Fonts: SectionWriter.WriteFonts(chunk, f.Fonts, stringsChunkBuilder, texPagOffsets, out chunkStringOffsetOffsets, out chunkTexpOffsetOffsets); break; case SectionHeaders.Objects: chunkStringOffsetOffsets = SectionWriter.WriteObjects(chunk, f.Objects, stringsChunkBuilder); break; case SectionHeaders.Rooms: chunkStringOffsetOffsets = SectionWriter.WriteRooms(chunk, f.Rooms, stringsChunkBuilder); break; case SectionHeaders.TexturePage: chunk = texpChunk; texpChunkPosition = writer.Buffer.Position + 8; break; case SectionHeaders.Code: chunk = codeChunk; chunkStringOffsetOffsets = codeChunkStringOffsetOffsets; codeChunkPosition = writer.Buffer.Position + 8; break; case SectionHeaders.Variables: if (f.VariableExtra != null) { foreach (var e in f.VariableExtra) { chunk.Buffer.Write(e); } } SectionWriter.WriteRefDefs(chunk, f.RefData.Variables, stringsChunkBuilder, f.General.IsOldBCVersion, false, out chunkStringOffsetOffsets, out chunkCodeOffsetOffsets); break; case SectionHeaders.Functions: SectionWriter.WriteRefDefs(chunk, f.RefData.Functions, stringsChunkBuilder, f.General.IsOldBCVersion, true, out chunkStringOffsetOffsets, out chunkCodeOffsetOffsets); chunkStringOffsetOffsets = chunkStringOffsetOffsets.Concat(SectionWriter.WriteFunctionLocals(chunk, f.FunctionLocals, stringsChunkBuilder)).ToArray(); break; case SectionHeaders.Strings: var stringOffsets = stringsChunkBuilder.WriteStringsChunk(chunk); stringsDataPosition = writer.Buffer.Position + stringOffsets[0] + 12; // for Textures chunk up next SectionWriter.Pad(chunk, 0x80, writer.Buffer.Position + 8); break; case SectionHeaders.Textures: SectionWriter.WriteTextures(chunk, f.Textures); break; case SectionHeaders.Audio: SectionWriter.WriteAudio(chunk, f.Audio, writer.Buffer.Position); break; case SectionHeaders.Shaders: chunkStringOffsetOffsets = SectionWriter.WriteShaders(chunk, f.Shaders, stringsChunkBuilder); break; default: var chunkName = chunkId.ToChunkName(); Console.Error.WriteLine($"Note: Don't know how to handle {chunkName}"); string chunkFile = null; if (projFile.Has("chunks") && projFile["chunks"].IsArray) { foreach (JsonData jd in projFile["chunks"]) { if (jd.IsString) { if (Path.GetFileNameWithoutExtension((string)jd) == chunkName) { chunkFile = (string)jd; break; } } } } BinBuffer chunkData; if (chunkFile == null) { Console.Error.WriteLine($"Note: Chunk {chunkName} was not dumped, assuming it's empty"); chunkData = new BinBuffer(); } else { Console.Error.WriteLine($"Note: Loading {chunkName} from dump"); try { chunkData = new BinBuffer(File.ReadAllBytes(Path.Combine(baseDir, chunkFile))); } catch (Exception e) { Console.Error.WriteLine($"Error loading {chunkName}, using empty"); Console.Error.WriteLine(e); chunkData = new BinBuffer(); } } chunk = new BBData(chunkData, new int[0]); break; } if (chunkStringOffsetOffsets != null) { foreach (var offset in chunkStringOffsetOffsets) { stringOffsetOffsets.Add(offset + writer.Buffer.Position); } } chunkStringOffsetOffsets = null; if (chunkTexpOffsetOffsets != null) { foreach (var offset in chunkTexpOffsetOffsets) { texpOffsetOffsets.Add(offset + writer.Buffer.Position); } } chunkTexpOffsetOffsets = null; if (chunkCodeOffsetOffsets != null) { foreach (var offset in chunkCodeOffsetOffsets) { codeOffsetOffsets.Add(offset + writer.Buffer.Position); } } chunkCodeOffsetOffsets = null; SectionWriter.WriteChunk(writer, chunkId, chunk); } writer.Buffer.Position = 4; writer.Buffer.Write(writer.Buffer.Size - 8); writer.Buffer.Position = writer.Buffer.Size; foreach (var stringOffset in stringOffsetOffsets) { writer.Buffer.Position = stringOffset; var o = writer.Buffer.ReadInt32(); //bb.Position -= sizeof(int); writer.Buffer.Write(o + stringsDataPosition); } foreach (var texpOffset in texpOffsetOffsets) { writer.Buffer.Position = texpOffset; var o = writer.Buffer.ReadInt32(); //bb.Position -= sizeof(int); writer.Buffer.Write(o + texpChunkPosition); } foreach (var codeOffset in codeOffsetOffsets) { writer.Buffer.Position = codeOffset; var o = writer.Buffer.ReadInt32(); //bb.Position -= sizeof(int); writer.Buffer.Write(o + codeChunkPosition); } writer.Buffer.Position = 0; return(writer.Buffer.ReadBytes(writer.Buffer.Size)); }