protected override long WriteSubtitle(ExtendedBinaryWriter output, Subtitle subtitle, long offset, bool returnToPos) { var result = offset; var pos = output.Position; if (subtitle == null || offset == 0) { output.Write((ushort)0); } else { output.Write((ushort)offset); output.Seek(offset, SeekOrigin.Begin); output.WriteString(subtitle.Translation); result = output.Position; } if (returnToPos) { output.Seek(pos + 2, SeekOrigin.Begin); } return(result); }
public void SendDiagnostics(DiagnosticsEventKind kind, Action <ExtendedBinaryWriter> writerDelegate) { if (_communicationErrorCount > MaxCommunicationErrorCount) { return; } lock (_currentWriterLock) { if (_finished) { throw new Exception("unexpected call of " + nameof(SendDiagnostics)); } if (_currentWriter == null) { _currentWriter = new ExtendedBinaryWriter(new MemoryStream(), Encoding.UTF8); } _currentWriter.Write((byte)kind); var eventDataLengthPos = (int)_currentWriter.BaseStream.Position; _currentWriter.Write(0); var startPos = (int)_currentWriter.BaseStream.Position; _currentWriter.Write(DateTime.Now.Ticks); writerDelegate?.Invoke(_currentWriter); var endPos = (int)_currentWriter.BaseStream.Position; _currentWriter.Seek(eventDataLengthPos, SeekOrigin.Begin); _currentWriter.Write(endPos - startPos); _currentWriter.Seek(endPos, SeekOrigin.Begin); } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); System.IO.File.Copy(Path, outputPath, true); var subtitles = GetSubtitles(); using (var fs = new FileStream(outputPath, FileMode.Open)) using (var output = new ExtendedBinaryWriter(fs, FileEncoding, Endianness.BigEndian)) { foreach (var subtitle in subtitles) { if (subtitle.Offset > 0) { output.Seek(subtitle.Offset, SeekOrigin.Begin); var zeros = new byte[MAX_SIZE]; output.Write(zeros); output.Seek(subtitle.Offset, SeekOrigin.Begin); output.WriteString(subtitle.Translation); } } } }
private void WriteSubtitle(ExtendedBinaryWriter output, IList <Subtitle> subtitles, int offset) { output.Seek(offset, SeekOrigin.Begin); var zeros = new byte[64]; output.Write(zeros); WriteSubtitle(output, subtitles, offset, offset); output.Seek(offset + 64, SeekOrigin.Begin); }
protected virtual long WriteSubtitle(ExtendedBinaryWriter output, Subtitle subtitle, long offset, bool returnToPos) { var pos = output.Position; output.Seek(offset, SeekOrigin.Begin); output.WriteString(subtitle.Translation); var result = output.Position; if (returnToPos) { output.Seek(pos, SeekOrigin.Begin); } return(result); }
private void RebuildFontTable(string outputFile) { if (!System.IO.File.Exists(outputFile)) { System.IO.File.Copy(Path, outputFile); } var data = GetFontTable(); using (var fs = new FileStream(outputFile, FileMode.Open)) using (var output = new ExtendedBinaryWriter(fs, FileEncoding)) { output.Seek(FontTableOffset, SeekOrigin.Begin); for (var i = 0; i < 256; i++) { output.Write(data[i][0]); output.Write(data[i][1]); output.Write(data[i][2]); output.Write(data[i][3]); output.Write(data[i][4]); output.Write(data[i][5]); } } }
private void RebuildPatches(string outputFile) { if (!System.IO.File.Exists(outputFile)) { System.IO.File.Copy(Path, outputFile); } var data = GetPatches(); using (var fs = new FileStream(outputFile, FileMode.Open)) using (var output = new ExtendedBinaryWriter(fs, FileEncoding)) { foreach (var patch in data) { if (patch.Enabled) { foreach (var patchInfo in patch.Patches) { output.Seek(patchInfo.Item1, SeekOrigin.Begin); output.Write(patchInfo.Item2); } } } } }
private long WriteItem(ExtendedBinaryWriter output, IList <Subtitle> subtitles, ItemElement item, long outputOffset) { output.Write((ushort)outputOffset); var returnPos = output.Position; output.Seek(outputOffset, SeekOrigin.Begin); var subtitle = subtitles.First(x => x.Offset == item.Title.Offset); var currentOffset = outputOffset + 4; currentOffset = WriteSubtitle(output, subtitle, currentOffset, true); subtitle = subtitles.First(x => x.Offset == item.Description.Offset); currentOffset = WriteSubtitle(output, subtitle, currentOffset, true); output.Seek(returnPos, SeekOrigin.Begin); return(currentOffset); }
public void WriteInfo(ExtendedBinaryWriter output) { var pos = output.Position; output.WriteString(Name, 48); output.Seek(pos + 48, SeekOrigin.Begin); output.Write(Type); output.Write(DataCount); output.Write(GetSize(output.Encoding)); output.Write(0); }
private long WriteItem(ExtendedBinaryWriter output, IList <Subtitle> subtitles, DTElement item, long outputOffset) { output.Write((ushort)outputOffset); var returnPos = output.Position; output.Seek(outputOffset, SeekOrigin.Begin); output.Write(item.Id); output.Write(item.Unknown); var currentOffset = outputOffset + 2 + UnknownSize + 2 * NumStringsPerItem; foreach (var str in item.Strings) { var subtitle = subtitles.First(x => x.Offset == str.Offset); currentOffset = WriteSubtitle(output, subtitle, currentOffset, true); } output.Seek(returnPos, SeekOrigin.Begin); return(currentOffset); }
protected override long WriteSubtitle(ExtendedBinaryWriter output, IList <Subtitle> subtitles, long inputOffset, long outputOffset) { var sub = subtitles.First(x => x.Offset == inputOffset); output.Write((ushort)outputOffset); var returnPos = output.Position; var evaluator = new MatchEvaluator(SubtitleMatchEvaluator); var newSub = Regex.Replace(sub.Translation, @"<Color: (?<colorValue>[0-9A-Fa-f]{2})>", evaluator); newSub = Regex.Replace(newSub, @"<Item: (?<itemValue>[0-9A-Fa-f]{4})>", evaluator); output.Seek(outputOffset, SeekOrigin.Begin); output.WriteString(newSub); var result = output.Position; output.Seek(returnPos, SeekOrigin.Begin); return(result); }
protected override long WriteSubtitle(ExtendedBinaryWriter output, Subtitle subtitle, long offset, bool returnToPos) { var result = offset; var pos = output.Position; output.Write((ushort)offset); output.Seek(offset, SeekOrigin.Begin); if (!string.IsNullOrEmpty(subtitle.Text)) { output.WriteString(subtitle.Translation); result = output.Position; } if (returnToPos) { output.Seek(pos + 2, SeekOrigin.Begin); } return(result); }
// NOTE: This method doesn't compress the data yet. // TODO: Make a Proper Write/Save Method. public override void Save(Stream fileStream) { // HEADER var files = GetFiles(false); var writer = new ExtendedBinaryWriter(fileStream, Encoding.ASCII, true); uint dataOffset = (uint)((stringBufferSize + 16) * files.Count + 16); writer.Write((uint)files.Count); // File Count writer.Write(0x10u); // File Entry Offset writer.Write(dataOffset); // File Data Offset writer.Write(0x0u); // Unknown1 // DATA char[] stringBuffer; int length = 0; for (int i = 0; i < files.Count; ++i) { var file = files[i]; // TODO: Create a PRS Compression method in HedgeLib var compressedBytes = file.Data; // Compressed Data length = (file.Name.Length > stringBufferSize) ? stringBufferSize : file.Name.Length; stringBuffer = new char[stringBufferSize]; file.Name.CopyTo(0, stringBuffer, 0, length); writer.Write(stringBuffer); // Writes StringBuffer to stream (+0x000000) writer.Write((uint)i); // FileIndex (+0x000020) writer.Write(dataOffset); // DataOffset (+0x000024) writer.Write((uint)compressedBytes.Length); // Compressed FileSize (+0x000028) writer.Write((uint)file.Data.Length); // Uncompressed FileSize (+0x00002C) // Adds Compressed FileSize to dataOffset. dataOffset += (uint)compressedBytes.Length; // Offset to where the next file is located } // Seeks to dataOffset writer.Seek((stringBufferSize + 16) * files.Count + 16, SeekOrigin.Begin); // Writes all the compressed data for (int i = 0; i < files.Count; ++i) { // TODO: Create a PRS Compression method in HedgeLib var compressedBytes = files[i].Data; writer.Write(compressedBytes); // Compressed data } }
private long WriteItem(ExtendedBinaryWriter output, IList <Subtitle> subtitles, ShopElement item, long outputOffset) { output.Write((ushort)outputOffset); var returnPos = output.Position; output.Seek(outputOffset, SeekOrigin.Begin); output.Write(item.Id); output.Write(item.Unknown1); output.Write((ushort)0x0000); var subtitle = subtitles.First(x => x.Offset == item.Title.Offset); var currentOffset = outputOffset + 2 + 0x0C + 4; currentOffset = WriteSubtitle(output, subtitle, currentOffset, true); output.Seek(outputOffset + 2 + 0x0C, SeekOrigin.Begin); output.Write((ushort)currentOffset); output.Seek(currentOffset, SeekOrigin.Begin); output.Write(item.Unknown2); currentOffset = output.Position; output.Seek(returnPos, SeekOrigin.Begin); return(currentOffset); }
private long WriteItem(ExtendedBinaryWriter output, IList <Subtitle> subtitles, TownElement item, long outputOffset) { var returnPos = output.Position + 2; var subtitle = subtitles.First(x => x.Offset == item.Title.Offset); WriteSubtitle(output, subtitle, outputOffset, false); output.Write(item.Unknown); var currentOffset = output.Position; output.Seek(returnPos, SeekOrigin.Begin); return(currentOffset); }
public int GetTextDictionaryKey(string text) { if (text == null) { return(0); } lock (_textDictionary) { if (!_textDictionary.TryGetValue(text, out var key)) { key = _textDictionary.Count + 1; _textDictionary.Add(text, key); if (_currentDictionaryWriter == null) { _currentDictionaryWriter = new ExtendedBinaryWriter(new MemoryStream(), Encoding.UTF8); } _currentDictionaryWriter.Write((byte)DiagnosticsEventKind.TextDictionaryKeyAdded); var eventDataLengthPos = (int)_currentDictionaryWriter.BaseStream.Position; _currentDictionaryWriter.Write(0); var startPos = (int)_currentDictionaryWriter.BaseStream.Position; _currentDictionaryWriter.Write7BitEncodedInt(key); _currentDictionaryWriter.WriteNullable(text); var endPos = (int)_currentDictionaryWriter.BaseStream.Position; _currentDictionaryWriter.Seek(eventDataLengthPos, SeekOrigin.Begin); _currentDictionaryWriter.Write(endPos - startPos); _currentDictionaryWriter.Seek(endPos, SeekOrigin.Begin); } return(key); } }
private void WriteString(ExtendedBinaryWriter output, Subtitle dds, long offset) { var pos = output.Position; if (dds == null || dds.Offset == 0) { output.Write(0); } else { output.Write((int)offset); base.WriteSubtitle(output, dds, offset, false); } output.Seek(pos + 4, SeekOrigin.Begin); }
protected override long WriteSubtitle(ExtendedBinaryWriter output, Subtitle subtitle, long offset, bool returnToPos) { var result = offset; var pos = output.Position; if (subtitle == null || offset == 0) { output.Write(0); } else { output.Write((int)offset); result = base.WriteSubtitle(output, subtitle, offset, false); } if (returnToPos) { output.Seek(pos + 4, SeekOrigin.Begin); // Le añado 4 para que vuelva después de escribir el offset } return(result); }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) { output.Write(input.ReadBytes(3)); var count = input.ReadByte(); output.Write(count); output.Write(input.ReadBytes(4)); var inputPointer1 = input.ReadInt32(); var inputCountPointer1 = input.ReadInt16(); var dataPointer1 = new byte[inputCountPointer1 * 16]; if (inputCountPointer1 > 0) { input.Seek(inputPointer1, SeekOrigin.Begin); dataPointer1 = input.ReadBytes(inputCountPointer1 * 16); input.Seek(14, SeekOrigin.Begin); } output.Write(0); // Si no es 0, ya lo rellenaré luego output.Write(inputCountPointer1); var numTalkers = input.ReadInt16(); output.Write(numTalkers); var inputPointerTalkers = input.ReadInt32(); output.Write(0); // Si no es 0, ya lo rellenaré luego var inputPointerRemainder = input.ReadInt32(); output.Write(0); // Si no es 0, ya lo rellenaré luego using (var unknownMemoryStream = new MemoryStream()) using (var outputUnknown = new ExtendedBinaryWriter(unknownMemoryStream, FileEncoding, Endianness.BigEndian)) using (var propertiesMemoryStream = new MemoryStream()) using (var outputProperties = new ExtendedBinaryWriter(propertiesMemoryStream, FileEncoding, Endianness.BigEndian)) using (var stringsMemoryStream = new MemoryStream()) using (var outputStrings = new ExtendedBinaryWriter(stringsMemoryStream, FileEncoding, Endianness.BigEndian)) { var stringLengths = new List <short>(); var stringOffsets = new List <int>(); var propertiesCount = new List <byte>(); var propertiesOffsets = new List <int>(); var unknownOffsets = new List <int>(); var unknownSectionOffset = 0; var strOffset = 0; var propOffset = 0; var totalStrCount = 0; for (var i = 0; i < count; i++) { input.Seek(0x18 + i * 0x10, SeekOrigin.Begin); var unknownOffset = input.ReadInt32(); output.Write(0); // Si no es 0, ya lo rellenaré luego var groupOffset = input.ReadInt32(); output.Write(groupOffset); var unknownCount = input.ReadByte(); output.Write(unknownCount); var stringCount = input.ReadByte(); output.Write(stringCount); totalStrCount += stringCount; output.Write(input.ReadBytes(6)); if (unknownOffset != 0) { var returnPos = input.Position; input.Seek(unknownOffset, SeekOrigin.Begin); outputUnknown.Write(input.ReadBytes(unknownCount * 12)); unknownOffsets.Add(unknownSectionOffset); unknownSectionOffset = (int)outputUnknown.Position; input.Seek(returnPos, SeekOrigin.Begin); } else { unknownOffsets.Add(-1); } input.Seek(groupOffset, SeekOrigin.Begin); for (var j = 0; j < stringCount; j++) { var inputStringLength = input.ReadInt16(); var inputPropertiesCount = input.ReadByte(); var zero = input.ReadByte(); var inputStringOffset = input.ReadInt32(); var inputPropertiesOffset = input.ReadInt32(); if (inputStringLength == 0) { stringLengths.Add(0); propertiesCount.Add(inputPropertiesCount); stringOffsets.Add(strOffset); propertiesOffsets.Add(propOffset); outputStrings.WriteString(string.Empty); strOffset = (int)outputStrings.Position; var ret = input.Position; input.Seek(inputPropertiesOffset, SeekOrigin.Begin); var prop = input.ReadBytes(inputPropertiesCount * 16); input.Seek(ret, SeekOrigin.Begin); outputProperties.Write(prop); propOffset = (int)outputProperties.Position; } else { var sub = (Subtitle)subtitles.First(x => x.Offset == inputStringOffset); stringLengths.Add((short)FileEncoding.GetByteCount(sub.Translation)); propertiesCount.Add((byte)sub.TranslationProperties.Count); stringOffsets.Add(strOffset); propertiesOffsets.Add(propOffset); outputStrings.WriteString(sub.Translation); strOffset = (int)outputStrings.Position; outputProperties.Write(sub.TranslationProperties.ToByteArray()); propOffset = (int)outputProperties.Position; } } } var unknownBytes = unknownMemoryStream.ToArray(); var propertiesBytes = propertiesMemoryStream.ToArray(); var stringsBytes = stringsMemoryStream.ToArray(); var propBase = (int)output.Position + totalStrCount * 12; var unknownBase = propBase + propertiesBytes.Length; var strBase = unknownBase + unknownBytes.Length; var outputReturnPos = output.Position; for (var i = 0; i < count; i++) { output.Seek(0x18 + i * 0x10, SeekOrigin.Begin); if (unknownOffsets[i] >= 0) { output.Write(unknownOffsets[i] + unknownBase); } } output.Seek(outputReturnPos, SeekOrigin.Begin); for (var i = 0; i < totalStrCount; i++) { output.Write(stringLengths[i]); output.Write(propertiesCount[i]); output.Write((byte)0); output.Write(stringOffsets[i] + strBase); output.Write(propertiesOffsets[i] + propBase); } output.Write(propertiesBytes); if (unknownBytes.Length > 0) { output.Write(unknownBytes); } output.Write(stringsBytes); output.WritePadding(4); } if (inputPointer1 > 0) { var outputPointer1 = (int)output.Position; output.Seek(8, SeekOrigin.Begin); output.Write(outputPointer1); output.Seek(outputPointer1, SeekOrigin.Begin); output.Write(dataPointer1); } if (inputPointerTalkers > 0) { var outputPointerTalkers = (int)output.Position; output.Seek(16, SeekOrigin.Begin); output.Write(outputPointerTalkers); output.Seek(outputPointerTalkers, SeekOrigin.Begin); input.Seek(inputPointerTalkers, SeekOrigin.Begin); using (var stringsMemoryStream = new MemoryStream()) using (var outputStrings = new ExtendedBinaryWriter(stringsMemoryStream, FileEncoding, Endianness.BigEndian)) { var baseOffset = (int)output.Position + numTalkers * 4; var strOffset = baseOffset; for (var i = 0; i < numTalkers; i++) { var offset = input.ReadInt32(); var sub = subtitles.FirstOrDefault(x => x.Offset == offset); output.Write(strOffset); if (sub != null) { outputStrings.WriteString(sub.Translation); } else { outputStrings.WriteString(string.Empty); } strOffset = baseOffset + (int)outputStrings.Position; } output.Write(stringsMemoryStream.ToArray()); } } if (inputPointerRemainder > 0) { var outputPointerRemainder = (int)output.Position; output.Seek(20, SeekOrigin.Begin); output.Write(outputPointerRemainder); output.Seek(outputPointerRemainder, SeekOrigin.Begin); input.Seek(inputPointerRemainder, SeekOrigin.Begin); var data = input.ReadBytes((int)(input.Length - inputPointerRemainder)); output.Write(data); } } }
private void RebuildSubtitles(string outputFile) { var data = GetSubtitles(); if (data.Any(x => x.Text != x.Translation)) { CreateExeFile(outputFile); var peInfo = WindowsAssembly.FromFile(outputFile); using (var inputFs = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(inputFs, FileEncoding)) using (var outputFs = new FileStream(outputFile, FileMode.Open)) using (var output = new ExtendedBinaryWriter(outputFs, FileEncoding)) { var pointerSection = peInfo.GetSectionByName(PointerSectionName); var pointerSectionStart = pointerSection.Header.PointerToRawData; var pointerCount = pointerSection.GetPhysicalLength() / 8; var stringsSection = peInfo.GetSectionByName(StringsSectionName); var stringsSectionBase = (long)(peInfo.NtHeaders.OptionalHeader.ImageBase + (stringsSection.Header.VirtualAddress - stringsSection.Header.PointerToRawData)); var translationSection = peInfo.GetSectionByName(".trad\0\0\0"); var translationSectionBase = (long)(peInfo.NtHeaders.OptionalHeader.ImageBase + (translationSection.Header.VirtualAddress - translationSection.Header.PointerToRawData)); var used = new Dictionary <long, long>(); var outputOffset = (long)translationSection.Header.PointerToRawData; for (var i = 0; i < pointerCount; i++) { input.Seek(pointerSectionStart + i * 8, SeekOrigin.Begin); output.Seek(pointerSectionStart + i * 8, SeekOrigin.Begin); var value = input.ReadInt64(); if (value != 0) { var possibleStringOffset = value - stringsSectionBase; bool allowed; if (AllowedStringOffsets != null) { allowed = AllowedStringOffsets.Any(x => x.Item1 <= possibleStringOffset && x.Item2 >= possibleStringOffset); } else { allowed = (stringsSection.Header.PointerToRawData <= possibleStringOffset) && (possibleStringOffset < (stringsSection.Header.PointerToRawData + stringsSection.Header.SizeOfRawData)); } if (allowed) { var exists = used.ContainsKey(possibleStringOffset); if (exists) { output.Write(used[possibleStringOffset]); } else { var newOffset = outputOffset + translationSectionBase; output.Write(newOffset); used[possibleStringOffset] = newOffset; outputOffset = WriteSubtitle(output, data, possibleStringOffset, outputOffset); } } } } } } }
public void Save(string path) { var fourByteArray = new byte[4]; byte[] buffer = new byte[0x8000]; int size; int read = 0; if (File.Exists(path)) { File.Delete(path); } using (var w = new ExtendedBinaryWriter(File.OpenWrite(path))) { buf.Position = 0; w.Write(buf.ReadBytes((int)data_offset)); int objCount = assets.Count; long[] offsetArray = new long[objCount]; uint[] sizeArray = new uint[objCount]; for (int i = 0; i < objCount; i++) { var objInfo = assets.ElementAt(i).Value; offsetArray[i] = w.BaseStream.Position - data_offset; if (replaceDict.ContainsKey(objInfo.pathID)) { w.Write(replaceDict[objInfo.pathID]); sizeArray[i] = (uint)replaceDict[objInfo.pathID].Length; } else { buf.Position = objInfo.RealOffset; size = (int)objInfo.size; while (size > 0 && (read = buf.Read(buffer, 0, Math.Min(buffer.Length, size))) > 0) { w.Write(buffer, 0, read); size -= read; } sizeArray[i] = objInfo.size; } var pos = w.BaseStream.Position; var mod = pos % 4; if (mod != 0) { w.Write(new byte[4 - mod]); } else { w.Write(fourByteArray); } } long totalSize = w.BaseStream.Position; w.BaseStream.Position = objectsIndexOffset; for (int i = 0; i < objCount; i++) { if (format >= 14) { w.AlignStream(); w.Seek(8, SeekOrigin.Current); } else if (longObjectIDs) { w.Seek(8, SeekOrigin.Current); } else { w.Seek(4, SeekOrigin.Current); } if (format >= 22) { w.Write(offsetArray[i]); } else { w.Write((uint)offsetArray[i]); } w.Write(sizeArray[i]); w.Seek(4, SeekOrigin.Current); if (format < 16) { w.Seek(4, SeekOrigin.Current); } if (format == 15 || format == 16) { w.Seek(1, SeekOrigin.Current); } } if (format >= 22) { w.Seek(0x18, SeekOrigin.Begin); var sizeBytes = BitConverter.GetBytes(totalSize); Array.Reverse(sizeBytes); w.Write(sizeBytes); } else { w.Seek(4, SeekOrigin.Begin); var sizeBytes = BitConverter.GetBytes((uint)totalSize); Array.Reverse(sizeBytes); w.Write(sizeBytes); } } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) { output.Write(input.ReadBytes(0x08)); var count1 = input.ReadInt32(); var start1 = input.ReadInt32(); var count2 = input.ReadInt32(); var start2 = input.ReadInt32(); output.Write(count1); output.Write(start1); output.Write(count2); output.Write(start2); long outputOffset = 0x18 + 0x10 * (count1 + count2); var inputStringOffsets = new int[count1 + count2]; var inputUnknownOffsets = new int[count1 + count2]; var inputUnknownSizes = new int[count1 + count2]; for (var i = 0; i < count1 + count2; i++) { input.Seek(0x18 + 0x10 * i, SeekOrigin.Begin); input.Skip(8); inputStringOffsets[i] = input.ReadInt32(); inputUnknownOffsets[i] = input.ReadInt32(); } for (var i = 0; i < count1 + count2 - 1; i++) { inputUnknownSizes[i] = (inputStringOffsets[i + 1] - inputUnknownOffsets[i]); } inputUnknownSizes[count1 + count2 - 1] = (int)(input.Length - inputUnknownOffsets[count1 + count2 - 1]); for (var i = 0; i < count1 + count2; i++) { input.Seek(0x18 + 0x10 * i, SeekOrigin.Begin); output.Seek(0x18 + 0x10 * i, SeekOrigin.Begin); output.Write(input.ReadBytes(8)); var inputSubtitle = ReadSubtitle(input); outputOffset = WriteSubtitle(output, subtitles, inputSubtitle.Offset, outputOffset); var inputOffset = input.ReadInt32(); output.Write((int)outputOffset); input.Seek(inputOffset, SeekOrigin.Begin); output.Seek(outputOffset, SeekOrigin.Begin); output.Write(input.ReadBytes(inputUnknownSizes[i])); outputOffset += inputUnknownSizes[i]; } } }
public static void Repack(string inputFolder, string outputPath, bool useCompression) { var logFile = Path.Combine(inputFolder, "Extract_Data.tf"); var dir = Path.GetDirectoryName(outputPath); Directory.CreateDirectory(dir); using (var output = new ExtendedBinaryWriter(new FileStream(outputPath, FileMode.Create), Encoding.UTF8, Endianness.BigEndian)) using (var log = new ExtendedBinaryReader(new FileStream(logFile, FileMode.Open), Encoding.UTF8, Endianness.BigEndian)) { var numFiles = log.ReadInt32(); output.Write((short)numFiles); output.Write(log.ReadBytes(6)); var outputOffset = 0x10 + 0x10 * numFiles; for (var i = 0; i < numFiles; i++) { output.Seek(8 + i * 16, SeekOrigin.Begin); var unknown = log.ReadInt32(); output.Write(unknown); var hasMsg = log.ReadInt32() != 0; var hasRemainder = log.ReadInt32() != 0; if (hasMsg) { var msgFile = Path.Combine(inputFolder, $"{i:0000}.msg"); var msg = File.ReadAllBytes(msgFile); output.Write(outputOffset); var returnPos = output.Position; output.Seek(outputOffset, SeekOrigin.Begin); output.Write(msg); output.WritePadding(0x04); outputOffset = (int)output.Position; output.Seek(returnPos + 4, SeekOrigin.Begin); output.Write((short)msg.Length); output.Seek(-6, SeekOrigin.Current); } else { output.Write(0); output.Skip(4); output.Write((short)0); output.Seek(-6, SeekOrigin.Current); } if (hasRemainder) { var sizeRemainder = log.ReadInt32(); var remainder = log.ReadBytes(sizeRemainder); output.Write(outputOffset); var returnPos = output.Position; output.Seek(outputOffset, SeekOrigin.Begin); output.Write(remainder); output.WritePadding(0x04); outputOffset = (int)output.Position; output.Seek(returnPos + 2, SeekOrigin.Begin); output.Write((short)sizeRemainder); } else { output.Write(0); output.Skip(2); output.Write((short)0); } } } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) { input.Skip(0x38); var stringsOffset = input.ReadInt32(); input.Seek(0, SeekOrigin.Begin); output.Write(input.ReadBytes(stringsOffset)); Subtitle subtitle; var dict = new Dictionary <long, long>(subtitles.Count); while (input.Position < input.Length) { subtitle = ReadSubtitle(input); var newSubtitle = subtitles.FirstOrDefault(x => x.Offset == subtitle.Offset); if (newSubtitle != null) { dict.Add(subtitle.Offset, output.Position); output.WriteString(newSubtitle.Translation); } } input.Seek(0x10, SeekOrigin.Begin); var count1 = input.ReadInt32(); var offset1 = input.ReadInt32(); input.Skip(8); var count2 = input.ReadInt32(); var offset2 = input.ReadInt32(); input.Seek(offset1, SeekOrigin.Begin); output.Seek(offset1, SeekOrigin.Begin); for (var i = 0; i < count1; i++) { input.Skip(4); output.Skip(4); var stringOffset = input.ReadInt32(); output.Write((int)dict[stringOffset]); input.Skip(16); output.Skip(16); } input.Seek(offset2, SeekOrigin.Begin); output.Seek(offset2, SeekOrigin.Begin); for (var i = 0; i < count2; i++) { var stringOffset = input.ReadInt32(); if (dict.ContainsKey(stringOffset)) { output.Write((int)dict[stringOffset]); } else { output.Skip(4); } } } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding)) { output.Write(input.ReadBytes(0x20)); // Escribo la cabecera, aunque al final tendré que editarla output.Write(input.ReadInt32()); var stringCount1 = input.ReadInt32(); output.Write(stringCount1); var aux = input.ReadInt32(); output.Write(aux); var stringCount2 = input.ReadInt32(); output.Write(stringCount2); output.Write(input.ReadInt32()); if (aux == 3) { output.Write(input.ReadInt32()); } var language = input.ReadInt32(); output.Write(language); var base1 = input.Position; var base2 = base1 + 4 * stringCount1; var stringsBase = base2 + aux * 4 * stringCount1; var outputOffset = 0; for (var i = 0; i < stringCount1; i++) { input.Seek(base1 + 4 * i, SeekOrigin.Begin); output.Seek(base1 + 4 * i, SeekOrigin.Begin); var index1 = input.ReadInt32(); output.Write(index1); input.Seek(base2 + 4 * index1, SeekOrigin.Begin); output.Seek(base2 + 4 * index1, SeekOrigin.Begin); output.Write(input.ReadInt32()); if (aux == 3) { output.Write(input.ReadInt32()); } var strOffset = input.ReadInt32(); output.Write(outputOffset); input.Seek(stringsBase + strOffset, SeekOrigin.Begin); output.Seek(stringsBase + outputOffset, SeekOrigin.Begin); var originalSize = input.ReadInt32(); var subtitle = ReadSubtitle(input); var outputSubtitle = subtitles.FirstOrDefault(x => x.Offset == subtitle.Offset); if (outputSubtitle != null) { var translationSize = FileEncoding.GetByteCount(outputSubtitle.Translation); output.Write((int)translationSize); WriteSubtitle(output, outputSubtitle, output.Position, false); } else { output.Write(originalSize); WriteSubtitle(output, subtitle, output.Position, false); } output.WritePadding(0x04); outputOffset = (int)(output.Position - stringsBase); } output.WritePadding(0x10); var size = output.Position - 0x20; input.Seek(-0x80, SeekOrigin.End); output.Write(input.ReadBytes(0x80)); output.Seek(0x04, SeekOrigin.Begin); output.Write((int)(size + 0x60)); output.Skip(12); output.Write((int)size); } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding)) { input.Seek(0x0C, SeekOrigin.Begin); var lengthTableOffset = input.ReadInt32(); var stringOffsetTable = input.ReadInt32(); var stringBase = input.ReadInt32(); var stringOffsetTable2 = input.ReadInt32(); var stringBase2 = input.ReadInt32(); input.Seek(0x2C, SeekOrigin.Begin); var lengthCount = input.ReadInt32(); var stringCount = input.ReadInt32(); var stringCount2 = input.ReadInt32(); input.Seek(0, SeekOrigin.Begin); output.Write(input.ReadBytes(stringOffsetTable)); long outputOffset = stringBase; var lengths = new Dictionary <int, short>(); for (var i = 0; i < stringCount; i++) { input.Seek(stringOffsetTable + 4 * i, SeekOrigin.Begin); var offset = input.ReadInt32(); output.Seek(stringOffsetTable + 4 * i, SeekOrigin.Begin); output.Write((int)(outputOffset - stringBase)); output.Seek(outputOffset, SeekOrigin.Begin); var newOutputOffset = WriteSubtitle(output, subtitles, stringBase + offset, outputOffset); var length = newOutputOffset - outputOffset - 1; lengths.Add(i, (short)length); outputOffset = newOutputOffset; } output.WritePadding(0x10); var newStringBase2 = output.Position; input.Seek(stringOffsetTable2, SeekOrigin.Begin); output.Seek(stringOffsetTable2, SeekOrigin.Begin); output.Write(input.ReadBytes(stringCount2 * 4)); input.Seek(stringBase2, SeekOrigin.Begin); output.Seek(newStringBase2, SeekOrigin.Begin); output.Write(input.ReadBytes((int)(input.Length - stringBase2))); output.Seek(0x1C, SeekOrigin.Begin); output.Write((int)newStringBase2); for (var i = 0; i < lengthCount; i++) { input.Seek(lengthTableOffset + i * 16, SeekOrigin.Begin); var id = input.ReadInt32(); output.Seek(lengthTableOffset + i * 16 + 4, SeekOrigin.Begin); output.Write(lengths[id]); } } WriteBoxSizes(System.IO.Path.GetDirectoryName(outputPath), subtitles); }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) using (var tempMemoryStream = new MemoryStream()) { var offsets = new List <int>(); input.Skip(0x24); var firstStringOffset = input.ReadInt32() + 4; input.Skip(0x4); var inputLastPointer = input.ReadInt32(); input.Seek(0, SeekOrigin.Begin); output.Write(input.ReadBytes(firstStringOffset)); // Copia de la cabecera input.Seek(0x38, SeekOrigin.Begin); var pointer = input.ReadInt32(); var count = input.ReadInt32(); input.Seek(pointer, SeekOrigin.Begin); using (var temp = new ExtendedBinaryWriter(tempMemoryStream, FileEncoding, Endianness.BigEndian)) { for (var i = 0; i < count; i++) { var offset = input.ReadInt32(); if (offset == 0) { offsets.Add(0); } else { var outputOffset = WriteString(temp, subtitles, offset); offsets.Add(outputOffset); } } } var strings = tempMemoryStream.ToArray(); output.Write(strings); output.WritePadding(16); var outputOffsetsPointer = output.Position; foreach (var offset in offsets) { output.Write(offset + firstStringOffset); } var outputRemainderPointer = output.Position; output.Write(input.ReadBytes((int)(inputLastPointer - input.Position))); var outputLastPointer = output.Position; output.Write((int)(outputRemainderPointer + 8)); output.WritePadding(16); var outputTotalLength = output.Position; output.Seek(0x0C, SeekOrigin.Begin); output.Write((int)outputTotalLength); output.Seek(0x28, SeekOrigin.Begin); output.Write((int)outputRemainderPointer); output.Write((int)outputLastPointer); output.Seek(0x34, SeekOrigin.Begin); output.Write((int)(outputRemainderPointer + 4)); output.Write((int)outputOffsetsPointer); } }
public static void Repack(string inputFolder, string outputPath, bool useCompression) { var dir = Path.GetDirectoryName(outputPath); Directory.CreateDirectory(dir); var datFileName = Path.GetFileNameWithoutExtension(outputPath); var dirFile = Path.Combine(dir, $"{datFileName}.dir"); var logFile = Path.Combine(inputFolder, "Extract_Data.tf"); using (var dirOutput = new ExtendedBinaryWriter(new FileStream(dirFile, FileMode.Create), Encoding.GetEncoding(1252))) using (var datOutput = new ExtendedBinaryWriter(new FileStream(outputPath, FileMode.Create), Encoding.UTF8)) using (var log = new ExtendedBinaryReader(new FileStream(logFile, FileMode.Open), Encoding.GetEncoding(1252))) { dirOutput.Write(DIR_HEADER); datOutput.Write(DAT_HEADER); var maxNumFiles = log.ReadInt64(); dirOutput.Write(maxNumFiles); datOutput.Write(maxNumFiles); var files = ReadFileInfo(log); var compressedData = new ConcurrentDictionary <string, byte[]>(); Parallel.ForEach(files, file => { if (file.CompressedSize > 0) { var fileToInsert = Path.Combine(inputFolder, file.FileName); var data = GetData(fileToInsert, file.IsCompressed, useCompression); compressedData[file.FileName] = data; } }); var fileOffset = 0x10 + maxNumFiles * 4 + 0x04; // Posición en la que hay que empezar a insertar los ficheros for (var i = 0; i < files.Count; i++) { var file = files[i]; dirOutput.WriteString(file.FileName, 16); datOutput.Seek(0x10 + i * 4, SeekOrigin.Begin); if (file.OriginalOffset != 0) { datOutput.Write((int)fileOffset); } else { datOutput.Write(0); } if (file.CompressedSize == 0) { // Solo tiene ceros dirOutput.Write(file.CompressedSize); dirOutput.Write(file.MaxSize); dirOutput.Write(file.Unknown); dirOutput.Write(file.TimeStamp); if (file.OriginalOffset != 0) { dirOutput.Write((int)fileOffset); } else { dirOutput.Write(0); } } else { datOutput.Seek(fileOffset, SeekOrigin.Begin); var data = compressedData[file.FileName]; datOutput.Write(data); dirOutput.Write(data.Length); if (data.Length <= file.MaxSize) { dirOutput.Write(file.MaxSize); dirOutput.Write(file.Unknown); dirOutput.Write(file.TimeStamp); dirOutput.Write((int)fileOffset); fileOffset += data.Length; } else { dirOutput.Write(file.MaxSize * 2); dirOutput.Write(file.MaxSize * 2); dirOutput.Write(file.TimeStamp); dirOutput.Write((int)fileOffset); fileOffset += data.Length; } } } } }
public static byte[] Compress(byte[] uncompressedData) { using (var ms = new MemoryStream()) using (var output = new ExtendedBinaryWriter(ms, Encoding.GetEncoding(1252), Endianness.BigEndian)) { output.Write((uint)0x534c4c5a); output.Write((byte)0x00); output.Write((byte)0x01); output.Endianness = Endianness.LittleEndian; output.Write((ushort)0x0010); output.Write((uint)uncompressedData.Length); output.Write((uint)0); var uncompressedSize = uncompressedData.Length; var currentPosition = 0; var manager = new BitManager(output); var queue = new Queue <SllzItem>(); var itemsToWrite = 7; // La primera vez se escriben 7 elementos, el resto de las veces, 8 while (currentPosition < uncompressedSize) { var match = FindMatch(uncompressedData, currentPosition, true); if (!match.Found) { var item = new SllzItem { IsLiteral = true, Literal = uncompressedData[currentPosition], CopyFlags = 0 }; queue.Enqueue(item); manager.SetFlagType(FlagType.Literal); } else { manager.SetFlagType(FlagType.Copy); var copyCount = (short)((match.Length - 3) & 0x0F); var copyDistance = (short)((match.Distance - 1) << 4); var tuple = (short)(copyDistance | copyCount); var item = new SllzItem { IsLiteral = false, Literal = 0, CopyFlags = tuple }; queue.Enqueue(item); } currentPosition += match.Length; if (manager.IsByteChange) { for (var i = 0; i < itemsToWrite; i++) { var item = queue.Dequeue(); if (item.IsLiteral) { output.Write(item.Literal); } else { output.Write(item.CopyFlags); } } itemsToWrite = 8; } } manager.Flush(); if (queue.Count > 0) { while (queue.Count > 0) { var item = queue.Dequeue(); if (item.IsLiteral) { output.Write(item.Literal); } else { output.Write(item.CopyFlags); } } } var length = output.Length; output.Seek(0x0C, SeekOrigin.Begin); output.Write((uint)length); return(ms.ToArray()); } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); var used = new Dictionary <long, long>(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) { output.Write(input.ReadBytes(4)); var count = input.ReadInt32(); output.Write(count); output.Write(input.ReadBytes(8)); long outputOffset = input.PeekInt32(); for (var i = 0; i < count; i++) { var offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); var pointer = input.ReadInt32(); output.Write(pointer); var numLines = input.ReadInt32(); output.Write(numLines); offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); output.Write(input.ReadBytes(4)); offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); var pos = input.Position; input.Seek(pointer, SeekOrigin.Begin); output.Seek(pointer, SeekOrigin.Begin); for (var j = 0; j < numLines; j++) { offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); } input.Seek(pos, SeekOrigin.Begin); output.Seek(pos, SeekOrigin.Begin); output.Write(input.ReadBytes(36)); } } }