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