示例#1
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.View.AsciiEqual(4, "PACK"))
            {
                return(null);
            }
            int length = file.View.ReadInt32(0x14);

            if (length < 0x10 || length >= file.MaxOffset)
            {
                return(null);
            }
            uint seed = file.View.ReadUInt32(8);
            var  dec  = new NekoEncryption32bit(seed);

            byte[] index = ReadBlock(file.View, dec, 0x10, out length);

            using (var reader = new IndexReader(file, dec, index, length))
            {
                var dir = reader.Parse(0x18 + length);
                if (null == dir)
                {
                    return(null);
                }
                byte[] buffer = new byte[0x10];
                reader.DetectTypes(dir, entry => {
                    file.View.Read(entry.Offset, buffer, 0, 0x10);
                    uint hash = LittleEndian.ToUInt32(buffer, 0);
                    if (0 != hash)
                    {
                        dec.Decrypt(hash, buffer, 8, 8);
                    }
                    return(LittleEndian.ToUInt32(buffer, 8));
                });
                return(new NekoArchive(file, this, dir, dec));
            }
        }
示例#2
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.View.AsciiEqual(4, "PACK"))
            {
                return(null);
            }
            int length = file.View.ReadInt32(0x14);

            if (length <= 0 || length >= file.MaxOffset)
            {
                return(null);
            }
            uint id  = file.View.ReadUInt32(8);
            var  dec = new NekoEncryption32bit(id);

            byte[] index     = ReadBlock(file.View, dec, 0x10, out length);
            long   offset    = 0x18 + length;
            var    dir       = new List <Entry>();
            int    index_pos = 0;

            for (int remaining = length; remaining > 0;)
            {
                int count = LittleEndian.ToInt32(index, index_pos + 4);
                if (count <= 0 || count > remaining / 8 - 1)
                {
                    return(null);
                }
                uint hash = LittleEndian.ToUInt32(index, index_pos);
                dir.Capacity = dir.Count + count;
                index_pos   += 8;
                for (int j = 0; j < count; ++j)
                {
                    var entry = new Entry
                    {
                        Offset = offset, Size = LittleEndian.ToUInt32(index, index_pos + 4)
                    };
                    if (!entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                    index_pos += 8;
                    offset    += entry.Size + 8;
                    dir.Add(entry);
                }
                remaining -= 8 + count * 8;
            }
            int i = 0;

            byte[] buffer = new byte[0x10];
            foreach (var entry in dir)
            {
                file.View.Read(entry.Offset, buffer, 0, 0x10);
                uint hash = LittleEndian.ToUInt32(buffer, 0);
                if (0 != hash)
                {
                    dec.Decrypt(hash, buffer, 8, 8);
                }
                uint   signature = LittleEndian.ToUInt32(buffer, 8);
                var    res       = AutoEntry.DetectFileType(signature);
                string ext       = "";
                if (null != res)
                {
                    ext        = res.Extensions.FirstOrDefault();
                    entry.Type = res.Type;
                }
                else if (0x474e4d8a == signature)
                {
                    ext = "mng";
                }
                if (!string.IsNullOrEmpty(ext))
                {
                    entry.Name = string.Format("{0:D4}.{1}", i, ext);
                }
                else
                {
                    entry.Name = i.ToString("D4");
                }
                ++i;
            }
            return(new NekoArchive(file, this, dir, dec));
        }
示例#3
0
文件: ArcNEKO.cs 项目: Casidi/GARbro
 public override ArcFile TryOpen(ArcView file)
 {
     if (!file.View.AsciiEqual (4, "PACK"))
         return null;
     int length = file.View.ReadInt32 (0x14);
     if (length <= 0 || length >= file.MaxOffset)
         return null;
     uint id = file.View.ReadUInt32 (8);
     var dec = new NekoEncryption32bit (id);
     byte[] index = ReadBlock (file.View, dec, 0x10, out length);
     long offset = 0x18 + length;
     var dir = new List<Entry>();
     int index_pos = 0;
     for (int remaining = length; remaining > 0;)
     {
         int count = LittleEndian.ToInt32 (index, index_pos+4);
         if (count <= 0 || count > remaining/8-1)
             return null;
         uint hash = LittleEndian.ToUInt32 (index, index_pos);
         dir.Capacity = dir.Count + count;
         index_pos += 8;
         for (int j = 0; j < count; ++j)
         {
             var entry = new Entry
                 { Offset = offset, Size = LittleEndian.ToUInt32 (index, index_pos+4) };
             if (!entry.CheckPlacement (file.MaxOffset))
                 return null;
             index_pos += 8;
             offset += entry.Size + 8;
             dir.Add (entry);
         }
         remaining -= 8 + count * 8;
     }
     int i = 0;
     byte[] buffer = new byte[0x10];
     foreach (var entry in dir)
     {
         file.View.Read (entry.Offset, buffer, 0, 0x10);
         uint hash = LittleEndian.ToUInt32 (buffer, 0);
         if (0 != hash)
         {
             dec.Decrypt (hash, buffer, 8, 8);
         }
         uint signature = LittleEndian.ToUInt32 (buffer, 8);
         var res = AutoEntry.DetectFileType (signature);
         string ext = "";
         if (null != res)
         {
             ext = res.Extensions.FirstOrDefault();
             entry.Type = res.Type;
         }
         else if (0x474e4d8a == signature)
             ext = "mng";
         if (!string.IsNullOrEmpty (ext))
             entry.Name = string.Format ("{0:D4}.{1}", i, ext);
         else
             entry.Name = i.ToString ("D4");
         ++i;
     }
     return new NekoArchive (file, this, dir, dec);
 }