示例#1
0
        /// <summary>
        ///     Reads a text entry of a Subtitle Packet from a Stream.
        /// </summary>
        /// <param name="Reader">The reader of the Stream where the data is located</param>
        /// <param name="Game">The game being tampered</param>
        /// <returns>The entry as a object</returns>
        public static SubtitlePacketText FromStream(EndianBinaryReader Reader, MGSGame Game)
        {
            SubtitlePacketText PacketText = new SubtitlePacketText();

            PacketText.StartTime = Reader.ReadUInt32();
            PacketText.EndTime   = Reader.ReadUInt32();
            uint   Dummy      = Reader.ReadUInt32();
            ushort TextLength = Reader.ReadUInt16();

            PacketText.LanguageId = Reader.ReadUInt16();

            byte[] TextBuffer = new byte[TextLength - 0x10];
            Reader.Read(TextBuffer, 0, TextBuffer.Length);
            PacketText.Text = MGSText.Buffer2Text(Unpad(TextBuffer), Game);
            PacketText.Text = PacketText.Text.Replace(Environment.NewLine, "\\n");

            return(PacketText);
        }
示例#2
0
        /// <summary>
        ///     Extracts the texts and other data inside the codec.dat file from MGS.
        /// </summary>
        /// <param name="Data">The Stream with the data to be extracted</param>
        /// <param name="OutputFolder">The output folder where the extracted data will be placed</param>
        public static void Extract(Stream Data, string OutputFolder, MGSGame Game)
        {
            if (Game == MGSGame.MGS3)
            {
                MGSText.Initialize();
            }
            BinaryReader Reader = new BinaryReader(Data);

            List <uint> AddressTable = new List <uint>();

            uint Delimiter = Reader.ReadUInt32();

            Data.Seek(0, SeekOrigin.Begin);
            while (Data.Position < Data.Length)
            {
                uint Position = (uint)Data.Position;
                uint Value    = Reader.ReadUInt32();
                if (Value == Delimiter)
                {
                    AddressTable.Add(Position);
                }
            }

            AddressTable.Add((uint)Data.Length);

            for (int Index = 0; Index < AddressTable.Count - 1; Index++)
            {
                string OutputPath = Path.Combine(OutputFolder, string.Format("Text_{0:D5}", Index));
                if (!Directory.Exists(OutputPath))
                {
                    Directory.CreateDirectory(OutputPath);
                }

                uint HeaderLength = 0;
                Data.Seek(AddressTable[Index], SeekOrigin.Begin);
                while (Reader.ReadInt32() != -1)
                {
                    HeaderLength += 4;
                }
                uint BaseOffset = (uint)Data.Position;

                uint ScriptOffset       = Reader.ReadUInt32() + BaseOffset;
                uint DialogsTableOffset = Reader.ReadUInt32() + BaseOffset;
                uint DialogsTextOffset  = Reader.ReadUInt32() + BaseOffset;
                uint ScriptHeaderOffset = Reader.ReadUInt32() + BaseOffset;
                uint Key = Reader.ReadUInt32();

                //Read header (with script pointers)
                Data.Seek(AddressTable[Index], SeekOrigin.Begin);
                byte[] Header = new byte[HeaderLength];
                Reader.Read(Header, 0, Header.Length);

                MGSCrypto     Crypto = new MGSCrypto(Key);
                StringBuilder Text   = new StringBuilder();

                //Read texts
                if (DialogsTableOffset != DialogsTextOffset)
                {
                    int  TextIndex = 0;
                    bool HasText   = true;
                    while (HasText)
                    {
                        Data.Seek(DialogsTableOffset + TextIndex++ *4, SeekOrigin.Begin);
                        uint Offset     = (Reader.ReadUInt32() & 0x7fffffff) + DialogsTextOffset;
                        uint NextOffset = (Reader.ReadUInt32() & 0x7fffffff) + DialogsTextOffset;
                        if (Data.Position > DialogsTextOffset)
                        {
                            NextOffset = ScriptHeaderOffset;
                            HasText    = false;
                        }

                        Data.Seek(Offset, SeekOrigin.Begin);
                        byte[] TextBuffer = new byte[NextOffset - Offset];
                        Reader.Read(TextBuffer, 0, TextBuffer.Length);
                        TextBuffer = UnpadText(Crypto.ProcessBuffer(TextBuffer));

                        Text.Append(MGSText.Buffer2Text(TextBuffer, Game));
                        Text.Append(TextSeparator);
                    }
                }

                if (Game == MGSGame.MGS3)
                {
                    //This is probably not a header, but I don't know what this data is, so...
                    string ScriptHeaderFile = Path.Combine(OutputPath, "ScriptHeader.bin");

                    Data.Seek(ScriptHeaderOffset, SeekOrigin.Begin);
                    uint   ScriptHeaderLength = ScriptOffset - ScriptHeaderOffset;
                    byte[] ScriptHeader       = new byte[ScriptHeaderLength];
                    Reader.Read(ScriptHeader, 0, ScriptHeader.Length);

                    File.WriteAllBytes(ScriptHeaderFile, ScriptHeader);
                }

                //Read script
                Data.Seek(ScriptOffset, SeekOrigin.Begin);
                uint   ScriptLength = AddressTable[Index + 1] - ScriptOffset;
                byte[] Script       = new byte[ScriptLength];
                Reader.Read(Script, 0, Script.Length);

                string HeaderFile = Path.Combine(OutputPath, "Header.bin");
                string TextFile   = Path.Combine(OutputPath, "Text.txt");
                string ScriptFile = Path.Combine(OutputPath, "Script.bin");

                File.WriteAllBytes(HeaderFile, Header);
                File.WriteAllText(TextFile, Text.ToString());
                File.WriteAllBytes(ScriptFile, Script);

                if (OnStatusChanged != null)
                {
                    float Percentage = (float)(Index + 1) / (AddressTable.Count - 1);
                    OnStatusChanged(Percentage);
                }
            }
        }