예제 #1
0
파일: ArcG2.cs 프로젝트: Casidi/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());
 }
예제 #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()));
        }