public void Decompress(byte[] compressed_data)
        {
            MemoryStream   stream = new MemoryStream(compressed_data);
            BinaryReaderBE reader = new BinaryReaderBE(stream);

            reader.BaseStream.Position = 8;
            UInt32 chunkCompressedSize = reader.ReadUInt32();

            reader.BaseStream.Position += 4;
            UInt32       offset      = CompressedSize - chunkCompressedSize;
            MemoryStream result      = new MemoryStream();
            BinaryWriter writer      = new BinaryWriter(result);
            long         chunkOffset = offset;

            while (reader.BaseStream.Position < offset)
            {
                UInt32 compressedSize = reader.ReadUInt32();
                reader.BaseStream.Position += 4;
                long current = reader.BaseStream.Position;
                reader.BaseStream.Position = chunkOffset;
                chunkOffset += compressedSize;
                byte[] chunkCompressedData = reader.ReadBytes((int)compressedSize);
                byte[] chunkUncompressData = ZlibDecompress(chunkCompressedData);
                writer.Write(chunkUncompressData);
                reader.BaseStream.Position = current;
            }
            reader.Close();
            writer.Close();
            UncompressedData = result.ToArray();
        }
Ejemplo n.º 2
0
        public static byte[] Decompress(byte[] input, uint offset)
        {
            MemoryStream   stream = new MemoryStream(input);
            BinaryReaderBE reader = new BinaryReaderBE(stream);

            reader.BaseStream.Position = offset;
            uint chunkCount = reader.ReadUInt32();
            long position   = reader.BaseStream.Position;
            List <CompressedChunk> totalChunk = new List <CompressedChunk>();

            for (int i = 0; i < chunkCount; i++)
            {
                reader.BaseStream.Position = position;
                uint uncompressedOffset = reader.ReadUInt32();
                uint uncompressedSize   = reader.ReadUInt32();
                uint compressedOffset   = reader.ReadUInt32();
                uint compressedSize     = reader.ReadUInt32();
                position = reader.BaseStream.Position;
                reader.BaseStream.Position = compressedOffset;
                byte[]          compressedData = reader.ReadBytes((int)compressedSize);
                CompressedChunk chunk          = new CompressedChunk(uncompressedOffset, uncompressedSize, compressedOffset, compressedSize);
                chunk.Decompress(compressedData);
                totalChunk.Add(chunk);
            }
            MemoryStream result         = new MemoryStream();
            BinaryWriter writer         = new BinaryWriter(result);
            long         unknowPosition = position;

            reader.BaseStream.Position = 0;
            writer.Write(reader.ReadBytes((int)ArchiveConfig.PackageFlagsOffset));
            writer.Write(ArchiveConfig.UncompressedFlagsBytes);
            reader.BaseStream.Position += 4;
            writer.Write(reader.ReadBytes((int)(ArchiveConfig.CompressionTypeOffset - ArchiveConfig.PackageFlagsOffset - 4)));
            writer.Write(new byte[8]);
            reader.BaseStream.Position = unknowPosition;
            writer.Write(reader.ReadBytes(8));
            position = ArchiveConfig.CompressionTypeOffset + 16;
            foreach (CompressedChunk chunk in totalChunk)
            {
                if (chunk.UncompressedOffset > position)
                {
                    long zeroes = chunk.UncompressedOffset - position;
                    writer.Write(new byte[zeroes]);
                    position = chunk.UncompressedOffset;
                }
                writer.Write(chunk.UncompressedData);
                position += chunk.UncompressedSize;
            }
            writer.Close();
            reader.Close();
            return(result.ToArray());
        }
Ejemplo n.º 3
0
        public static List <DataMessage> Decrypt(byte[] input)
        {
            List <DataMessage> result = new List <DataMessage>();
            MemoryStream       stream = new MemoryStream(input);
            BinaryReaderBE     reader = new BinaryReaderBE(stream);

            if (reader.ReadUInt32() == ArchiveConfig.Signature)
            {
                reader.BaseStream.Position = ArchiveConfig.CompressionTypeOffset;
                uint compressType = reader.ReadUInt32();
                switch (compressType)
                {
                case 0:
                    reader.BaseStream.Position = ArchiveConfig.TableOffset;

                    uint nameCount    = reader.ReadUInt32();
                    uint nameOffset   = reader.ReadUInt32();
                    uint exportCount  = reader.ReadUInt32();
                    uint exportOffset = reader.ReadUInt32();
                    uint importCount  = reader.ReadUInt32();
                    uint importOffset = reader.ReadUInt32();

                    string[] nameTable = new string[nameCount];
                    reader.BaseStream.Position = nameOffset;
                    for (int i = 0; i < nameCount; i++)
                    {
                        uint strLength = reader.ReadUInt32();
                        nameTable[i] = Encoding.UTF8.GetString(reader.ReadBytes((int)strLength - 1));
                        reader.BaseStream.Position += 9;
                    }
                    string[] nameImport = new string[importCount];
                    reader.BaseStream.Position = importOffset;
                    for (int i = 0; i < importCount; i++)
                    {
                        reader.BaseStream.Position += 20;
                        uint index = reader.ReadUInt32();
                        nameImport[i] = nameTable[(int)index];
                        reader.BaseStream.Position += 4;
                    }
                    reader.BaseStream.Position = exportOffset;
                    long current = reader.BaseStream.Position;
                    for (int i = 0; i < exportCount; i++)
                    {
                        reader.BaseStream.Position = current;
                        uint indexType = (uint)reader.ReadInt32() ^ 0xFFFFFFFF;
                        reader.BaseStream.Position += 8;
                        uint   nameIndex  = reader.ReadUInt32();
                        uint   suffixName = reader.ReadUInt32();
                        string name       = nameTable[(int)nameIndex];
                        if (suffixName != 0)
                        {
                            name += $"_{suffixName}";
                        }
                        reader.BaseStream.Position += 12;
                        uint size   = reader.ReadUInt32();
                        uint offset = reader.ReadUInt32();
                        reader.BaseStream.Position += 4;
                        if (reader.ReadUInt32() > 0)
                        {
                            reader.BaseStream.Position += 4;
                        }
                        reader.BaseStream.Position += 20;
                        current = reader.BaseStream.Position;
                        if (nameImport[indexType] == "Sqex03DataMessage")
                        {
                            reader.BaseStream.Position = offset;
                            uint           order    = reader.ReadUInt32();
                            List <Speaker> speakers = new List <Speaker>();
                            while (true)
                            {
                                string nameID = nameTable[reader.ReadInt32()];
                                if (nameID == "None")
                                {
                                    break;
                                }
                                string classID = nameTable[reader.ReadInt64()];
                                if (classID == "IntProperty")
                                {
                                    long lengthProperty = reader.ReadInt64();
                                    long intProperty    = reader.ReadInt64();
                                }
                                else if (classID == "ArrayProperty")
                                {
                                    long lengthProperty = reader.ReadInt64();
                                    if (nameID == "m_String")
                                    {
                                        DataMessage dataMessage = GetStrings(ref reader, name, false);
                                        result.Add(dataMessage);
                                    }
                                    else if (nameID == "m_Name")
                                    {
                                        DataMessage dataMessage = GetStrings(ref reader, $"{name}_Name", true);
                                        if (!string.IsNullOrWhiteSpace(string.Join("", dataMessage.Strings)))
                                        {
                                            result.Add(dataMessage);
                                        }
                                    }
                                    else if (nameID == "m_MesData")
                                    {
                                        GetSpeakers(ref reader, ref speakers, nameTable);
                                    }
                                    else
                                    {
                                        reader.BaseStream.Position += lengthProperty + 4;
                                    }
                                }
                            }
                            if (result.Any(entry => entry.Name == $"{name}_Name"))
                            {
                                DataMessage data     = result.Find(entry => entry.Name == name);
                                DataMessage dataName = result.Find(entry => entry.Name == $"{name}_Name");
                                for (int y = 0; y < speakers.Count; y++)
                                {
                                    try
                                    {
                                        speakers[y].Name = dataName.Strings[speakers[y].ID];
                                    }
                                    catch
                                    {
                                        speakers[y].Name = "";
                                    }
                                }
                                data.Speakers = speakers;
                            }
                        }
                    }
                    break;

                case 1:
                    byte[] decompressedData = Decompress(input, (uint)reader.BaseStream.Position);
                    return(Decrypt(decompressedData));

                default:
                    throw new Exception("The file has an unsupported compression type.");
                }
            }
            else
            {
                throw new Exception("The file is not a Drakengard 3 (Unreal 3) file.");
            }
            reader.Close();
            return(result);
        }
Ejemplo n.º 4
0
        private static byte[] Reimport(byte[] input, Dictionary <string, List <string> > data)
        {
            MemoryStream   result      = new MemoryStream();
            MemoryStream   inputStream = new MemoryStream(input);
            BinaryReaderBE reader      = new BinaryReaderBE(inputStream);
            BeBinaryWriter writer      = new BeBinaryWriter(result);

            if (reader.ReadUInt32() == ArchiveConfig.Signature)
            {
                reader.BaseStream.Position = ArchiveConfig.CompressionTypeOffset;
                uint compressType = reader.ReadUInt32();
                switch (compressType)
                {
                case 0:
                    reader.BaseStream.Position = ArchiveConfig.TableOffset;

                    uint     nameCount     = reader.ReadUInt32();
                    uint     nameOffset    = reader.ReadUInt32();
                    uint     exportCount   = reader.ReadUInt32();
                    uint     exportOffset  = reader.ReadUInt32();
                    uint     importCount   = reader.ReadUInt32();
                    uint     importOffset  = reader.ReadUInt32();
                    uint     emptyOffset   = reader.ReadUInt32();
                    uint     unknownOffset = reader.ReadUInt32();
                    long     emptyBytes    = unknownOffset - emptyOffset;
                    string[] nameTable     = new string[nameCount];
                    reader.BaseStream.Position = nameOffset;
                    for (int i = 0; i < nameCount; i++)
                    {
                        uint strLength = reader.ReadUInt32();
                        nameTable[i] = Encoding.UTF8.GetString(reader.ReadBytes((int)strLength - 1));
                        reader.BaseStream.Position += 9;
                    }
                    string[] nameImport = new string[importCount];
                    reader.BaseStream.Position = importOffset;
                    for (int i = 0; i < importCount; i++)
                    {
                        reader.BaseStream.Position += 20;
                        uint index = reader.ReadUInt32();
                        nameImport[i] = nameTable[(int)index];
                        reader.BaseStream.Position += 4;
                    }

                    reader.BaseStream.Position = 0;
                    writer.Write(reader.ReadBytes((int)exportOffset));     //header

                    long          bytesChanged = 0;
                    List <byte[]> newData      = new List <byte[]>();
                    long          current      = exportOffset;
                    for (int i = 0; i < exportCount; i++)
                    {
                        MemoryStream   newRealData = new MemoryStream();
                        BeBinaryWriter writerData  = new BeBinaryWriter(newRealData);
                        reader.BaseStream.Position = current;
                        long start     = reader.BaseStream.Position;
                        uint indexType = (uint)reader.ReadInt32() ^ 0xFFFFFFFF;
                        reader.BaseStream.Position += 8;
                        uint   nameIndex  = reader.ReadUInt32();
                        uint   suffixName = reader.ReadUInt32();
                        string name       = nameTable[(int)nameIndex];
                        if (suffixName != 0)
                        {
                            name += $"_{suffixName}";
                        }
                        reader.BaseStream.Position += 12;
                        uint size      = reader.ReadUInt32();
                        uint offset    = reader.ReadUInt32();
                        long newOffset = offset + bytesChanged;
                        reader.BaseStream.Position += 4;
                        if (reader.ReadUInt32() > 0)
                        {
                            reader.BaseStream.Position += 4;
                        }
                        reader.BaseStream.Position += 20;
                        long headerLength = reader.BaseStream.Position - start;
                        current = reader.BaseStream.Position;
                        reader.BaseStream.Position = offset;
                        long stringBytesChanged = 0;

                        if (nameImport[indexType] == "Sqex03DataMessage")
                        {
                            uint order = reader.ReadUInt32();
                            writerData.Write(order);
                            while (true)
                            {
                                int    nameIDIndex = reader.ReadInt32();
                                string nameID      = nameTable[nameIDIndex];
                                writerData.Write(nameIDIndex);
                                if (nameID == "None")
                                {
                                    writerData.Write(new byte[4]);
                                    break;
                                }
                                long   classIDIndex = reader.ReadInt64();
                                string classID      = nameTable[classIDIndex];
                                writerData.Write(classIDIndex);
                                if (classID == "IntProperty")
                                {
                                    writerData.Write(reader.ReadBytes(16));
                                }
                                else if (classID == "ArrayProperty")
                                {
                                    long lengthProperty = reader.ReadInt64();
                                    if (nameID == "m_String")
                                    {
                                        List <string> strings;
                                        if (data.TryGetValue(name, out strings))
                                        {
                                            byte[] temp         = WriteStrings(ref reader, strings);
                                            long   newStrLength = temp.Length - 4;
                                            writerData.Write(newStrLength);
                                            writerData.Write(temp);
                                            stringBytesChanged += newStrLength - lengthProperty;
                                        }
                                        else
                                        {
                                            writerData.Write(lengthProperty);
                                            writerData.Write(reader.ReadBytes((int)lengthProperty + 4));
                                        }
                                    }
                                    else if (nameID == "m_Name")
                                    {
                                        List <string> strings;
                                        if (data.TryGetValue($"{name}_Name", out strings))
                                        {
                                            byte[] temp         = WriteStrings(ref reader, strings);
                                            long   newStrLength = temp.Length - 4;
                                            writerData.Write(newStrLength);
                                            writerData.Write(temp);
                                            stringBytesChanged += newStrLength - lengthProperty;
                                        }
                                        else
                                        {
                                            writerData.Write(lengthProperty);
                                            writerData.Write(reader.ReadBytes((int)lengthProperty + 4));
                                        }
                                    }
                                    else
                                    {
                                        writerData.Write(lengthProperty);
                                        writerData.Write(reader.ReadBytes((int)(lengthProperty + 4)));
                                    }
                                }
                            }
                        }
                        else
                        {
                            writerData.Write(reader.ReadBytes((int)size));
                        }
                        writerData.Close();
                        newData.Add(newRealData.ToArray());
                        reader.BaseStream.Position = start;
                        writer.Write(reader.ReadBytes(32));
                        if (stringBytesChanged != 0)
                        {
                            writer.Write((uint)(size + stringBytesChanged));
                            bytesChanged += stringBytesChanged;
                            reader.BaseStream.Position += 4;
                        }
                        else
                        {
                            writer.Write(reader.ReadBytes(4));
                        }
                        writer.Write((uint)newOffset);
                        reader.BaseStream.Position += 4;
                        writer.Write(reader.ReadBytes((int)headerLength - 40));
                    }
                    writer.Write(new byte[emptyBytes]);
                    foreach (byte[] dataMessage in newData)
                    {
                        writer.Write(dataMessage);
                    }
                    writer.Write(new byte[4]);
                    break;

                case 1:
                    byte[] decompressedData = Decompress(input, (uint)reader.BaseStream.Position);
                    return(Reimport(decompressedData, data));

                default:
                    throw new Exception("The file has an unsupported compression type.");
                }
            }
            else
            {
                throw new Exception("The file is not a Drakengard 3 (Unreal 3) file.");
            }
            reader.Close();
            writer.Close();
            return(result.ToArray());
        }