/// <summary> /// Inserts extracted subtitles into a movie.dat. /// </summary> /// <param name="Movie">The movie.dat file path</param> /// <param name="Input">The input folder with subtitles in XML</param> /// <param name="Game">The game being tampered (MGS3 or MGS4)</param> private static void Insert(string Movie, string Input, MGSGame Game) { string[] Files = Directory.GetFiles(Input); MGSText.Initialize(); string NewFile = Path.GetTempFileName(); FileStream In = new FileStream(Movie, FileMode.Open); FileStream Out = new FileStream(NewFile, FileMode.Create); Endian Endian = Endian.Default; switch (Game) { case MGSGame.MGSTS: Endian = Endian.Big; Game = MGSGame.MGS3; break; case MGSGame.MGS3: Endian = Endian.Little; break; case MGSGame.MGS4: Endian = Endian.Big; break; } EndianBinaryReader Reader = new EndianBinaryReader(In, Endian); EndianBinaryWriter Writer = new EndianBinaryWriter(Out, Endian); int Index = 0; int SubIndex = 0; MovieSubtitle Subtitle = GetSubtitle(Files[0]); while (In.Position < In.Length) { StreamPacket Packet = StreamPacket.FromStream(Reader, Game); switch (Packet.Type) { case PacketType.Subtitle: SubtitlePacket.ToStream(Writer, Subtitle.Subtitles[SubIndex++], Game); break; case PacketType.EndOfStream: if (++Index < Files.Length) { Subtitle = GetSubtitle(Files[Index]); } SubIndex = 0; break; } if (Packet.Type != PacketType.Subtitle) { StreamPacket.ToStream(Writer, Packet, Game); } ReportProgress((float)In.Position / In.Length); } In.Close(); Out.Close(); File.Delete(Movie); File.Move(NewFile, Movie); File.Delete(NewFile); }
/// <summary> /// Extracts the subtitles from a *.spc file to a *.xml file. /// </summary> /// <param name="Speech">The input *.spc file Stream</param> /// <param name="OutFile">The output *.xml file path</param> public static void Extract(Stream Speech, string OutFile) { SpeechSubtitle Output = new SpeechSubtitle(); EndianBinaryReader Reader = new EndianBinaryReader(Speech, Endian.Big); int Index = 0; uint HeaderOffset = GetHeaderPosition(Reader); while (Speech.Position < Speech.Length) { Speech.Seek(HeaderOffset + Index * 0x20, SeekOrigin.Begin); uint Id = Reader.ReadUInt32(); uint WaveOffset = Reader.ReadUInt32() << 11; uint WaveLength = Reader.ReadUInt32() << 11; float WaveSynchro = Reader.ReadSingle(); uint SubtitleOffset = Reader.ReadUInt32() + WaveOffset; uint SubtitleLength = Reader.ReadUInt32(); uint TableLength = Reader.ReadUInt32(); if (Id == 0 || Speech.Position >= Speech.Length) { break; } if (SubtitleLength > 0) { SpeechDialog Dialog = new SpeechDialog(); Speech.Seek(SubtitleOffset, SeekOrigin.Begin); while (true) { SubtitlePacket Subtitle = SubtitlePacket.FromStream(Reader); if (Subtitle != null) { Dialog.Subtitles.Add(Subtitle); } if (Speech.Position >= SubtitleOffset + SubtitleLength || Subtitle == null) { break; } } Output.Dialogs.Add(Dialog); } Index++; } XmlSerializerNamespaces NameSpaces = new XmlSerializerNamespaces(); NameSpaces.Add(string.Empty, string.Empty); XmlWriterSettings Settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true }; XmlSerializer Serializer = new XmlSerializer(typeof(SpeechSubtitle)); using (FileStream OutputStream = new FileStream(OutFile, FileMode.Create)) { XmlWriter Writer = XmlWriter.Create(OutputStream, Settings); Serializer.Serialize(Writer, Output, NameSpaces); } }
void ffmpegSubtitleSupport_SubtitlePopulatedEvent(SubtitleSupport sender, SubtitlePacket subtitlePacket) { MessengerInstance.Send <Message>(new Message("SubtitleInFFmpeg", subtitlePacket), TransportControlViewModel.NAME); }
/// <summary> /// Inserts the subtitles from a *.xml into a *.spc file. /// </summary> /// <param name="Speech">The output *.spc file Stream</param> /// <param name="InFile">The input *.xml file path</param> public static void Insert(Stream Speech, string InFile) { SpeechSubtitle Input; XmlSerializer Deserializer = new XmlSerializer(typeof(SpeechSubtitle)); using (FileStream InputStream = new FileStream(InFile, FileMode.Open)) { Input = (SpeechSubtitle)Deserializer.Deserialize(InputStream); } EndianBinaryReader Reader = new EndianBinaryReader(Speech, Endian.Big); using (MemoryStream Output = new MemoryStream()) { MemoryStream Header = new MemoryStream(); EndianBinaryWriter Writer = new EndianBinaryWriter(Header, Endian.Big); int Index = 0; int SubIndex = 0; long DataOffset = 0; uint HeaderOffset = GetHeaderPosition(Reader); while (Speech.Position < Speech.Length) { Speech.Seek(HeaderOffset + Index * 0x20, SeekOrigin.Begin); uint Id = Reader.ReadUInt32(); uint WaveOffset = Reader.ReadUInt32() << 11; uint WaveLength = Reader.ReadUInt32() << 11; float WaveSynchro = Reader.ReadSingle(); uint SubtitleOffset = Reader.ReadUInt32() + WaveOffset; uint SubtitleLength = Reader.ReadUInt32(); uint TableLength = Reader.ReadUInt32(); if (Id == 0 || Speech.Position >= Speech.Length) { break; } Speech.Seek(WaveOffset + 8, SeekOrigin.Begin); WaveLength = Reader.ReadUInt32(); byte[] WaveBuffer = new byte[WaveLength]; Speech.Seek(WaveOffset, SeekOrigin.Begin); Speech.Read(WaveBuffer, 0, WaveBuffer.Length); Output.Seek(DataOffset, SeekOrigin.Begin); Output.Write(WaveBuffer, 0, WaveBuffer.Length); if (SubtitleLength > 0) { SubtitleLength = 0; foreach (SubtitlePacket Subtitle in Input.Dialogs[SubIndex++].Subtitles) { byte[] SubtitleBuffer = SubtitlePacket.ToBytes(Subtitle); SubtitleLength += (uint)SubtitleBuffer.Length; Output.Write(SubtitleBuffer, 0, SubtitleBuffer.Length); } } Speech.Seek(SubtitleOffset + SubtitleLength, SeekOrigin.Begin); byte[] TableBuffer = new byte[TableLength]; Speech.Read(TableBuffer, 0, TableBuffer.Length); Output.Write(TableBuffer, 0, TableBuffer.Length); while ((Output.Position & 0x7ff) != 0) { Output.WriteByte(0); } Writer.Write(Id); Writer.Write((uint)(DataOffset >> 11)); Writer.Write((uint)((Output.Position - DataOffset) >> 11)); Writer.Write(WaveSynchro); Writer.Write(WaveLength); Writer.Write(SubtitleLength); Writer.Write(TableLength); Writer.Write(0u); DataOffset = Output.Position; Index++; } Output.Write(Header.ToArray(), 0, (int)Header.Length); while ((Output.Position & 0x7ff) != 0) { Output.WriteByte(0); } Header.Dispose(); Speech.SetLength(0); Speech.Write(Output.ToArray(), 0, (int)Output.Length); } }