Example #1
0
        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;
        }
Example #2
0
 public void Write(BinBuffer bb)
 {
     Write(bb, 0, bb.Size);
 }
Example #3
0
        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));
        }