Example #1
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.View.AsciiEqual(4, "PACK"))
            {
                return(null);
            }

            uint init_key = file.View.ReadUInt32(0xC);
            var  xdec     = new NekoXCode(init_key);
            uint seed     = file.View.ReadUInt32(0x10);
            var  buffer   = file.View.ReadBytes(0x14, 8);

            xdec.Decrypt(seed, buffer, 0, 8);

            uint index_size = LittleEndian.ToUInt32(buffer, 0);

            if (index_size < 0x14 || index_size != LittleEndian.ToUInt32(buffer, 4))
            {
                return(null);
            }
            var index = new byte[(index_size + 7u) & ~7u];

            if (file.View.Read(0x1C, index, 0, index_size) < index_size)
            {
                return(null);
            }
            xdec.Decrypt(seed, index, 0, index.Length);

            using (var reader = new IndexReader(file, xdec, index, (int)index_size))
            {
                var dir = reader.Parse(0x1C + index.Length);
                if (null == dir)
                {
                    return(null);
                }
                reader.DetectTypes(dir, entry => {
                    uint key = file.View.ReadUInt32(entry.Offset);
                    file.View.Read(entry.Offset + 12, buffer, 0, 8);
                    xdec.Decrypt(key, buffer, 0, 8);
                    return(LittleEndian.ToUInt32(buffer, 0));
                });
                return(new NekoArchive(file, this, dir, xdec));
            }
        }
Example #2
0
        void DetectTypes(ArcView file, List <Entry> dir, NekoXCode dec)
        {
            byte[] buffer = new byte[8];
            foreach (var entry in dir.Where(e => string.IsNullOrEmpty(e.Type)))
            {
                if (entry.Name.EndsWith(".txt", StringComparison.InvariantCultureIgnoreCase))
                {
                    entry.Type = "script";
                    continue;
                }
                uint key = file.View.ReadUInt32(entry.Offset);
                file.View.Read(entry.Offset + 12, buffer, 0, 8);
                dec.Decrypt(key, buffer, 0, 8);
                uint   signature = LittleEndian.ToUInt32(buffer, 0);
                var    res       = AutoEntry.DetectFileType(signature);
                string ext       = "";
                if (res != null)
                {
                    ext        = res.Extensions.FirstOrDefault();
                    entry.Type = res.Type;
                }
                else if (0x474e4d8a == signature)
                {
                    ext = "mng";
                }
                else if (entry.Name.StartsWith("script/"))
                {
                    entry.Type = "script";
                }

                if (!string.IsNullOrEmpty(ext))
                {
                    entry.Name = Path.ChangeExtension(entry.Name, ext);
                }
            }
        }
Example #3
0
        void DetectTypes(ArcView file, List<Entry> dir, NekoXCode dec)
        {
            byte[] buffer = new byte[8];
            foreach (var entry in dir.Where (e => string.IsNullOrEmpty (e.Type)))
            {
                if (entry.Name.EndsWith (".txt", StringComparison.InvariantCultureIgnoreCase))
                {
                    entry.Type = "script";
                    continue;
                }
                uint key = file.View.ReadUInt32 (entry.Offset);
                file.View.Read (entry.Offset+12, buffer, 0, 8);
                dec.Decrypt (key, buffer, 0, 8);
                uint signature = LittleEndian.ToUInt32 (buffer, 0);
                var res = AutoEntry.DetectFileType (signature);
                string ext = "";
                if (res != null)
                {
                    ext = res.Extensions.FirstOrDefault();
                    entry.Type = res.Type;
                }
                else if (0x474e4d8a == signature)
                    ext = "mng";
                else if (entry.Name.StartsWith ("script/"))
                    entry.Type = "script";

                if (!string.IsNullOrEmpty (ext))
                    entry.Name = Path.ChangeExtension (entry.Name, ext);
            }
        }
Example #4
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.View.AsciiEqual(4, "PACK"))
            {
                return(null);
            }

            uint init_key = file.View.ReadUInt32(0xC);
            var  xdec     = new NekoXCode(init_key);
            uint key      = file.View.ReadUInt32(0x10);
            var  buffer   = file.View.ReadBytes(0x14, 8);

            xdec.Decrypt(key, buffer, 0, 8);

            uint index_size = LittleEndian.ToUInt32(buffer, 0);

            if (index_size != LittleEndian.ToUInt32(buffer, 4))
            {
                return(null);
            }
            var index = new byte[(index_size + 7u) & ~7u];

            if (file.View.Read(0x1C, index, 0, index_size) < index_size)
            {
                return(null);
            }
            xdec.Decrypt(key, index, 0, index.Length);

            var names_map = GetNamesMap(init_key, KnownDirNames);
            var files_map = GetNamesMap(init_key, KnownFileNames.Value);

            int  index_pos      = 0;
            var  dir            = new List <Entry>();
            long current_offset = 0x1C + index.Length;

            while (index_pos < (int)index_size)
            {
                uint dir_hash = LittleEndian.ToUInt32(index, index_pos);
                int  count    = LittleEndian.ToInt32(index, index_pos + 4);
                if (count != LittleEndian.ToInt32(index, index_pos + 8))
                {
                    break;
                }
                index_pos += 12;
                string dir_name;
                if (!names_map.TryGetValue(dir_hash, out dir_name))
                {
                    dir_name = dir_hash.ToString("X8");
                }
                dir.Capacity = dir.Count + count;
                for (int i = 0; i < count; ++i)
                {
                    uint   name_hash = LittleEndian.ToUInt32(index, index_pos);
                    uint   size      = LittleEndian.ToUInt32(index, index_pos + 4);
                    string file_name;
                    string type = "";
                    if (!files_map.TryGetValue(name_hash, out file_name))
                    {
                        file_name = name_hash.ToString("X8");
                    }
                    else
                    {
                        type = FormatCatalog.Instance.GetTypeFromName(file_name);
                    }
                    var entry = new Entry
                    {
                        Name   = string.Format("{0}/{1}", dir_name, file_name),
                        Type   = type,
                        Offset = current_offset,
                        Size   = size,
                    };
                    if (!entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                    dir.Add(entry);
                    index_pos      += 8;
                    current_offset += entry.Size;
                }
            }
            if (0 == dir.Count)
            {
                return(null);
            }
            DetectTypes(file, dir, xdec);
            return(new NekoArchive(file, this, dir, xdec));
        }
Example #5
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.View.AsciiEqual (4, "PACK"))
                return null;

            uint init_key = file.View.ReadUInt32 (0xC);
            var xdec = new NekoXCode (init_key);
            uint key = file.View.ReadUInt32 (0x10);
            var buffer = file.View.ReadBytes (0x14, 8);
            xdec.Decrypt (key, buffer, 0, 8);

            uint index_size = LittleEndian.ToUInt32 (buffer, 0);
            if (index_size != LittleEndian.ToUInt32 (buffer, 4))
                return null;
            var index = new byte[(index_size + 7u) & ~7u];
            if (file.View.Read (0x1C, index, 0, index_size) < index_size)
                return null;
            xdec.Decrypt (key, index, 0, index.Length);

            var names_map = GetNamesMap (init_key, KnownDirNames);
            var files_map = GetNamesMap (init_key, KnownFileNames.Value);

            int index_pos = 0;
            var dir = new List<Entry>();
            long current_offset = 0x1C + index.Length;
            while (index_pos < (int)index_size)
            {
                uint dir_hash = LittleEndian.ToUInt32 (index, index_pos);
                int count = LittleEndian.ToInt32 (index, index_pos+4);
                if (count != LittleEndian.ToInt32 (index, index_pos+8))
                    break;
                index_pos += 12;
                string dir_name;
                if (!names_map.TryGetValue (dir_hash, out dir_name))
                    dir_name = dir_hash.ToString ("X8");
                dir.Capacity = dir.Count + count;
                for (int i = 0; i < count; ++i)
                {
                    uint name_hash = LittleEndian.ToUInt32 (index, index_pos);
                    uint size = LittleEndian.ToUInt32 (index, index_pos+4);
                    string file_name;
                    string type = "";
                    if (!files_map.TryGetValue(name_hash, out file_name))
                        file_name = name_hash.ToString("X8");
                    else
                        type = FormatCatalog.Instance.GetTypeFromName (file_name);
                    var entry = new Entry
                    {
                        Name = string.Format ("{0}/{1}", dir_name, file_name),
                        Type = type,
                        Offset = current_offset,
                        Size = size,
                    };
                    if (!entry.CheckPlacement (file.MaxOffset))
                        return null;
                    dir.Add (entry);
                    index_pos += 8;
                    current_offset += entry.Size;
                }
            }
            if (0 == dir.Count)
                return null;
            DetectTypes (file, dir, xdec);
            return new NekoArchive (file, this, dir, xdec);
        }