コード例 #1
0
        public override void Write(IntPtr data, int size)
        {
            var buf = new byte[size];

            ILHacks.Cpblk((void *)data, buf, 0, size);
            stream.Write(buf, 0, size);
        }
コード例 #2
0
        public UniquePtr(byte[] data)
        {
            Size     = data.Length;
            LongSize = data.LongLength;

            stuff = Marshal.AllocHGlobal(data.Length);

            ILHacks.Cpblk(data, stuff, 0, data.Length);
            //Marshal.Copy(data, 0, stuff, data.Length);
        }
コード例 #3
0
        public unsafe T ReadStruct <T>()
            where T : struct
        {
            var s = ILHacks.SizeOf <T>();

            fixed(byte *ptr = ReadBytes(s))
            {
                var r = default(T);

                ILHacks.Cpblk((void *)ptr, ref r);
                return(r);
            }
        }
コード例 #4
0
        public override void Write(Union v, int size)
        {
            if (pos > buffer.Length - size)
            {
                ResizeBuffer(buffer.Length + size);
            }
            if (pos > this.size - size)
            {
                this.size += size;
            }

            ILHacks.Cpblk(ref v, buffer, pos, size);

            pos += size;
        }
コード例 #5
0
        public override void Write(IntPtr data, int size)
        {
            if (pos + size > buffer.Length)
            {
                throw new EndOfStreamException();
            }
            if (pos + size > this.size)
            {
                this.size += size;
            }

            ILHacks.Cpblk((void *)data, buffer, pos, size);

            pos += size;
        }
コード例 #6
0
        public override void Write(IntPtr data, int size)
        {
            if (pos + size > buffer.Length)
            {
                ResizeBuffer(buffer.Length + size);
            }
            if (pos + size > this.size)
            {
                this.size += size;
            }

            ILHacks.Cpblk((void *)data, buffer, pos, size);

            pos += size;
        }
コード例 #7
0
        public override void Write(IntPtr data, int size)
        {
            if (setMaxSize > -1 && Position + size > setMaxSize)
            {
                throw new EndOfStreamException();
            }
            if (Position + size > this.size)
            {
                this.size += size;
            }

            ILHacks.Cpblk((void *)data, (void *)(address + Position), size);

            Position += size;
        }
コード例 #8
0
        public unsafe void Write <T>(T value)
            where T : struct
        {
            var s     = ILHacks.SizeOf <T>();
            var stuff = Marshal.AllocHGlobal(s);

            try
            {
                ILHacks.Cpblk(ref value, (void *)stuff);
                Write(stuff, s);
            }
            finally
            {
                Marshal.FreeHGlobal(stuff);
            }
        }
コード例 #9
0
        public override void Write(Union v, int size)
        {
            var up = &v;

            if (setMaxSize > -1 && Position + size > setMaxSize)
            {
                throw new AccessViolationException();
            }
            if (Position + size > this.size)
            {
                this.size += size;
            }

            ILHacks.Cpblk((void *)(&v), (void *)(address + Position), size);

            Position += size;
        }
コード例 #10
0
        // used to prove the chunk order doesn't matter
        unsafe static void SwapChunks(GMFileContent f)
        {
            int EmptyChunkSize = sizeof(SectionUnknown);

            var exntO = (long)f.Extensions - (long)f.RawData.BPtr;
            var tmlnO = (long)f.Timelines - (long)f.RawData.BPtr;

            byte[] extnT = new byte[EmptyChunkSize];

            ILHacks.Cpblk((IntPtr)f.Extensions, extnT, 0, EmptyChunkSize);
            ILHacks.Cpblk((IntPtr)f.Timelines, (IntPtr)f.Extensions, EmptyChunkSize);
            ILHacks.Cpblk(extnT, (IntPtr)f.Timelines, 0, EmptyChunkSize);

            byte[] EVERYTHING = new byte[f.RawData.Size];

            ILHacks.Cpblk(f.RawData.IPtr, EVERYTHING, 0, f.RawData.Size);

            File.WriteAllBytes("data.fake.win", EVERYTHING);
        }
コード例 #11
0
        static void Export(ExportOptions eo)
        {
            var file = Path.GetFullPath(String.IsNullOrEmpty(eo.File) ? DATA_WIN : eo.File);

            try // see #m17
            {
                int i = Console.CursorLeft;
                i = i-- + 1;
            }
            catch
            {
                eo.NoPrecProg = true;
            }

            if (Directory.Exists(file) && !File.Exists(file))
            {
                file += Path.DirectorySeparatorChar + DATA_WIN;
            }
            if (!File.Exists(file))
            {
                throw new ParserException("File \"" + file + "\" not found.");
            }

            var od = (String.IsNullOrEmpty(eo.OutputDirectory) ? Path.GetDirectoryName(file) : eo.OutputDirectory) + Path.DirectorySeparatorChar;

            using (var f = GMFile.GetFile(file))
            {
                #region defaults
                if (!(eo.Disassemble || eo.String || eo.Variables || eo.Functions ||
                      eo.Audio || eo.Background || eo.Decompile || eo.Font || eo.General ||
                      eo.Object || eo.Options || eo.Path || eo.Room || eo.Script ||
                      eo.Sound || eo.Sprite || eo.Texture || eo.TPag ||
                      eo.ExportToProject || eo.Any || eo.DumpUnknownChunks))
                {
                    eo.Any = true;
                }

                if (eo.ExportToProject)
                {
                    eo.Disassemble = eo.String = eo.Variables = eo.Functions = false;

                    eo.Audio = eo.Background = eo.Decompile = eo.Font = eo.General
                                                                            = eo.Object = eo.Options = eo.Path = eo.Room = eo.Script
                                                                                                                               = eo.Sound = eo.Sprite = eo.Texture = eo.TPag = eo.DumpUnknownChunks
                                                                                                                                                                                   = true;
                }
                if (eo.Any)
                {
                    eo.Disassemble = false;

                    eo.Audio = eo.Background = eo.Decompile = eo.Font = eo.General
                                                                            = eo.Object = eo.Options = eo.Path = eo.Room = eo.Script
                                                                                                                               = eo.Sound = eo.Sprite = eo.Texture = eo.TPag
                                                                                                                                                                         = eo.String = eo.Variables = eo.Functions = eo.DumpUnknownChunks
                                                                                                                                                                                                                         = true;
                }
                #endregion

                // ---

                #region GEN8
                if (eo.General)
                {
                    if (!eo.Quiet)
                    {
                        Console.WriteLine("Exporting manifest file...");
                    }

                    File.WriteAllText(od + "general.json", JsonMapper.ToJson(Serialize.SerializeGeneral(f.General)));
                }
                #endregion
                #region OPTN
                if (eo.Options)
                {
                    if (!eo.Quiet)
                    {
                        Console.WriteLine("Exporting options...");
                    }

                    File.WriteAllText(od + "options.json", JsonMapper.ToJson(Serialize.SerializeOptions(f.Options)));
                }
                #endregion

                #region STRG
                if (eo.String && f.Strings != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.WriteLine("Dumping strings...");
                    }

                    File.WriteAllText(od + "strings.json", JsonMapper.ToJson(Serialize.SerializeStrings(f)));
                }
                #endregion
                #region VARI
                if (eo.Variables && f.RefData.Variables != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.WriteLine("Dumping variables...");
                    }

                    File.WriteAllText(od + "variables.json", JsonMapper.ToJson(Serialize.SerializeVars(f)));
                }
                #endregion
                #region FUNC
                if (eo.Functions && f.RefData.Functions != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.WriteLine("Dumping functions...");
                    }

                    File.WriteAllText(od + "functions.json", JsonMapper.ToJson(Serialize.SerializeFuncs(f)));
                }
                #endregion

                int cl = 0, ct = 0;
                #region TXTR
                if (eo.Texture && f.Textures != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting texture sheets... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_TEX))
                    {
                        Directory.CreateDirectory(od + DIR_TEX);
                    }

                    for (int i = 0; i < f.Textures.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);

                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Textures.Length + C_PAREN);
                        }

                        File.WriteAllBytes(od + DIR_TEX + i + EXT_PNG, f.Textures[i].PngData);
                    }
                }
                #endregion
                #region AUDO
                if (eo.Audio && f.Audio != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting audio files... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    var infoTable = new Dictionary <int, SoundInfo>();

                    foreach (var s in f.Sound)
                    {
                        if ((s.IsEmbedded || s.IsCompressed) && s.AudioID != -1)
                        {
                            infoTable[s.AudioID] = s;
                        }
                    }

                    if (!Directory.Exists(od + DIR_WAV))
                    {
                        Directory.CreateDirectory(od + DIR_WAV);
                    }

                    for (int i = 0; i < f.Audio.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Audio.Length + C_PAREN);
                        }

                        File.WriteAllBytes(od + DIR_WAV + infoTable[i].Name + SR.EXT_WAV, f.Audio[i].Wave);
                    }
                }
                #endregion
                #region CODE
                if (eo.Decompile && f.Code != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Decompiling code... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_CODE))
                    {
                        Directory.CreateDirectory(od + DIR_CODE);
                    }

                    for (int i = 0; i < f.Code.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Code.Length + C_PAREN);
                        }

                        try
                        {
                            File.WriteAllText(od + DIR_CODE + f.Code[i].Name + EXT_GML_LSP, Decompiler.DecompileCode(f, i, eo.AbsoluteAddresses));
                        }
                        catch (Exception e)
                        {
                            Console.Error.WriteLine($"Error: Failed to decompile {f.Code[i].Name}, ignoring...");
                        }
                    }
                }
                if (eo.Disassemble && f.Code != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Disassembling bytecode... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_CODE))
                    {
                        Directory.CreateDirectory(od + DIR_CODE);
                    }

                    for (int i = 0; i < f.Code.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Code.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_CODE + f.Code[i].Name + EXT_GML_ASM, Disassembler.DisplayInstructions(f, i, eo.AbsoluteAddresses));
                    }
                }
                #endregion

                #region SCPT
                if (eo.Script && f.Scripts != null && f.Code != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting scripts... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_SCR))
                    {
                        Directory.CreateDirectory(od + DIR_SCR);
                    }

                    for (int i = 0; i < f.Scripts.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Scripts.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_SCR + f.Scripts[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeScript(f.Scripts[i], f.Code)));
                    }
                }
                #endregion
                #region TPAG
                if (eo.TPag && f.TexturePages != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting texture maps... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_TXP))
                    {
                        Directory.CreateDirectory(od + DIR_TXP);
                    }

                    for (int i = 0; i < f.TexturePages.Length; i++)
                    {
                        Console.SetCursorPosition(cl, ct);
                        Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.TexturePages.Length + C_PAREN);

                        File.WriteAllText(od + DIR_TXP + i + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeTPag(f.TexturePages[i])));
                    }
                }
                #endregion
                #region SPRT
                if (eo.Sprite && f.Sprites != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting sprites... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_SPR))
                    {
                        Directory.CreateDirectory(od + DIR_SPR);
                    }

                    for (int i = 0; i < f.Sprites.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Sprites.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_SPR + f.Sprites[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeSprite(f.Sprites[i])));
                    }
                }
                #endregion
                #region SOND
                if (eo.Sound && f.Sound != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting sounds... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_SND))
                    {
                        Directory.CreateDirectory(od + DIR_SND);
                    }

                    for (int i = 0; i < f.Sound.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Sound.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_SND + f.Sound[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeSound(f.Sound[i])));
                    }
                }
                #endregion

                #region OBJT
                if (eo.Object && f.Objects != null && f.Sprites != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting objects... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_OBJ))
                    {
                        Directory.CreateDirectory(od + DIR_OBJ);
                    }

                    for (int i = 0; i < f.Objects.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Objects.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_OBJ + f.Objects[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeObj(f.Objects[i], f.Sprites, f.Objects)));
                    }
                }
                #endregion
                #region BGND
                if (eo.Background && f.Backgrounds != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting backgrounds... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_BG))
                    {
                        Directory.CreateDirectory(od + DIR_BG);
                    }

                    for (int i = 0; i < f.Backgrounds.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Backgrounds.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_BG + f.Backgrounds[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeBg(f.Backgrounds[i])));
                    }
                }
                #endregion
                #region ROOM
                if (eo.Room && f.Rooms != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting rooms... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_ROOM))
                    {
                        Directory.CreateDirectory(od + DIR_ROOM);
                    }

                    for (int i = 0; i < f.Rooms.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Rooms.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_ROOM + f.Rooms[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeRoom(f.Rooms[i], f.Backgrounds, f.Objects)));
                    }
                }
                #endregion

                #region FONT
                if (eo.Background && f.Fonts != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting fonts... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_FNT))
                    {
                        Directory.CreateDirectory(od + DIR_FNT);
                    }

                    for (int i = 0; i < f.Fonts.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Fonts.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_FNT + f.Fonts[i].CodeName + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeFont(f.Fonts[i])));
                    }
                }
                #endregion
                #region PATH
                if (eo.Path && f.Paths != null)
                {
                    if (!eo.Quiet)
                    {
                        Console.Write("Exporting paths... ");

                        if (!eo.NoPrecProg)
                        {
                            cl = Console.CursorLeft;
                            ct = Console.CursorTop;
                        }
                    }

                    if (!Directory.Exists(od + DIR_PATH))
                    {
                        Directory.CreateDirectory(od + DIR_PATH);
                    }

                    for (int i = 0; i < f.Paths.Length; i++)
                    {
                        if (!eo.Quiet && !eo.NoPrecProg)
                        {
                            Console.SetCursorPosition(cl, ct);
                            Console.WriteLine(O_PAREN + (i + 1) + SLASH + f.Paths.Length + C_PAREN);
                        }

                        File.WriteAllText(od + DIR_PATH + f.Paths[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializePath(f.Paths[i])));
                    }
                }
                #endregion

                List <IntPtr> chunks = new List <IntPtr>(6);

                if (eo.DumpUnknownChunks || eo.DumpAllChunks)
                {
                    Action <IntPtr> DumpUnk = _unk =>
                    {
                        var unk = (SectionUnknown *)_unk;

                        if (unk->IsEmpty() && !eo.DumpEmptyChunks)
                        {
                            return;
                        }

                        if (!eo.Quiet)
                        {
                            Console.WriteLine($"Dumping {unk->Header.MagicString()} chunk...");
                        }

                        byte[] buf = new byte[unk->Header.Size];
                        uint * src = &unk->Unknown;

                        ILHacks.Cpblk <byte>((void *)src, buf, 0, buf.Length);

                        File.WriteAllBytes(od + unk->Header.MagicString() + EXT_BIN, buf);
                    };

                    var c = f.Content;

                    chunks.Add((IntPtr)c.Extensions);
                    chunks.Add((IntPtr)c.AudioGroup);
                    chunks.Add((IntPtr)c.Shaders);
                    chunks.Add((IntPtr)c.Timelines);
                    chunks.Add((IntPtr)c.DataFiles);
                    chunks.Add((IntPtr)c.GNAL_Unk);

                    if (eo.DumpAllChunks)
                    {
                        chunks.Add((IntPtr)c.General);
                        chunks.Add((IntPtr)c.Options);

                        chunks.Add((IntPtr)c.Sounds);
                        chunks.Add((IntPtr)c.Sprites);
                        chunks.Add((IntPtr)c.Backgrounds);
                        chunks.Add((IntPtr)c.Paths);
                        chunks.Add((IntPtr)c.Scripts);
                        chunks.Add((IntPtr)c.Fonts);
                        chunks.Add((IntPtr)c.Objects);
                        chunks.Add((IntPtr)c.Rooms);
                        chunks.Add((IntPtr)c.TexturePages);
                        chunks.Add((IntPtr)c.Code);
                        chunks.Add((IntPtr)c.Strings);
                        chunks.Add((IntPtr)c.Textures);
                        chunks.Add((IntPtr)c.Audio);

                        chunks.Add((IntPtr)c.Functions);
                        chunks.Add((IntPtr)c.Variables);
                    }

                    chunks = chunks.Where(cc => cc != IntPtr.Zero && !((SectionUnknown *)cc)->IsEmpty()).ToList();

                    for (int i = 0; i < chunks.Count; i++)
                    {
                        DumpUnk(chunks[i]);
                    }
                }

                if (eo.ExportToProject)
                {
                    if (!eo.Quiet)
                    {
                        Console.WriteLine("Emitting project file...");
                    }

                    File.WriteAllText(od + f.General.Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeProject(f, chunks)));
                }
            }
        }
コード例 #12
0
ファイル: Program.cs プロジェクト: impiaaa/Altar.NET
        static void Export(ExportOptions eo)
        {
            var file = Path.GetFullPath(String.IsNullOrEmpty(eo.File) ? DATA_WIN : eo.File);

            try // see #17
            {
                int i = Console.CursorLeft;
                i = i-- + 1;
            }
            catch
            {
                eo.NoPrecProg = true;
            }

            if (Directory.Exists(file) && !File.Exists(file))
            {
                file += Path.DirectorySeparatorChar + DATA_WIN;
            }
            if (!File.Exists(file))
            {
                throw new ParserException("File \"" + file + "\" not found.");
            }

            var od = (String.IsNullOrEmpty(eo.OutputDirectory) ? Path.GetDirectoryName(file) : eo.OutputDirectory) + Path.DirectorySeparatorChar;

            if (!Directory.Exists(od))
            {
                Directory.CreateDirectory(od);
            }

            using (var f = GMFile.GetFile(file))
            {
                #region defaults
                if (!(eo.Disassemble || eo.String || eo.Variables || eo.Functions ||
                      eo.Audio || eo.Background || eo.Decompile || eo.Font || eo.General ||
                      eo.Object || eo.Options || eo.Path || eo.Room || eo.Script ||
                      eo.Sound || eo.Sprite || eo.Texture || eo.TPag || eo.AudioGroups ||
                      eo.Shader || eo.ExportToProject || eo.Any || eo.DumpUnknownChunks ||
                      eo.DumpEmptyChunks || eo.DumpAllChunks))
                {
                    eo.Any = true;
                }

                if (eo.ExportToProject)
                {
                    eo.Disassemble = eo.String = eo.Variables = eo.Functions
                                                                    = eo.Audio = eo.Background = eo.Font = eo.General
                                                                                                               = eo.Object = eo.Options = eo.Path = eo.Room = eo.Script
                                                                                                                                                                  = eo.Sound = eo.Sprite = eo.Texture = eo.TPag = eo.AudioGroups
                                                                                                                                                                                                                      = eo.Shader = eo.DumpUnknownChunks = true;
                }
                if (eo.Any)
                {
                    eo.Disassemble = false;

                    eo.Audio = eo.Background = eo.Decompile = eo.Font = eo.General
                                                                            = eo.Object = eo.Options = eo.Path = eo.Room = eo.Script
                                                                                                                               = eo.Sound = eo.Sprite = eo.Texture = eo.TPag
                                                                                                                                                                         = eo.String = eo.Variables = eo.Functions = eo.DumpUnknownChunks
                                                                                                                                                                                                                         = eo.AudioGroups = eo.Shader = true;
                }
                #endregion

                eos   = eo;
                quiet = eo.Quiet;
                nopp  = eo.NoPrecProg;

                // ---
                #region GEN8
                if (eo.General && f.Content.General != null)
                {
                    WriteLine("Exporting manifest file...");

                    File.WriteAllText(od + "general.json", JsonMapper.ToJson(Serialize.SerializeGeneral(f.General)));
                }
                #endregion
                #region OPTN
                if (eo.Options && f.Content.Options != null)
                {
                    WriteLine("Exporting options...");

                    File.WriteAllText(od + "options.json", JsonMapper.ToJson(Serialize.SerializeOptions(f.Options)));
                }
                #endregion

                #region STRG
                if (eo.String && f.Strings != null)
                {
                    WriteLine("Dumping strings...");

                    File.WriteAllText(od + "strings.json", JsonMapper.ToJson(Serialize.SerializeStrings(f)));
                }
                #endregion
                #region VARI
                if (eo.Variables && f.RefData.Variables != null)
                {
                    WriteLine("Dumping variables...");

                    File.WriteAllText(od + "variables.json", JsonMapper.ToJson(Serialize.SerializeVars(f)));
                }
                #endregion
                #region FUNC
                if (eo.Functions && f.RefData.Functions != null)
                {
                    WriteLine("Dumping functions...");

                    File.WriteAllText(od + "functions.json", JsonMapper.ToJson(Serialize.SerializeFuncs(f)));
                }
                #endregion
                int cl = 0, ct = 0;
                #region AGRP
                if (eo.AudioGroups && f.AudioGroups != null)
                {
                    WriteLine("Dumping audio groups...");

                    File.WriteAllText(od + "audiogroups.json", JsonMapper.ToJson(Serialize.SerializeAudioGroups(f)));
                }
                if (eo.DetachedAgrp && f.AudioGroups != null)
                {
                    WriteLine("Dumping audio from detached audio groups...");

                    for (int i = 1; i < f.AudioGroups.Length; ++i)
                    {
                        WrAndGetC(DASH_ + f.AudioGroups[i] + O_PAREN + i +
                                  SLASH + f.AudioGroups.Length + C_PAREN + SPACE_S,
                                  out cl, out ct);

                        var agrpfn = Path.GetDirectoryName(file) + Path.DirectorySeparatorChar
                                     + AGRPF + i + D_DAT;
                        if (!File.Exists(agrpfn))
                        {
                            Console.Error.WriteLine("Eep: file '" + agrpfn + "' doesn't exist, skipping...");
                            continue;
                        }

                        var infoTable = new Dictionary <int, SoundInfo>();

                        for (uint iii = 0; iii < f.Sound.Length; ++iii)
                        {
                            var s = f.Sound[iii];
                            if ((s.IsEmbedded || s.IsCompressed) && s.AudioID != -1 &&
                                s.GroupID == i)
                            {
                                infoTable[s.AudioID] = s;
                            }
                        }

                        var odgrp = od + DIR_AGRP + f.AudioGroups[i];
                        if (!Directory.Exists(odgrp))
                        {
                            Directory.CreateDirectory(odgrp);
                        }

                        using (var af = GMFile.GetFile(agrpfn))
                        {
                            for (int j = 0; j < af.Audio.Length; ++j)
                            {
                                SetCAndWr(cl, ct, O_PAREN + (j + 1) + SLASH +
                                          (af.Audio.Length - 1) + C_PAREN);
                                File.WriteAllBytes(odgrp + Path.DirectorySeparatorChar
                                                   + infoTable[j].Name + SR.EXT_WAV, af.Audio[j].Wave);
                            }
                        }
                        Console.WriteLine();
                    }
                    f.AudioGroups.Clear();
                }
                #endregion

                #region TXTR
                MemoryStream[] txtrStreams = null;
                Bitmap      [] txtrBitmaps = null;
                if (eo.Texture && f.Textures != null)
                {
                    txtrStreams = new MemoryStream[f.Textures.Length];
                    txtrBitmaps = new Bitmap      [f.Textures.Length];
                    WrAndGetC("Exporting texture sheets... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_TEX))
                    {
                        Directory.CreateDirectory(od + DIR_TEX);
                    }

                    for (int i = 0; i < f.Textures.Length; i++)
                    {
                        if (f.Textures[i].PngData == null)
                        {
                            continue;
                        }

                        using (var ms = new MemoryStream(f.Textures[i].PngData))
                        {
                            txtrBitmaps[i] = new Bitmap(txtrStreams[i] = ms);
                        }

                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Textures.Length + C_PAREN);

                        File.WriteAllBytes(od + DIR_TEX + i + EXT_PNG, f.Textures[i].PngData);
                    }
                    Console.WriteLine();
                    f.Textures.Clear();
                }
                #endregion
                #region AUDO
                if (eo.Audio && f.Audio != null)
                {
                    WrAndGetC("Exporting audio files... ", out cl, out ct);

                    var infoTable = new Dictionary <int, SoundInfo>();

                    foreach (var s in f.Sound)
                    {
                        if ((s.IsEmbedded || s.IsCompressed) && s.AudioID != -1 &&
                            s.GroupID == 0)        // not from audiogroup$n.dat
                        {
                            infoTable[s.AudioID] = s;
                        }
                    }

                    if (!Directory.Exists(od + DIR_WAV))
                    {
                        Directory.CreateDirectory(od + DIR_WAV);
                    }

                    for (int i = 0; i < f.Audio.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Audio.Length + C_PAREN);

                        File.WriteAllBytes(od + DIR_WAV + infoTable[i].Name + SR.EXT_WAV, f.Audio[i].Wave);
                    }
                    Console.WriteLine();
                    f.Audio.Clear();
                }
                #endregion
                #region CODE
                if (eo.Decompile && f.Code != null)
                {
                    WrAndGetC("Decompiling code... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_CODE))
                    {
                        Directory.CreateDirectory(od + DIR_CODE);
                    }

                    for (int i = 0; i < f.Code.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Code.Length + C_PAREN);

                        try
                        {
                            File.WriteAllText(od + DIR_CODE + f.Code[i].Name + EXT_GML_LSP, Decompiler.DecompileCode(f, i, eo.AbsoluteAddresses));
                        }
                        catch (Exception e)
                        {
                            Console.Error.WriteLine($"Error: Failed to decompile {f.Code[i].Name}, ignoring...");
#if DEBUG
                            Console.Error.WriteLine(e);
#endif
                        }
                    }
                    Console.WriteLine();
                }
                if (eo.Disassemble && f.Code != null)
                {
                    WrAndGetC("Disassembling bytecode... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_CODE))
                    {
                        Directory.CreateDirectory(od + DIR_CODE);
                    }

                    for (int i = 0; i < f.Code.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Code.Length + C_PAREN);

                        File.WriteAllText(od + DIR_CODE + f.Code[i].Name + EXT_GML_ASM, Disassembler.DisplayInstructions(f, i, eo.AbsoluteAddresses));

                        /*
                         * // Dump binary code to separate files. Useful for debugging de-/re-assembly/de-/re-compilation.
                         * BinBuffer bb = new BinBuffer();
                         * for (uint j = 0; j < f.Code[i].Instructions.Length; j++)
                         * {
                         *  var instr = f.Code[i].Instructions[j];
                         *  var isize = DisasmExt.Size(instr, f.General.BytecodeVersion)*4;
                         *
                         *  bb.Write((IntPtr)instr, (int)isize);
                         * }
                         * bb.Position = 0;
                         * File.WriteAllBytes(od + DIR_CODE + f.Code[i].Name + EXT_BIN, bb.ReadBytes(bb.Size));
                         */
                    }
                    Console.WriteLine();
                }
                if (f.Code != null)
                {
                    f.Code.Clear();
                }
                #endregion

                #region SCPT
                if (eo.Script && f.Scripts != null && f.Code != null)
                {
                    WrAndGetC("Exporting scripts... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_SCR))
                    {
                        Directory.CreateDirectory(od + DIR_SCR);
                    }

                    for (int i = 0; i < f.Scripts.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Scripts.Length + C_PAREN);

                        File.WriteAllText(od + DIR_SCR + f.Scripts[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeScript(f.Scripts[i], f.Code)));
                    }
                    Console.WriteLine();
                    f.Scripts.Clear();
                }
                #endregion
                #region TPAG
                Bitmap[] tpagBitmaps = null;
                if (eo.TPag && f.TexturePages != null)
                {
                    tpagBitmaps = new Bitmap[f.TexturePages.Length];
                    WrAndGetC("Exporting texture maps... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_TXP))
                    {
                        Directory.CreateDirectory(od + DIR_TXP);
                    }

                    for (int i = 0; i < f.TexturePages.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.TexturePages.Length + C_PAREN);

                        var tpag = f.TexturePages[i];
                        File.WriteAllText(od + DIR_TXP + i + EXT_JSON,
                                          JsonMapper.ToJson(Serialize.SerializeTPag(tpag)));

                        var bc = txtrBitmaps[tpag.SpritesheetId]
                                 .Clone(new GDIRectangle(tpag.Source.X, tpag.Source.Y,
                                                         tpag.Source.Width, tpag.Source.Height),
                                        PixelFormat.DontCare);
                        tpagBitmaps[i] = bc;

                        if (eo.DumpTPagPNGs)
                        {
                            bc.Save(od + DIR_TXP + i + EXT_PNG);
                        }
                    }
                    Console.WriteLine();
                    f.TexturePages.Clear();
                }
                #endregion
                #region SPRT
                if (eo.Sprite && f.Sprites != null)
                {
                    WrAndGetC("Exporting sprites... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_SPR))
                    {
                        Directory.CreateDirectory(od + DIR_SPR);
                    }

                    for (int i = 0; i < f.Sprites.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Sprites.Length + C_PAREN);

                        File.WriteAllText(od + DIR_SPR + f.Sprites[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeSprite(f.Sprites[i])));

                        if (eo.DumpSpritePNGs)
                        {
                            for (int j = 0; j < f.Sprites[i].TextureIndices.Length; ++j)
                            {
                                uint id = f.Sprites[i].TextureIndices[j];
                                tpagBitmaps[id].Save(od + DIR_SPR + f.Sprites[i].Name + UNDERSCORE + j + EXT_PNG);
                            }
                        }
                    }
                    Console.WriteLine();
                    f.Sprites.Clear();
                }
                #endregion
                #region SOND
                if (eo.Sound && f.Sound != null)
                {
                    WrAndGetC("Exporting sounds... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_SND))
                    {
                        Directory.CreateDirectory(od + DIR_SND);
                    }

                    for (int i = 0; i < f.Sound.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Sound.Length + C_PAREN);

                        File.WriteAllText(od + DIR_SND + f.Sound[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeSound(f.Sound[i])));
                    }
                    Console.WriteLine();
                    f.Sound.Clear();
                }
                #endregion

                #region OBJT
                if (eo.Object && f.Objects != null && f.Sprites != null)
                {
                    WrAndGetC("Exporting objects... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_OBJ))
                    {
                        Directory.CreateDirectory(od + DIR_OBJ);
                    }

                    for (int i = 0; i < f.Objects.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Objects.Length + C_PAREN);

                        File.WriteAllText(od + DIR_OBJ + f.Objects[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeObj(f.Objects[i], f.Sprites, f.Objects)));
                    }
                    Console.WriteLine();
                }
                #endregion
                #region BGND
                if (eo.Background && f.Backgrounds != null)
                {
                    WrAndGetC("Exporting backgrounds... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_BG))
                    {
                        Directory.CreateDirectory(od + DIR_BG);
                    }

                    for (int i = 0; i < f.Backgrounds.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Backgrounds.Length + C_PAREN);

                        File.WriteAllText(od + DIR_BG + f.Backgrounds[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeBg(f.Backgrounds[i])));
                    }
                    Console.WriteLine();
                }
                #endregion
                #region ROOM
                if (eo.Room && f.Rooms != null)
                {
                    WrAndGetC("Exporting rooms... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_ROOM))
                    {
                        Directory.CreateDirectory(od + DIR_ROOM);
                    }

                    for (int i = 0; i < f.Rooms.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Rooms.Length + C_PAREN);

                        File.WriteAllText(od + DIR_ROOM + f.Rooms[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeRoom(f.Rooms[i], f.Backgrounds, f.Objects)));
                    }
                    Console.WriteLine();
                }
                if (f.Backgrounds != null)
                {
                    f.Backgrounds.Clear();
                }
                if (f.Objects != null)
                {
                    f.Objects.Clear();
                }
                if (f.Rooms != null)
                {
                    f.Rooms.Clear();
                }
                #endregion

                #region FONT
                if (eo.Font && f.Fonts != null)
                {
                    WrAndGetC("Exporting fonts... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_FNT))
                    {
                        Directory.CreateDirectory(od + DIR_FNT);
                    }

                    for (int i = 0; i < f.Fonts.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Fonts.Length + C_PAREN);

                        File.WriteAllText(od + DIR_FNT + f.Fonts[i].CodeName + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeFont(f.Fonts[i])));
                    }
                    Console.WriteLine();
                    f.Fonts.Clear();
                }
                #endregion
                #region PATH
                if (eo.Path && f.Paths != null)
                {
                    WrAndGetC("Exporting paths... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_PATH))
                    {
                        Directory.CreateDirectory(od + DIR_PATH);
                    }

                    for (int i = 0; i < f.Paths.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Paths.Length + C_PAREN);

                        File.WriteAllText(od + DIR_PATH + f.Paths[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializePath(f.Paths[i])));
                    }
                    Console.WriteLine();
                    f.Paths.Clear();
                }
                #endregion
                #region SHDR
                if (eo.Shader && f.Shaders != null)
                {
                    WrAndGetC("Exporting shaders... ", out cl, out ct);

                    if (!Directory.Exists(od + DIR_SHDR))
                    {
                        Directory.CreateDirectory(od + DIR_SHDR);
                    }

                    for (int i = 0; i < f.Shaders.Length; i++)
                    {
                        SetCAndWr(cl, ct, O_PAREN + (i + 1) + SLASH + f.Shaders.Length + C_PAREN);

                        File.WriteAllText(od + DIR_SHDR + f.Shaders[i].Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeShader(f.Shaders[i])));
                    }
                    Console.WriteLine();
                }
                #endregion
                List <IntPtr> chunks = null;

                if (eo.DumpUnknownChunks || eo.DumpAllChunks)
                {
                    chunks = new List <IntPtr>(6);
                    Action <IntPtr> DumpUnk = _unk =>
                    {
                        var unk = (SectionUnknown *)_unk;

                        if (unk == null || (unk->IsEmpty() && !eo.DumpEmptyChunks))
                        {
                            return;
                        }

                        WriteLine($"Dumping {unk->Header.MagicString()} chunk...");

                        var    len = unk->Header.Size;
                        byte[] buf = new byte[len];
                        uint * src = &unk->Unknown;

                        if (len != 0)
                        {
                            ILHacks.Cpblk <byte>((void *)src, buf, 0, (int)len);
                        }

                        File.WriteAllBytes(od + unk->Header.MagicString() + EXT_BIN, buf);
                    };

                    var c = f.Content;

                    if (eo.DumpAllChunks)
                    {
                        chunks.AddRange(c.Chunks.Values);
                    }

                    // TODO: how to filter out unknowns?

                    for (int i = 0; i < chunks.Count; i++)
                    {
                        DumpUnk(chunks[i]);
                    }
                }

                if (eo.ExportToProject)
                {
                    WriteLine("Emitting project file...");

                    File.WriteAllText(od + f.General.Name + EXT_JSON, JsonMapper.ToJson(Serialize.SerializeProject(f, eo, chunks)));
                }

                if (tpagBitmaps != null)
                {
                    for (int i = 0; i < tpagBitmaps.Length; ++i)
                    {
                        tpagBitmaps[i].Dispose();
                    }
                }
                if (txtrStreams != null)
                {
                    for (int i = 0; i < txtrStreams.Length; ++i)
                    {
                        txtrBitmaps[i].Dispose();
                        txtrStreams[i].Dispose();
                    }
                }
            }
        }