private bool WriteATO1(BinaryWriterX bw) { bool result = false; try { bw.WriteASCII(ATO1.Identifier); bw.Write(ATO1.SectionSize); bw.Write(ATO1.Padding1); bw.Write(ATO1.Unknown2); result = true; } catch (Exception) { result = false; } return(result); }
private bool WriteTSY1(BinaryWriterX bw) { bool result = false; try { bw.Write(TSY1.Identifier); bw.Write(TSY1.SectionSize); bw.Write(TSY1.Unknown1); bw.Write(TSY1.Unknown2); PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return(result); }
private bool WriteLBL1(BinaryWriterX bw) { bool result = false; try { // Calculate Section Size UInt32 newSize = (UInt32)(LBL1.Unknown2.Length + LBL1.Unknown3.Length); foreach (Entry lbl in LBL1.Labels) { newSize += (UInt32)(sizeof(byte) + lbl.Value.Length + sizeof(UInt32)); } bw.Write(LBL1.Identifier); bw.Write(newSize); bw.Write(LBL1.Unknown1); bw.Write(LBL1.Unknown2); bw.Write(LBL1.Unknown3); foreach (Entry lbl in LBL1.Labels) { bw.Write(Convert.ToByte(lbl.Length)); bw.Write(lbl.Value); bw.Write(lbl.ID); } PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return(result); }
private bool WriteATR1(BinaryWriterX bw) { bool result = false; try { bw.Write(ATR1.Identifier); bw.Write(ATR1.SectionSize); bw.Write(ATR1.Unknown1); bw.Write(ATR1.NumberOfAttributes); bw.Write(ATR1.Unknown2); PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return(result); }
public static string Extract(string filename, string path, bool overwrite = true) { string result = "Files successfully extracted."; if (File.Exists(filename) && new FileInfo(filename).Length > 0) { FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None); BinaryReaderX br = new BinaryReaderX(fs); try { string magic = Encoding.ASCII.GetString(br.ReadBytes(4)); if (magic != "BG4\0") { throw new InvalidBG4Exception("The file provided is not a valid BG4 archive."); } ushort Constant1 = br.ReadUInt16(); ushort NumberOfHeaders = br.ReadUInt16(); uint SizeOfHeaders = br.ReadUInt32(); ushort NumberOfHeadersDerived = br.ReadUInt16(); ushort NumberOfHeadersMultiplier = br.ReadUInt16(); // Read in file headers List <FileEntry> entries = new List <FileEntry>(); FileEntry entry = new FileEntry(); for (int i = 0; i < NumberOfHeaders; i++) { uint offsetTemp = br.ReadUInt32(); if ((offsetTemp & 0x80000000) == 0x80000000) { entry.Compressed = true; } entry.Offset = entry.Compressed ? (offsetTemp ^ 0x80000000) : offsetTemp; entry.Size = br.ReadUInt32(); entry.Unknown1 = br.ReadUInt32(); entry.NameIndex = br.ReadUInt16(); if (entry.Unknown1 != 0xFFFFFFFF) { entries.Add(entry); } entry = new FileEntry(); } // Sort the file entries into NameIndex order entries.Sort(); // Read in file names bool eofn = false; List <string> filenames = new List <string>(); while (!eofn) { if (br.PeekString(2) == Encoding.ASCII.GetString(new byte[] { 0xFF, 0xFF })) { eofn = true; } else { bool eos = false; string name = string.Empty; while (!eos) { byte chr = br.ReadByte(); if (chr == 0x00) { eos = true; } else { name += (char)chr; } } if (name != "(invalid)") { filenames.Add(name); } } } // Extract! for (int i = 0; i < entries.Count; i++) { FileEntry fe = entries[i]; string extension = (!Regex.IsMatch(filenames[i], @"\..*?$") ? ".bin" : string.Empty); if (extension != string.Empty) { br.BaseStream.Seek(fe.Offset, SeekOrigin.Begin); magic = Encoding.ASCII.GetString(br.ReadBytes(8)); if (magic.StartsWith("MsgStdBn")) { extension = ".msbt"; } else if (magic.StartsWith("BCH")) { extension = ".bch"; } else if (magic.StartsWith("PTX")) { extension = ".ptx"; } // TODO: Add more known magic/extension pairs } Debug.Print("[" + fe.Offset.ToString("X8") + "] " + fe.NameIndex + " (" + fe.Unknown1 + ") " + filenames[i] + extension); FileInfo fi = new FileInfo(filename); FileStream fsr = new FileStream(Path.Combine(path, filenames[i] + extension), FileMode.Create, FileAccess.Write, FileShare.None); BinaryWriterX bw = new BinaryWriterX(fsr); br.BaseStream.Seek(fe.Offset, SeekOrigin.Begin); bw.Write(br.ReadBytes((int)fe.Size)); bw.Close(); } result = NumberOfHeaders + " header(s) were scanned and " + entries.Count + " files were successfully extracted!"; } catch (InvalidBG4Exception ibex) { result = ibex.Message; } catch (Exception ex) { result = ex.Message; } finally { br.Close(); } } return(result); }
private bool WriteTXT2(BinaryWriterX bw) { bool result = false; try { // Calculate Section Size UInt32 newSize = (UInt32)(TXT2.NumberOfStrings * sizeof(UInt32) + sizeof(UInt32)); for (int i = 0; i < TXT2.NumberOfStrings; i++) { foreach (Value value in TXT2.Entries[i].Values) { newSize += (UInt32)(value.Data.Length + (value.NullTerminated ? 2 : 0)); } } bw.Write(TXT2.Identifier); bw.Write(newSize); bw.Write(TXT2.Unknown1); long startOfStrings = bw.BaseStream.Position; bw.Write(TXT2.NumberOfStrings); List <UInt32> offsets = new List <UInt32>(); UInt32 offsetsLength = TXT2.NumberOfStrings * sizeof(UInt32) + sizeof(UInt32); UInt32 runningTotal = 0; for (int i = 0; i < TXT2.NumberOfStrings; i++) { offsets.Add(offsetsLength + runningTotal); foreach (Value value in TXT2.Entries[i].Values) { runningTotal += (UInt32)(value.Data.Length + (value.NullTerminated ? 2 : 0)); } } for (int i = 0; i < TXT2.NumberOfStrings; i++) { bw.Write(offsets[i]); } for (int i = 0; i < TXT2.NumberOfStrings; i++) { for (int j = 0; j < TXT2.Entries[i].Values.Count; j++) { TXT2.OriginalEntries[i].Values[j] = TXT2.Entries[i].Values[j]; } foreach (Value value in TXT2.Entries[i].Values) { if (Header.ByteOrderMark[0] == 0xFF) { bw.Write(value.Data); } else { for (int j = 0; j < value.Data.Length; j += 2) { bw.Write(value.Data[j + 1]); bw.Write(value.Data[j]); } } if (value.NullTerminated) { bw.Write('\0'); bw.Write('\0'); } } } PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return(result); }
private bool WriteTXT2(BinaryWriterX bw) { bool result = false; try { // Calculate Section Size UInt32 newSize = (UInt32)(TXT2.NumberOfStrings * sizeof(UInt32) + sizeof(UInt32)); for (int i = 0; i < TXT2.NumberOfStrings; i++) { newSize += (UInt32)((String)TXT2.Strings[i]).Value.Length; } bw.WriteASCII(TXT2.Identifier); bw.Write(newSize); bw.Write(TXT2.Padding1); long startOfStrings = bw.BaseStream.Position; bw.Write(TXT2.NumberOfStrings); List <UInt32> offsets = new List <UInt32>(); UInt32 offsetsLength = TXT2.NumberOfStrings * sizeof(UInt32) + sizeof(UInt32); UInt32 runningTotal = 0; for (int i = 0; i < TXT2.NumberOfStrings; i++) { offsets.Add(offsetsLength + runningTotal); runningTotal += (UInt32)((String)TXT2.Strings[i]).Value.Length; } for (int i = 0; i < TXT2.NumberOfStrings; i++) { bw.Write(offsets[i]); } for (int i = 0; i < TXT2.NumberOfStrings; i++) { for (int j = 0; j < TXT2.Strings.Count; j++) { TXT2.OriginalStrings[i] = TXT2.Strings[i]; } if (Header.EncodingByte == EncodingByte.UTF8) { bw.Write(((String)TXT2.Strings[i]).Value); } else { if (Header.ByteOrderMark[0] == 0xFF) { bw.Write(((String)TXT2.Strings[i]).Value); } else { for (int j = 0; j < ((String)TXT2.Strings[i]).Value.Length; j += 2) { bw.Write(((String)TXT2.Strings[i]).Value[j + 1]); bw.Write(((String)TXT2.Strings[i]).Value[j]); } } } } PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return(result); }
private bool WriteLBL1(BinaryWriterX bw) { bool result = false; try { // Calculate Section Size UInt32 newSize = sizeof(UInt32); foreach (Group grp in LBL1.Groups) { newSize += (UInt32)(sizeof(UInt32) + sizeof(UInt32)); } foreach (Label lbl in LBL1.Labels) { newSize += (UInt32)(sizeof(byte) + lbl.Name.Length + sizeof(UInt32)); } // Calculate Group Offsets UInt32 offsetsLength = LBL1.NumberOfGroups * sizeof(UInt32) * 2 + sizeof(UInt32); UInt32 runningTotal = 0; for (int i = 0; i < LBL1.Groups.Count; i++) { LBL1.Groups[i].Offset = offsetsLength + runningTotal; foreach (Label lbl in LBL1.Labels) { if (lbl.Checksum == i) { runningTotal += (UInt32)(sizeof(byte) + lbl.Name.Length + sizeof(UInt32)); } } } // Write bw.WriteASCII(LBL1.Identifier); bw.Write(newSize); bw.Write(LBL1.Padding1); bw.Write(LBL1.NumberOfGroups); foreach (Group grp in LBL1.Groups) { bw.Write(grp.NumberOfLabels); bw.Write(grp.Offset); } foreach (Group grp in LBL1.Groups) { foreach (Label lbl in LBL1.Labels) { if (lbl.Checksum == LBL1.Groups.IndexOf(grp)) { bw.Write(Convert.ToByte(lbl.Length)); bw.WriteASCII(lbl.Name); bw.Write(lbl.Index); } } } PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return(result); }
private void PaddingWrite(BinaryWriterX bw) { long remainder = bw.BaseStream.Position % 16; if (remainder > 0) for (int i = 0; i < 16 - remainder; i++) bw.Write(paddingChar); }
// Saving public bool Save() { bool result = false; try { FileStream fs = System.IO.File.Create(File.FullName); BinaryWriterX bw = new BinaryWriterX(fs); // Byte Order bw.ByteOrder = Header.ByteOrderMark[0] > Header.ByteOrderMark[1] ? ByteOrder.LittleEndian : ByteOrder.BigEndian; // Header bw.WriteASCII(Header.Identifier); bw.Write(Header.ByteOrderMark); bw.Write(Header.Unknown1); bw.Write((byte)Header.EncodingByte); bw.Write(Header.Unknown2); bw.Write(Header.NumberOfSections); bw.Write(Header.Unknown3); bw.Write(Header.FileSize); bw.Write(Header.Unknown4); foreach (string section in SectionOrder) { if (section == "LBL1") { WriteLBL1(bw); } else if (section == "NLI1") { WriteNLI1(bw); } else if (section == "ATO1") { WriteATO1(bw); } else if (section == "ATR1") { WriteATR1(bw); } else if (section == "TSY1") { WriteTSY1(bw); } else if (section == "TXT2") { WriteTXT2(bw); } Console.WriteLine("Wrote {0}", section); } // Update FileSize long fileSize = bw.BaseStream.Position; bw.BaseStream.Seek(Header.FileSizeOffset, SeekOrigin.Begin); bw.Write((UInt32)fileSize); bw.Close(); } catch (Exception) { } return(result); }
private bool WriteTXT2(BinaryWriterX bw) { bool result = false; try { // Calculate Section Size UInt32 newSize = (UInt32)(TXT2.NumberOfStrings * sizeof(UInt32) + sizeof(UInt32)); for (int i = 0; i < TXT2.NumberOfStrings; i++) { foreach (Value value in TXT2.Entries[i].Values) { newSize += (UInt32)(value.Data.Length + (value.NullTerminated ? 2 : 0)); } } bw.Write(TXT2.Identifier); bw.Write(newSize); bw.Write(TXT2.Unknown1); long startOfStrings = bw.BaseStream.Position; bw.Write(TXT2.NumberOfStrings); List<UInt32> offsets = new List<UInt32>(); UInt32 offsetsLength = TXT2.NumberOfStrings * sizeof(UInt32) + sizeof(UInt32); UInt32 runningTotal = 0; for (int i = 0; i < TXT2.NumberOfStrings; i++) { offsets.Add(offsetsLength + runningTotal); foreach (Value value in TXT2.Entries[i].Values) runningTotal += (UInt32)(value.Data.Length + (value.NullTerminated ? 2 : 0)); } for (int i = 0; i < TXT2.NumberOfStrings; i++) bw.Write(offsets[i]); for (int i = 0; i < TXT2.NumberOfStrings; i++) { for (int j = 0; j < TXT2.Entries[i].Values.Count; j++) TXT2.OriginalEntries[i].Values[j] = TXT2.Entries[i].Values[j]; foreach (Value value in TXT2.Entries[i].Values) { if (Header.ByteOrderMark[0] == 0xFF) bw.Write(value.Data); else for (int j = 0; j < value.Data.Length; j += 2) { bw.Write(value.Data[j + 1]); bw.Write(value.Data[j]); } if (value.NullTerminated) { bw.Write('\0'); bw.Write('\0'); } } } PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return result; }
private bool WriteTSY1(BinaryWriterX bw) { bool result = false; try { bw.Write(TSY1.Identifier); bw.Write(TSY1.SectionSize); bw.Write(TSY1.Unknown1); bw.Write(TSY1.Unknown2); PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return result; }
private bool WriteATR1(BinaryWriterX bw) { bool result = false; try { bw.Write(ATR1.Identifier); bw.Write(ATR1.SectionSize); bw.Write(ATR1.Unknown1); bw.Write(ATR1.NumberOfAttributes); bw.Write(ATR1.Unknown2); PaddingWrite(bw); result = true; } catch (Exception) { result = false; } return result; }
private bool WriteLBL1(BinaryWriterX bw) { bool result = false; try { // Calculate Section Size UInt32 newSize = (UInt32)(LBL1.Unknown2.Length + LBL1.Unknown3.Length); foreach (Entry lbl in LBL1.Labels) { newSize += (UInt32)(sizeof(byte) + lbl.Value.Length + sizeof(UInt32)); } bw.Write(LBL1.Identifier); bw.Write(newSize); bw.Write(LBL1.Unknown1); bw.Write(LBL1.Unknown2); bw.Write(LBL1.Unknown3); foreach (Entry lbl in LBL1.Labels) { bw.Write(Convert.ToByte(lbl.Length)); bw.Write(lbl.Value); bw.Write(lbl.Index); } PaddingWrite(bw); result = true; } catch(Exception) { result = false; } return result; }
public bool Save() { bool result = false; try { FileStream fs = System.IO.File.Create(File.FullName); BinaryWriterX bw = new BinaryWriterX(fs); // Byte Order bw.ByteOrder = Header.ByteOrderMark[0] == 0xFF ? ByteOrder.LittleEndian : ByteOrder.BigEndian; // Header bw.Write(Header.Identifier); bw.Write(Header.ByteOrderMark); bw.Write(Header.Unknown1); bw.Write(Header.Unknown2); bw.Write(Header.NumberOfSections); bw.Write(Header.Unknown3); bw.Write(Header.FileSize); bw.Write(Header.Unknown4); foreach (string section in SectionOrder) { if (section == "LBL1") WriteLBL1(bw); else if (section == "NLI1") WriteNLI1(bw); else if (section == "ATR1") WriteATR1(bw); else if (section == "TSY1") WriteTSY1(bw); else if (section == "TXT2") WriteTXT2(bw); } // Update FileSize long fileSize = bw.BaseStream.Position; bw.BaseStream.Seek(Header.FileSizeOffset, SeekOrigin.Begin); bw.Write((UInt32)fileSize); bw.Close(); } catch (Exception) { } return result; }