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()); }
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())); }