Пример #1
0
        Stream OpenLstIndex(ArcView file, string dat_name, HibikiDatScheme scheme)
        {
            var lst_name = Path.ChangeExtension(file.Name, ".lst");

            if (VFS.FileExists(lst_name))
            {
                return(VFS.OpenStream(lst_name));
            }
            else if ("init.dat" == dat_name)
            {
                return(file.CreateStream());
            }
            // try to open 'init.dat' archive in the same directory
            var init_dat = VFS.CombinePath(VFS.GetDirectoryName(file.Name), "init.dat");

            if (!VFS.FileExists(init_dat))
            {
                return(file.CreateStream());
            }
            try
            {
                using (var init = VFS.OpenView(init_dat))
                    using (var init_arc = TryOpenWithScheme(init, ReadCount(init), scheme))
                    {
                        lst_name = Path.GetFileName(lst_name);
                        var lst_entry = init_arc.Dir.First(e => e.Name == lst_name);
                        return(init_arc.OpenEntry(lst_entry));
                    }
            }
            catch
            {
                return(file.CreateStream());
            }
        }
Пример #2
0
        ArcFile TryOpenWithScheme(ArcView file, int count, HibikiDatScheme scheme)
        {
            var dat_name = Path.GetFileName(file.Name).ToLowerInvariant();
            IList <HibikiTocRecord> toc_table = null;

            if (scheme.ArcMap != null && scheme.ArcMap.TryGetValue(dat_name, out toc_table))
            {
                if (toc_table.Count != count)
                {
                    toc_table = null;
                }
            }
            using (var input = OpenLstIndex(file, dat_name, scheme))
                using (var dec = new XoredStream(input, 0x80))
                    using (var index = new BinaryReader(dec))
                    {
                        const int name_length = 0x100;
                        int       data_offset = 2 + (name_length + 10) * count;
                        index.BaseStream.Position = 2;
                        Func <int, Entry> read_entry;
                        if (null == toc_table)
                        {
                            var name_buf = new byte[name_length];
                            read_entry = i => {
                                if (name_length != index.Read(name_buf, 0, name_length))
                                {
                                    return(null);
                                }
                                var name  = Binary.GetCString(name_buf, 0);
                                var entry = FormatCatalog.Instance.Create <Entry> (name);
                                index.ReadUInt16();
                                entry.Size   = index.ReadUInt32();
                                entry.Offset = index.ReadUInt32();
                                return(entry);
                            };
                        }
                        else
                        {
                            read_entry = i => {
                                index.BaseStream.Seek(name_length + 6, SeekOrigin.Current);
                                index.ReadUInt32(); // throws in case of EOF
                                var toc_entry = toc_table[i];
                                var entry     = FormatCatalog.Instance.Create <Entry> (toc_entry.Name);
                                entry.Offset = toc_entry.Offset;
                                entry.Size   = toc_entry.Size;
                                return(entry);
                            };
                        }
                        var dir = new List <Entry> (count);
                        for (int i = 0; i < count; ++i)
                        {
                            var entry = read_entry(i);
                            if (null == entry || string.IsNullOrWhiteSpace(entry.Name) ||
                                entry.Offset < data_offset || entry.Size > file.MaxOffset)
                            {
                                return(null);
                            }
                            dir.Add(entry);
                        }
                        return(new HibikiArchive(file, this, dir, scheme.ContentKey));
                    }
        }