/// <summary> /// Writes a text entry of a Subtitle Packet to a Stream. /// </summary> /// <param name="Writer">The writer of the output Stream</param> /// <param name="PacketText">The text entry to be written</param> /// <param name="Game">The game being tampered</param> public static void ToStream(EndianBinaryWriter Writer, SubtitlePacketText PacketText, MGSGame Game) { byte[] TextBuffer = new byte[0]; if (PacketText.Text != null) { PacketText.Text = PacketText.Text.Replace("\\n", Environment.NewLine); TextBuffer = MGSText.Text2Buffer(PacketText.Text, Game); } int Length = TextBuffer.Length + 1; if ((Length & 3) != 0) { Length = (Length & ~3) + 4; } Writer.Write(PacketText.StartTime); Writer.Write(PacketText.EndTime); Writer.Write(0u); Writer.Write((ushort)(Length + 0x10)); Writer.Write((ushort)PacketText.LanguageId); Writer.Write(TextBuffer); Writer.Write((byte)0); while ((Writer.BaseStream.Position & 3) != 0) { Writer.Write((byte)0); } }
/// <summary> /// Creates a codec.dat file from a folder with the extracted data. /// </summary> /// <param name="Data">The output stream where the newly created data will be placed</param> /// <param name="InputFolder">The input folder with the extracted data</param> public static void Create(Stream Data, string InputFolder, MGSGame Game) { if (Game == MGSGame.MGS3) { MGSText.Initialize(); } BinaryWriter Writer = new BinaryWriter(Data); string[] Folders = Directory.GetDirectories(InputFolder); int CurrentFolder = 0; foreach (string Folder in Folders) { string HeaderFile = Path.Combine(Folder, "Header.bin"); string TextFile = Path.Combine(Folder, "Text.txt"); string ScriptFile = Path.Combine(Folder, "Script.bin"); if (File.Exists(HeaderFile) && File.Exists(TextFile) && File.Exists(ScriptFile)) { const uint Key = 0x4805d94d; MGSCrypto Crypto = new MGSCrypto(Key); Writer.Write(File.ReadAllBytes(HeaderFile)); Writer.Write(-1); byte[] ScriptHeader = null; uint ScriptHeaderLength = 0; if (Game == MGSGame.MGS3) { string ScriptHeaderFile = Path.Combine(Folder, "ScriptHeader.bin"); if (File.Exists(ScriptHeaderFile)) { ScriptHeader = File.ReadAllBytes(ScriptHeaderFile); ScriptHeaderLength = (uint)ScriptHeader.Length; } } using (MemoryStream TextBlock = new MemoryStream()) { BinaryWriter TextWriter = new BinaryWriter(TextBlock); string Text = File.ReadAllText(TextFile); string[] Texts = Text.Split(new string[] { TextSeparator }, StringSplitOptions.RemoveEmptyEntries); int BaseTextOffset = 0x14 + Texts.Length * 4; int TextOffset = 0; TextBlock.Seek(BaseTextOffset, SeekOrigin.Begin); for (int Index = 0; Index < Texts.Length; Index++) { TextBlock.Seek(0x14 + Index * 4, SeekOrigin.Begin); TextWriter.Write((uint)(TextOffset | 0x80000000)); TextBlock.Seek(BaseTextOffset + TextOffset, SeekOrigin.Begin); byte[] Buffer = MGSText.Text2Buffer(Texts[Index], Game); TextWriter.Write(Crypto.ProcessBuffer(Buffer)); TextOffset += Buffer.Length; } int PadIndex = 0; while ((TextBlock.Position & 3) != 0) { byte Encrypted = Crypto.ProcessByte((byte)Padding[PadIndex++]); TextBlock.WriteByte(Encrypted); } uint ScriptHeaderOffset = (uint)TextBlock.Position; uint ScriptOffset = ScriptHeaderOffset + ScriptHeaderLength; TextBlock.Seek(0, SeekOrigin.Begin); TextWriter.Write(ScriptOffset); TextWriter.Write(0x14); TextWriter.Write(BaseTextOffset); TextWriter.Write(ScriptHeaderOffset); TextWriter.Write(Key); Writer.Write(TextBlock.ToArray()); } if (ScriptHeaderLength > 0) { Writer.Write(ScriptHeader); } Writer.Write(File.ReadAllBytes(ScriptFile)); while ((Data.Position & 0xf) != 0) { Data.WriteByte(0); } } if (OnStatusChanged != null) { float Percentage = (float)++CurrentFolder / Folders.Length; OnStatusChanged(Percentage); } } }