예제 #1
0
파일: ArcG2.cs 프로젝트: tenyuhuang/GARbro
        public override Stream OpenEntry(ArcFile arc, Entry entry)
        {
            var g2ent = entry as G2Entry;

            if (null == g2ent)
            {
                return(base.OpenEntry(arc, entry));
            }

            int entry_size = (int)g2ent.Size;
            int offset     = 0;
            var decoders   = new G2Scheme[4];

            for (int i = 0; i < 4 && offset < entry_size; ++i)
            {
                decoders[i] = G2MetaScheme.CreateInstance(g2ent.Keys[i]);
                if (null != decoders[i])
                {
                    offset += EntryChunkSize;
                }
            }
            var output          = new byte[entry_size];
            var input           = new byte[EntryChunkSize];
            int current_decoder = 0;

            offset = 0;
            while (offset < entry_size)
            {
                int current_chunk_size = Math.Min(EntryChunkSize, entry_size - offset);
                if (null != decoders[current_decoder])
                {
                    arc.File.View.Read(g2ent.Offset + offset, input, 0, (uint)current_chunk_size);
                    decoders[current_decoder].Decrypt(input, 0, output, offset, current_chunk_size);
                }
                else
                {
                    arc.File.View.Read(g2ent.Offset + offset, output, offset, (uint)current_chunk_size);
                }
                current_decoder = (current_decoder + 1) & 3;
                offset         += current_chunk_size;
            }
            return(new MemoryStream(output));
        }
예제 #2
0
파일: ArcG2.cs 프로젝트: tenyuhuang/GARbro
        public override ArcFile TryOpen(ArcView file)
        {
            var header = file.View.ReadBytes(0, 0x5C);

            if (header.Length != 0x5C)
            {
                return(null);
            }
            header = HeaderEncryption.Decrypt(header);
            if (!Binary.AsciiEqual(header, "GLibArchiveData2.") || header[0x12] != 0)
            {
                return(null);
            }
            int version = header[0x11] - '0';

            if (version != 0 && version != 1)
            {
                return(null);
            }
            uint index_offset = LittleEndian.ToUInt32(header, 0x54);
            uint index_size   = LittleEndian.ToUInt32(header, 0x58);

            byte[][] encrypted_index = new byte[2][];
            encrypted_index[0] = file.View.ReadBytes(index_offset, index_size);
            if (encrypted_index[0].Length != index_size)
            {
                return(null);
            }
            encrypted_index[1] = new byte[index_size];
            uint[] keys =
            {
                LittleEndian.ToUInt32(header, 0x44),
                LittleEndian.ToUInt32(header, 0x34),
                LittleEndian.ToUInt32(header, 0x24),
                LittleEndian.ToUInt32(header, 0x14),
            };
            int i = 0;

            foreach (var key in keys)
            {
                var decoder = G2MetaScheme.CreateInstance(key);
                decoder.Decrypt(encrypted_index[i], encrypted_index[i ^ 1]);
                i ^= 1;
            }
            byte[] index = encrypted_index[i];
            if (!Binary.AsciiEqual(index, "CDBD"))
            {
                return(null);
            }
            int count          = LittleEndian.ToInt32(index, 4);
            int current_offset = 0x10;
            int info_base      = current_offset + LittleEndian.ToInt32(index, 8);
            int names_base     = current_offset + count * 0x18;
            var dir            = new List <Entry> (count);

            for (i = 0; i < count; ++i)
            {
                int name_offset = names_base + LittleEndian.ToInt32(index, current_offset);
                int parent_dir  = LittleEndian.ToInt32(index, current_offset + 8);
                int attr        = LittleEndian.ToInt32(index, current_offset + 0xC);
                var name        = Binary.GetCString(index, name_offset, info_base - name_offset);
                if (parent_dir != -1)
                {
                    name = Path.Combine(dir[parent_dir].Name, name);
                }
                var entry = new G2Entry {
                    Name = name
                };
                if (0x100 == attr)
                {
                    int info_offset = info_base + LittleEndian.ToInt32(index, current_offset + 0x10);
                    entry.Size   = LittleEndian.ToUInt32(index, info_offset + 8);
                    entry.Offset = LittleEndian.ToUInt32(index, info_offset + 0xC);
                    entry.Type   = FormatCatalog.Instance.GetTypeFromName(name);
                    for (int j = 0; j < 4; ++j)
                    {
                        info_offset  += 0x10;
                        entry.Keys[j] = LittleEndian.ToUInt32(index, info_offset);
                    }
                }
                dir.Add(entry);
                current_offset += 0x18;
            }
            return(new ArcFile(file, this, dir.Where(e => e.Offset != -1).ToList()));
        }