Пример #1
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!VFS.IsPathEqualsToFileName(file.Name, "0000.bin"))
            {
                return(null);
            }
            if ((file.MaxOffset % BitmapSize) != 0)
            {
                return(null);
            }
            int count = (int)(file.MaxOffset / BitmapSize);

            if (!IsSaneCount(count))
            {
                return(null);
            }

            uint offset = 0;
            var  dir    = new List <Entry> (count);

            for (int i = 0; i < count; ++i)
            {
                var entry = new Entry {
                    Name   = string.Format("{0:D4}.bmp", i),
                    Type   = "image",
                    Offset = offset,
                    Size   = BitmapSize,
                };
                dir.Add(entry);
                offset += BitmapSize;
            }
            return(new ArcFile(file, this, dir));
        }
Пример #2
0
        public override IImageDecoder OpenImage(ArcFile arc, Entry entry)
        {
            OrgMetaData info;

            if (VFS.IsPathEqualsToFileName(arc.File.Name, "MASK.DAT"))
            {
                info = new OrgMetaData {
                    Width  = arc.File.View.ReadUInt32(entry.Offset),
                    Height = arc.File.View.ReadUInt32(entry.Offset + 4),
                    BPP    = 8,
                    IsMask = true,
                };
            }
            else
            {
                byte has_alpha = arc.File.View.ReadByte(entry.Offset);
                byte type      = arc.File.View.ReadByte(entry.Offset + 1);
                if (has_alpha > 1 || type < 1 || type > 3)
                {
                    return(base.OpenImage(arc, entry));
                }
                info = new OrgMetaData {
                    Width    = arc.File.View.ReadUInt16(entry.Offset + 2),
                    Height   = arc.File.View.ReadUInt16(entry.Offset + 4),
                    HasAlpha = has_alpha != 0,
                    Method   = type,
                    BPP      = 32,
                };
            }
            var input = arc.File.CreateStream(entry.Offset, entry.Size);

            return(new OrgImageDecoder(input, info));
        }
Пример #3
0
        uint GetContentKey(ArcView file, List <Entry> dir, EncryptionScheme scheme)
        {
            if (null != scheme.ContentKey)
            {
                return(scheme.ContentKey.Value);
            }

            if (VFS.IsPathEqualsToFileName(file.Name, "system.arc"))
            {
                return(ReadSysenvSeed(file, dir, scheme.IndexKey));
            }
            else
            {
                var system_arc = VFS.CombinePath(VFS.GetDirectoryName(file.Name), "system.arc");
                using (var arc = VFS.OpenView(system_arc))
                {
                    var header = arc.View.ReadBytes(0, 0x30);
                    Decrypt(header, 0, scheme.IndexKey);
                    using (var arc_file = ReadIndex(arc, header, scheme))
                    {
                        return(ReadSysenvSeed(arc, arc_file.Dir, scheme.IndexKey));
                    }
                }
            }
        }
Пример #4
0
        public override ArcFile TryOpen(ArcView file)
        {
            uint key   = 0x8B6A4E5F;
            int  count = file.View.ReadInt32(4) ^ (int)key;

            if (!IsSaneCount(count))
            {
                return(null);
            }

            var scheme = QueryScheme(file.Name);

            if (null == scheme)
            {
                return(null);
            }

            bool is_script = VFS.IsPathEqualsToFileName(file.Name, "script.dat");

            using (var index = new NcIndexReader(file, count, key)
            {
                IndexPosition = 8
            })
            {
                var file_map = ReadFilenameMap(scheme);
                var dir      = index.Read(file_map);
                if (null == dir)
                {
                    return(null);
                }
                return(new ArcDatArchive(file, this, dir, scheme.Hash));
            }
        }
Пример #5
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.Name.HasExtension(".dat"))
            {
                return(null);
            }
            var cpn_name = Path.ChangeExtension(file.Name, ".cpn");

            if (!VFS.FileExists(cpn_name))
            {
                return(null);
            }
            byte   key;
            string cpn_index;

            using (var cpn = VFS.OpenView(cpn_name))
            {
                key = cpn.View.ReadByte(0);
                var cpn_data = cpn.View.ReadBytes(1, (uint)(cpn.MaxOffset - 1));
                for (int i = 0; i < cpn_data.Length; ++i)
                {
                    cpn_data[i] ^= key;
                }
                cpn_index = Encodings.cp932.GetString(cpn_data);
            }
            int idx = cpn_index.IndexOf('#', 1);

            if (idx <= 1)
            {
                return(null);
            }
            var data_name = cpn_index.Substring(1, idx - 1);

            if (!VFS.IsPathEqualsToFileName(file.Name, data_name))
            {
                return(null);
            }
            var dir   = new List <Entry>();
            var match = CpnEntryRe.Match(cpn_index, idx);

            while (match.Success)
            {
                var name  = match.Groups["name"].Value;
                var entry = FormatCatalog.Instance.Create <Entry> (name);
                entry.Offset = UInt32.Parse(match.Groups["offset"].Value);
                entry.Size   = UInt32.Parse(match.Groups["size"].Value);
                if (!entry.CheckPlacement(file.MaxOffset))
                {
                    return(null);
                }
                dir.Add(entry);
                match = match.NextMatch();
            }
            if (0 == dir.Count)
            {
                return(null);
            }
            return(new CpnArchive(file, this, dir, key));
        }
Пример #6
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!VFS.IsPathEqualsToFileName(file.Name, "gaf"))
            {
                return(null);
            }
            int count = file.View.ReadInt32(8);

            if (!IsSaneCount(count))
            {
                return(null);
            }
            uint width  = file.View.ReadUInt32(0);
            uint height = file.View.ReadUInt32(4);

            if (width == 0 || width > 0x4000 || height == 0 || height > 0x4000)
            {
                return(null);
            }
            uint offset     = 0xC;
            var  base_name  = Path.GetFileNameWithoutExtension(file.Name);
            var  dir        = new List <Entry> (count);
            uint image_size = width * height;

            for (int i = 0; i < count; ++i)
            {
                var entry = new Entry {
                    Name   = string.Format("{0}#{1:D4}", base_name, i),
                    Type   = "image",
                    Offset = offset,
                };
                if (i + 1 < count)
                {
                    uint unpacked = 0;
                    while (unpacked < image_size && offset < file.MaxOffset)
                    {
                        unpacked += file.View.ReadByte(offset + 1);
                        offset   += 2;
                    }
                }
                else
                {
                    offset = (uint)file.MaxOffset;
                }
                entry.Size = (uint)(offset - entry.Offset);
                dir.Add(entry);
            }
            var info = new ImageMetaData {
                Width = width, Height = height, BPP = 8
            };

            return(new GafArchive(file, this, dir, info));
        }
Пример #7
0
 string XmlFindArchiveKey(XmlDocument xml, string filename)
 {
     foreach (XmlNode archive in xml.DocumentElement.SelectNodes("archive[@path and @key]"))
     {
         var attr = archive.Attributes;
         var path = attr["path"].Value;
         if (VFS.IsPathEqualsToFileName(path, filename))
         {
             return(attr["key"].Value);
         }
     }
     return(null);
 }
Пример #8
0
        public override ArcFile TryOpen(ArcView file)
        {
            int count = file.View.ReadInt32(0);

            if (!IsSaneCount(count) || 8 + count * MinEntryLength >= file.MaxOffset)
            {
                return(null);
            }
            uint is_compressed = file.View.ReadUInt32(4);

            if (is_compressed > 1) // should be either 0 or 1
            {
                return(null);
            }

            var index_reader = new ArcIndexReader(file, count, is_compressed != 0);
            var scheme       = index_reader.GuessScheme(8, new int[] { 0x20, 0x18 });

            // additional checks to avoid dialog popup on false positives
            if (null == scheme && KnownSchemes.Count > 0 && file.Name.HasExtension(".arc"))
            {
                var first_entry = file.View.ReadBytes(8, 0x20);
                if (-1 == Array.FindIndex(first_entry, x => x != 0))
                {
                    return(null);
                }
                scheme = QueryScheme();
            }
            if (null == scheme)
            {
                return(null);
            }

            // special case for "instdata.arc" archives
            if (scheme.Keyword != "inst" &&
                VFS.IsPathEqualsToFileName(file.Name, "instdata.arc"))
            {
                scheme = new EncryptionScheme("inst", scheme.NameLength);
            }

            var dir = index_reader.ReadIndex(8, scheme);

            if (null == dir)
            {
                return(null);
            }
            return(new ArcFile(file, this, dir));
        }
Пример #9
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!VFS.IsPathEqualsToFileName(file.Name, "SCNPAC.DAT"))
            {
                return(null);
            }
            int count = file.View.ReadInt32(0);

            if (!IsSaneCount(count))
            {
                return(null);
            }
            uint index_size = 4 * (uint)count;

            if (index_size > file.View.Reserve(4, index_size))
            {
                return(null);
            }

            int  index_offset = 4;
            uint next_offset  = file.View.ReadUInt32(index_offset);

            if (next_offset < index_offset + index_size)
            {
                return(null);
            }
            var dir = new List <Entry> (count);

            for (int i = 0; i < count; ++i)
            {
                index_offset += 4;
                var entry = new Entry {
                    Name = i.ToString("D5"), Type = "script"
                };
                entry.Offset = next_offset;
                next_offset  = file.View.ReadUInt32(index_offset);
                if (next_offset < entry.Offset || next_offset > file.MaxOffset)
                {
                    return(null);
                }
                entry.Size = next_offset - (uint)entry.Offset;
                dir.Add(entry);
            }
            return(new ArcFile(file, this, dir));
        }
Пример #10
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.Name.HasExtension(".pb"))
            {
                return(null);
            }
            int count = file.View.ReadInt32(0);

            if (count <= 0 || count > 0xfff)
            {
                return(null);
            }
            var  dir          = new List <Entry> (count);
            int  index_offset = 0x10;
            bool is_voice     = VFS.IsPathEqualsToFileName(file.Name, "voice.pb");
            int  data_offset  = index_offset + 8 * count;

            for (int i = 0; i < count; ++i)
            {
                uint  offset = file.View.ReadUInt32(index_offset);
                Entry entry;
                if (!is_voice)
                {
                    entry = new Entry {
                        Name = i.ToString("D4"), Type = "audio", Offset = offset
                    }
                }
                ;
                else
                {
                    entry = new Entry {
                        Name = string.Format("{0:D4}.pb", i), Type = "archive", Offset = offset
                    }
                };
                entry.Size = file.View.ReadUInt32(index_offset + 4);
                if (offset < data_offset || !entry.CheckPlacement(file.MaxOffset))
                {
                    return(null);
                }
                dir.Add(entry);
                index_offset += 8;
            }
            return(new ArcFile(file, this, dir));
        }
    }
Пример #11
0
        static public RioReader Create(ArcView file)
        {
            if (CRioArchive.RioSignature == file.View.ReadUInt32(0))
            {
                return(new RioReader(file));
            }

            if (file.Name.HasExtension(".ici"))
            {
                return(null);
            }
            var ici_name = file.Name + ".ici";

            if (!VFS.FileExists(ici_name))
            {
                ici_name = Path.ChangeExtension(file.Name, ".ici");
                if (!VFS.FileExists(ici_name))
                {
                    return(null);
                }
            }
            byte[] ici_data;
            using (var ici = VFS.OpenBinaryStream(ici_name))
                ici_data = ReadIci(ici, IciKey);

            CObjectArcMan arc_man;

            using (var ici = new BinMemoryStream(ici_data))
            {
                var rio = new CRioArchive(ici);
                arc_man = rio.DeserializeRoot() as CObjectArcMan;
                if (null == arc_man)
                {
                    return(null);
                }
            }
            var arc_object = arc_man.ArcList.FirstOrDefault();

            if (null == arc_object || !VFS.IsPathEqualsToFileName(file.Name, arc_object.RioName))
            {
                return(null);
            }
            return(new RioReader(arc_man, file));
        }
Пример #12
0
        public override ArcFile TryOpen(ArcView file)
        {
            // enforce extension to avoid false positives
            if (!file.Name.HasExtension(".awf"))
            {
                return(null);
            }
            int count = file.View.ReadInt32(0);

            if (!IsSaneCount(count))
            {
                return(null);
            }
            uint index_offset = 4;
            uint index_size   = (uint)count * 0x34;

            if (index_size > file.View.Reserve(index_offset, index_size))
            {
                return(null);
            }

            // rather loose criterion, haven't found anything better yet.
            bool is_mp3 = VFS.IsPathEqualsToFileName(file.Name, "voice.awf");
            var  dir    = new List <Entry> (count);

            for (int i = 0; i < count; ++i)
            {
                var name = file.View.ReadString(index_offset, 0x20);
                if (is_mp3)
                {
                    name = Path.ChangeExtension(name, "mp3");
                }
                var entry = FormatCatalog.Instance.Create <Entry> (name);
                entry.Offset = file.View.ReadUInt32(index_offset + 0x20);
                entry.Size   = file.View.ReadUInt32(index_offset + 0x24);
                if (!entry.CheckPlacement(file.MaxOffset))
                {
                    return(null);
                }
                dir.Add(entry);
                index_offset += 0x34;
            }
            return(new ArcFile(file, this, dir));
        }
Пример #13
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.View.AsciiEqual(0, "BinaryCombineData"))
            {
                return(null);
            }
            var bcl_name = Path.ChangeExtension(file.Name, "bcl");

            using (var bcl = VFS.OpenStream(bcl_name))
                using (var index = new StreamReader(bcl, Encodings.cp932))
                {
                    if (index.ReadLine() != "[BinaryCombineData]")
                    {
                        return(null);
                    }
                    var filename = index.ReadLine();
                    if (!VFS.IsPathEqualsToFileName(file.Name, filename))
                    {
                        return(null);
                    }
                    index.ReadLine();
                    var dir = new List <Entry>();
                    while ((filename = index.ReadLine()) != null)
                    {
                        if (!filename.StartsWith("[") || !filename.EndsWith("]"))
                        {
                            return(null);
                        }
                        filename = filename.Substring(1, filename.Length - 2);
                        var offset = index.ReadLine();
                        var size   = index.ReadLine();
                        index.ReadLine();
                        var entry = Create <Entry> (filename);
                        entry.Offset = UInt32.Parse(offset);
                        entry.Size   = UInt32.Parse(size);
                        if (!entry.CheckPlacement(file.MaxOffset))
                        {
                            return(null);
                        }
                        dir.Add(entry);
                    }
                    return(new ArcFile(file, this, dir));
                }
        }
Пример #14
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!VFS.IsPathEqualsToFileName(file.Name, "data.dsm") ||
                (file.View.ReadUInt32(0) & 0xFFFFFF) != 0xBFBBEF)     // UTF-8 BOM
            {
                return(null);
            }

            var dir = new List <Entry> {
                new Entry {
                    Name   = "data.txt",
                    Type   = "script",
                    Offset = 0,
                    Size   = (uint)file.MaxOffset / 4 * 3,
                }
            };

            return(new ArcFile(file, this, dir));
        }
Пример #15
0
        public override IImageDecoder OpenImage(ArcFile arc, Entry entry)
        {
            var aent = entry as AssetEntry;

            if (null == aent || aent.AssetObject.TypeName != "Texture2D")
            {
                return(base.OpenImage(arc, entry));
            }
            var uarc    = (UnityBundle)arc;
            var obj     = aent.AssetObject;
            var bundles = new BundleStream(uarc.File, uarc.Segments);
            var input   = new StreamRegion(bundles, obj.Offset, obj.Size);
            var reader  = new AssetReader(input, entry.Name);

            reader.SetupReaders(obj.Asset);
            Texture2D tex  = null;
            var       type = obj.Type;

            if (type != null && type.Children.Any(t => t.Type == "StreamingInfo"))
            {
                var fields = obj.Deserialize(reader);
                tex = new Texture2D();
                tex.Import(fields);
                var info = fields["m_StreamData"] as StreamingInfo;
                if (info != null)
                {
                    var bundle = uarc.Bundles.FirstOrDefault(b => VFS.IsPathEqualsToFileName(info.Path, b.Name));
                    if (bundle != null)
                    {
                        tex.m_DataLength = (int)info.Size;
                        input            = new StreamRegion(bundles, bundle.Offset + info.Offset, info.Size);
                        reader           = new AssetReader(input, entry.Name);
                    }
                }
            }
            if (null == tex)
            {
                tex = new Texture2D();
                tex.Load(reader);
            }
            return(new Texture2DDecoder(tex, reader));
        }
Пример #16
0
        void DetectFileTypes(List <Entry> dir, ArcView file)
        {
            bool is_mask = VFS.IsPathEqualsToFileName(file.Name, "MASK.DAT");
            var  buffer  = new byte[0x11];

            foreach (var entry in dir)
            {
                file.View.Read(entry.Offset, buffer, 0, 0x11);
                if (buffer.AsciiEqual(0xD, "OggS"))
                {
                    entry.ChangeType(OggAudio.Instance);
                    entry.Offset += 0xD;
                    entry.Size   -= 0xD;
                }
                else if (is_mask || buffer[0] <= 1 && buffer[1] > 0 && buffer[1] <= 3)
                {
                    entry.Type = "image";
                }
            }
        }
Пример #17
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!VFS.IsPathEqualsToFileName(file.Name, "CG") || file.MaxOffset <= DefaultDataOffset)
            {
                return(null);
            }
            uint index_pos = 0;
            var  dir       = new List <Entry>();

            while (index_pos < DefaultDataOffset)
            {
                if (file.View.ReadByte(index_pos) == 0)
                {
                    break;
                }
                var name = file.View.ReadString(index_pos, 0x20);
                if (string.IsNullOrWhiteSpace(name))
                {
                    return(null);
                }
                var entry = Create <CgEntry> (name);
                entry.Offset = file.View.ReadUInt32(index_pos + 0x20) + DefaultDataOffset;
                entry.Size   = file.View.ReadUInt32(index_pos + 0x2C);
                if (!entry.CheckPlacement(file.MaxOffset))
                {
                    return(null);
                }
                entry.Info = new ImageMetaData {
                    Width  = file.View.ReadUInt32(index_pos + 0x24),
                    Height = file.View.ReadUInt32(index_pos + 0x28),
                    BPP    = 8,
                };
                dir.Add(entry);
                index_pos += 0x30;
            }
            if (0 == dir.Count)
            {
                return(null);
            }
            return(new ArcFile(file, this, dir));
        }
Пример #18
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (file.MaxOffset > uint.MaxValue ||
                !VFS.IsPathEqualsToFileName(file.Name, "ArchPac.dat"))
            {
                return(null);
            }
            foreach (var scheme in KnownSchemes.Values.Where(s => s.IndexOffset < file.MaxOffset).OrderBy(s => s.IndexOffset))
            {
                var dir = ReadIndex(file, scheme.IndexOffset, file.MaxOffset);
                if (dir != null)
                {
                    if (scheme.EventMap != null)
                    {
                        return(new SeraphArchive(file, this, dir, scheme));
                    }
                    else
                    {
                        return(new ArcFile(file, this, dir));
                    }
                }
            }
            var scnpac_name = VFS.ChangeFileName(file.Name, "ScnPac.dat");

            if (!VFS.FileExists(scnpac_name))
            {
                return(null);
            }
            using (var scnpac = VFS.OpenView(scnpac_name))
            {
                uint first_offset = scnpac.View.ReadUInt32(4);
                uint index_offset = scnpac.View.ReadUInt32(first_offset - 4);
                var  dir          = ReadIndex(scnpac, index_offset, file.MaxOffset);
                if (dir != null)
                {
                    return(new ArcFile(file, this, dir));
                }
            }
            return(null);
        }
Пример #19
0
        public override ArcFile TryOpen(ArcView file)
        {
            uint key   = 0x8B6A4E5F;
            int  count = file.View.ReadInt32(4) ^ (int)key;

            if (!IsSaneCount(count))
            {
                return(null);
            }

            var scheme = QueryScheme(file.Name);

            if (null == scheme)
            {
                return(null);
            }

            bool is_script = VFS.IsPathEqualsToFileName(file.Name, "script.dat");

            var dir = new List <Entry> (count);

            using (var input = file.CreateStream(8, (uint)count * 0x15))
            {
                foreach (var entry in ReadIndex(input, count, scheme, key))
                {
                    if (!entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                    if (is_script)
                    {
                        entry.Hash ^= scheme.Hash;
                    }
                    dir.Add(entry);
                }
            }
            return(new ArcFile(file, this, dir));
        }
Пример #20
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.Name.HasExtension(".dat") || VFS.IsPathEqualsToFileName(file.Name, "00000000.dat"))
            {
                return(null);
            }
            var index_name = VFS.ChangeFileName(file.Name, "00000000.dat");

            if (!VFS.FileExists(index_name))
            {
                return(null);
            }
            var arc_name = Path.GetFileName(file.Name);

            using (var index = VFS.OpenView(index_name))
            {
                var dir = ReadIndex(index, arc_name, file.MaxOffset);
                if (null == dir)
                {
                    return(null);
                }
                return(new ArcFile(file, this, dir));
            }
        }
Пример #21
0
 public override ArcFile TryOpen(ArcView file)
 {
     if (file.MaxOffset > uint.MaxValue ||
         !VFS.IsPathEqualsToFileName(file.Name, "ArchPac.dat"))
     {
         return(null);
     }
     foreach (var scheme in KnownSchemes.Values.Where(s => s.IndexOffset < file.MaxOffset))
     {
         var dir = ReadIndex(file, scheme);
         if (dir != null)
         {
             if (scheme.EventMap != null)
             {
                 return(new SeraphArchive(file, this, dir, scheme));
             }
             else
             {
                 return(new ArcFile(file, this, dir));
             }
         }
     }
     return(null);
 }
Пример #22
0
        ArchiveKey FindArchiveKey(string arc_name)
        {
            // look for "start.ps3" in the same directory as an archive
            var start_name = VFS.ChangeFileName(arc_name, "start.ps3");

            if (!VFS.FileExists(start_name))
            {
                return(null);
            }
            byte[] start_data;
            using (var start = VFS.OpenView(start_name))
            {
                if (!start.View.AsciiEqual(0, "PS2A"))
                {
                    return(null);
                }
                start_data = start.View.ReadBytes(0, (uint)start.MaxOffset);
            }
            arc_name   = Path.GetFileName(arc_name);
            start_data = UnpackPs2(start_data);

            int table_count    = start_data.ToInt32(0x10);
            int strings_offset = 0x30 + table_count * 4 + start_data.ToInt32(0x14);
            int strings_size   = start_data.ToInt32(0x1C);

            if (strings_offset < 0x30 || strings_offset + strings_size > start_data.Length)
            {
                return(null);
            }

            // search strings table for archive name
            int string_pos  = strings_offset;
            int strings_end = strings_offset + strings_size;
            int arc_id      = -1;

            while (string_pos < strings_end)
            {
                int end_pos = Array.IndexOf <byte> (start_data, 0, string_pos);
                if (-1 == end_pos)
                {
                    end_pos = strings_offset + strings_size;
                }
                if (end_pos != string_pos)
                {
                    var text = Encodings.cp932.GetString(start_data, string_pos, end_pos - string_pos);
                    if (VFS.IsPathEqualsToFileName(text, arc_name))
                    {
                        arc_id = string_pos - strings_offset;
                        break;
                    }
                }
                string_pos = end_pos + 1;
            }
            if (-1 == arc_id)
            {
                return(null);
            }

            // search bytecode for a reference to archive name found above
            var id_bytes = new byte[4];

            LittleEndian.Pack(arc_id, id_bytes, 0);
            for (int data_pos = 0x30 + table_count * 4; data_pos + 4 <= strings_offset; ++data_pos)
            {
                if (start_data[data_pos + 0] == id_bytes[0] && start_data[data_pos + 1] == id_bytes[1] &&
                    start_data[data_pos + 2] == id_bytes[2] && start_data[data_pos + 3] == id_bytes[3])
                {
                    if (start_data[data_pos - 0x33] == 2 && start_data[data_pos - 0x32] == 0 &&
                        start_data[data_pos - 0x31] == 1)
                    {
                        return(new ArchiveKey {
                            IndexDirKey = start_data.ToUInt32(data_pos - 0x0C),
                            IndexEntryKey = start_data.ToUInt32(data_pos - 0x18),
                            EntryDataKey1 = start_data.ToUInt32(data_pos - 0x24),
                            EntryDataKey2 = start_data.ToUInt32(data_pos - 0x30),
                        });
                    }
                }
            }
            return(null);
        }
Пример #23
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (file.MaxOffset > uint.MaxValue ||
                !VFS.IsPathEqualsToFileName(file.Name, "ARCHPAC.DAT"))
            {
                return(null);
            }
            int file_count = file.View.ReadInt16(0);

            if (!IsSaneCount(file_count))
            {
                return(null);
            }
            uint index_pos  = 2;
            var  size_table = new uint[file_count];

            for (int i = 0; i < file_count; ++i)
            {
                size_table[i] = file.View.ReadUInt32(index_pos);
                index_pos    += 4;
            }
            var  section_table = new SortedDictionary <int, uint>();
            uint min_offset    = (uint)file.MaxOffset;

            while (index_pos + 6 <= min_offset)
            {
                uint offset = file.View.ReadUInt32(index_pos);
                int  index  = file.View.ReadInt16(index_pos + 4);
                if (index < 0 || index > file_count || offset > file.MaxOffset)
                {
                    return(null);
                }
                if (offset < min_offset)
                {
                    min_offset = offset;
                }
                section_table[index] = offset;
                index_pos           += 6;
            }
            var dir         = new List <Entry> (file_count);
            int section_num = 0;

            foreach (var section in section_table)
            {
                int  i           = section.Key;
                uint base_offset = section.Value;
                do
                {
                    uint size  = size_table[i];
                    var  entry = new PackedEntry {
                        Name   = string.Format("{0}-{1:D6}", section_num, i),
                        Offset = base_offset,
                        Size   = size,
                    };
                    if (!entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                    if (section_num < DefaultSections.Length && DefaultSections[section_num] != null)
                    {
                        entry.Type = DefaultSections[section_num];
                    }
                    if ("script" == entry.Type)
                    {
                        entry.IsPacked = true;
                    }
                    dir.Add(entry);
                    base_offset += size;
                    ++i;
                }while (i < file_count && !section_table.ContainsKey(i));
                ++section_num;
            }
            return(new ArcFile(file, this, dir));
        }
Пример #24
0
        public override ArcFile TryOpen(ArcView file)
        {
            int count = file.View.ReadInt32(4);

            if (!IsSaneCount(count) || VFS.IsPathEqualsToFileName(file.Name, "00.mpk"))
            {
                return(null);
            }
            var           list_name = VFS.ChangeFileName(file.Name, "00.mpk");
            List <string> filelist;

            if (VFS.FileExists(list_name))
            {
                using (var s = VFS.OpenStream(list_name))
                    using (var xs = new XoredStream(s, 0xA))
                        using (var reader = new StreamReader(xs, Encodings.cp932))
                        {
                            filelist = new List <string> (count);
                            string filename;
                            while ((filename = reader.ReadLine()) != null)
                            {
                                filelist.Add(filename);
                            }
                        }
            }
            else
            {
                var base_name = Path.GetFileNameWithoutExtension(file.Name);
                filelist = Enumerable.Range(0, count).Select(x => string.Format("{0}#{1:D4}", base_name, x)).ToList();
            }
            bool has_sizes    = file.View.ReadByte(3) != 'P';
            uint index_offset = 8;
            uint record_size  = has_sizes ? 8u : 4u;
            var  dir          = new List <Entry> (count);

            for (int i = 0; i < count; ++i)
            {
                var entry = FormatCatalog.Instance.Create <Entry> (filelist[i]);
                entry.Offset = file.View.ReadUInt32(index_offset);
                if (has_sizes)
                {
                    entry.Size = file.View.ReadUInt32(index_offset + 4);
                    if (!entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                }
                else if (entry.Offset > file.MaxOffset)
                {
                    return(null);
                }
                dir.Add(entry);
                index_offset += record_size;
            }
            if (!has_sizes)
            {
                for (int i = 1; i < count; ++i)
                {
                    dir[i - 1].Size = (uint)(dir[i].Offset - dir[i - 1].Offset);
                }
                dir[dir.Count - 1].Size = (uint)(file.MaxOffset - dir[dir.Count - 1].Offset);
            }
            return(new ArcFile(file, this, dir));
        }
Пример #25
0
        public override void Create(Stream output, IEnumerable <Entry> list, ResourceOptions options,
                                    EntryCallback callback)
        {
            var xp3_options = GetOptions <Xp3Options> (options);

            ICrypt scheme            = xp3_options.Scheme;
            bool   compress_index    = xp3_options.CompressIndex;
            bool   compress_contents = xp3_options.CompressContents;
            bool   retain_dirs       = xp3_options.RetainDirs;

            bool use_encryption = !(scheme is NoCrypt);

            using (var writer = new BinaryWriter(output, Encoding.ASCII, true))
            {
                writer.Write(s_xp3_header);
                if (2 == xp3_options.Version)
                {
                    writer.Write((long)0x17);
                    writer.Write((int)1);
                    writer.Write((byte)0x80);
                    writer.Write((long)0);
                }
                long index_pos_offset = writer.BaseStream.Position;
                writer.BaseStream.Seek(8, SeekOrigin.Current);

                int  callback_count = 0;
                var  used_names     = new HashSet <string>();
                var  dir            = new List <Xp3Entry>();
                long current_offset = writer.BaseStream.Position;
                foreach (var entry in list)
                {
                    if (null != callback)
                    {
                        callback(callback_count++, entry, arcStrings.MsgAddingFile);
                    }

                    string name = entry.Name;
                    if (!retain_dirs)
                    {
                        name = Path.GetFileName(name);
                    }
                    else
                    {
                        name = name.Replace(@"\", "/");
                    }
                    if (!used_names.Add(name))
                    {
                        Trace.WriteLine("duplicate name", entry.Name);
                        continue;
                    }

                    var xp3entry = new Xp3Entry {
                        Name        = name,
                        Cipher      = scheme,
                        IsEncrypted = use_encryption &&
                                      !(scheme.StartupTjsNotEncrypted && VFS.IsPathEqualsToFileName(name, "startup.tjs"))
                    };
                    bool compress = compress_contents && ShouldCompressFile(entry);
                    using (var file = File.Open(name, FileMode.Open, FileAccess.Read))
                    {
                        if (!xp3entry.IsEncrypted || 0 == file.Length)
                        {
                            RawFileCopy(file, xp3entry, output, compress);
                        }
                        else
                        {
                            EncryptedFileCopy(file, xp3entry, output, compress);
                        }
                    }

                    dir.Add(xp3entry);
                }

                long index_pos = writer.BaseStream.Position;
                writer.BaseStream.Position = index_pos_offset;
                writer.Write(index_pos);
                writer.BaseStream.Position = index_pos;

                using (var header = new BinaryWriter(new MemoryStream(dir.Count * 0x58), Encoding.Unicode))
                {
                    if (null != callback)
                    {
                        callback(callback_count++, null, arcStrings.MsgWritingIndex);
                    }

                    long dir_pos = 0;
                    foreach (var entry in dir)
                    {
                        header.BaseStream.Position = dir_pos;
                        header.Write((uint)0x656c6946);  // "File"
                        long header_size_pos = header.BaseStream.Position;
                        header.Write((long)0);
                        header.Write((uint)0x6f666e69);  // "info"
                        header.Write((long)(4 + 8 + 8 + 2 + entry.Name.Length * 2));
                        header.Write((uint)(use_encryption ? 0x80000000 : 0));
                        header.Write((long)entry.UnpackedSize);
                        header.Write((long)entry.Size);

                        header.Write((short)entry.Name.Length);
                        foreach (char c in entry.Name)
                        {
                            header.Write(c);
                        }

                        header.Write((uint)0x6d676573);  // "segm"
                        header.Write((long)0x1c);
                        var segment = entry.Segments.First();
                        header.Write((int)(segment.IsCompressed ? 1 : 0));
                        header.Write((long)segment.Offset);
                        header.Write((long)segment.Size);
                        header.Write((long)segment.PackedSize);

                        header.Write((uint)0x726c6461);  // "adlr"
                        header.Write((long)4);
                        header.Write((uint)entry.Hash);

                        dir_pos = header.BaseStream.Position;
                        long header_size = dir_pos - header_size_pos - 8;
                        header.BaseStream.Position = header_size_pos;
                        header.Write(header_size);
                    }

                    header.BaseStream.Position = 0;
                    writer.Write(compress_index);
                    long unpacked_dir_size = header.BaseStream.Length;
                    if (compress_index)
                    {
                        if (null != callback)
                        {
                            callback(callback_count++, null, arcStrings.MsgCompressingIndex);
                        }

                        long packed_dir_size_pos = writer.BaseStream.Position;
                        writer.Write((long)0);
                        writer.Write(unpacked_dir_size);

                        long dir_start = writer.BaseStream.Position;
                        using (var zstream = new ZLibStream(writer.BaseStream, CompressionMode.Compress,
                                                            CompressionLevel.Level9, true))
                            header.BaseStream.CopyTo(zstream);

                        long packed_dir_size = writer.BaseStream.Position - dir_start;
                        writer.BaseStream.Position = packed_dir_size_pos;
                        writer.Write(packed_dir_size);
                    }
                    else
                    {
                        writer.Write(unpacked_dir_size);
                        header.BaseStream.CopyTo(writer.BaseStream);
                    }
                }
            }
            output.Seek(0, SeekOrigin.End);
        }
Пример #26
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!VFS.IsPathEqualsToFileName(file.Name, "AVGDatas.pck"))
            {
                return(null);
            }
            int seed   = Binary.BigEndian(file.View.ReadInt32(file.MaxOffset - 104));
            var header = file.View.ReadBytes(file.MaxOffset - 100, 100);
            var rnd    = new RandomGenerator();

            rnd.Init(seed);
            rnd.Decrypt(header, 0, header.Length);

            uint checksum = (uint)(header[1] | header[2] << 8 | header[0] << 16 | header[3] << 24) ^ 0xDEFD32D3;
            uint length   = BigEndian.ToUInt32(header, 24);

            if (checksum != length)
            {
                return(null);
            }

            uint idx_pos  = BigEndian.ToUInt32(header, 28);
            uint idx_size = Binary.BigEndian(file.View.ReadUInt32(idx_pos));

            uint index_size;
            var  index = ReadChunk(file, 8, idx_pos + 4, out index_size);

            if (index_size >= 0x80000000)
            {
                index_size &= 0x7FFFFFFF;
                var unpacked = new byte[idx_size];
                LzssUnpack(index, index.Length, unpacked);
                index = unpacked;
            }
            using (var input = new BinMemoryStream(index))
            {
                var dir       = new List <Entry>();
                int dir_count = 0;
                while (input.PeekByte() != -1)
                {
                    input.ReadInt32();
                    input.ReadInt32();
                    input.ReadInt32();
                    int count    = Binary.BigEndian(input.ReadInt32());
                    var dir_name = dir_count.ToString("X4");
                    for (int i = 0; i < count; ++i)
                    {
                        var name = input.ReadCString(0x28);
                        name = Path.Combine(dir_name, name);
                        var entry = Create <PckEntry> (name);
                        entry.Offset       = Binary.BigEndian(input.ReadUInt32());
                        entry.Size         = Binary.BigEndian(input.ReadUInt32());
                        entry.IsEncrypted  = input.ReadInt32() != 0;
                        entry.UnpackedSize = input.ReadUInt32();
                        entry.IsPacked     = entry.Size != entry.UnpackedSize;
                        if (!entry.CheckPlacement(file.MaxOffset))
                        {
                            return(null);
                        }
                        dir.Add(entry);
                    }
                    ++dir_count;
                }
                return(new ArcFile(file, this, dir));
            }
        }
Пример #27
0
        public override ArcFile TryOpen(ArcView file)
        {
            int count = file.View.ReadInt32(0);

            if (!IsSaneCount(count) || 8 + count * MinEntryLength >= file.MaxOffset)
            {
                return(null);
            }
            uint is_compressed = file.View.ReadUInt32(4);

            if (is_compressed > 1) // should be either 0 or 1
            {
                return(null);
            }
            var scheme = GuessScheme(file, count);

            // additional filename extension check avoids dialog popup on false positives
            if (null == scheme && KnownSchemes.Count > 0 && file.Name.HasExtension(".arc"))
            {
                scheme = QueryScheme();
            }
            if (null == scheme)
            {
                return(null);
            }

            // special case for "instdata.arc" archives
            if (scheme.Keyword != "inst" &&
                VFS.IsPathEqualsToFileName(file.Name, "instdata.arc"))
            {
                scheme = new EncryptionScheme("inst", scheme.NameLength);
            }

            int index_size = count * (scheme.NameLength + 12);
            var index      = new byte[index_size];

            if (index_size != file.View.Read(8, index, 0, (uint)index_size))
            {
                return(null);
            }
            DecryptIndex(index, scheme.Keyword);

            uint data_offset = LittleEndian.ToUInt32(index, scheme.NameLength + 8);

            if (data_offset != 8 + index_size)
            {
                return(null);
            }

            int index_offset = 0;
            var dir          = new List <Entry> (count);

            for (int i = 0; i < count; ++i)
            {
                var name = Binary.GetCString(index, index_offset, scheme.NameLength);
                index_offset += scheme.NameLength;
                var entry = FormatCatalog.Instance.Create <PackedEntry> (name);
                entry.UnpackedSize = LittleEndian.ToUInt32(index, index_offset);
                entry.Size         = LittleEndian.ToUInt32(index, index_offset + 4);
                entry.Offset       = LittleEndian.ToUInt32(index, index_offset + 8);
                entry.IsPacked     = is_compressed != 0;
                if (0 != entry.Size)
                {
                    if (entry.Offset < data_offset || !entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                }
                dir.Add(entry);
                index_offset += 12;
            }
            return(new ArcFile(file, this, dir));
        }
Пример #28
0
        public override ArcFile TryOpen(ArcView file)
        {
            uint file_size = file.View.ReadUInt32(4);

            if (file_size != file.MaxOffset)
            {
                return(null);
            }
            int count = file.View.ReadInt32(8);

            if (count <= 0 || count > 0xfffff)
            {
                return(null);
            }
            int  dir_level    = file.View.ReadByte(0x0d);
            int  dir_entries  = file.View.ReadUInt16(0x0e);
            uint index_offset = 0x10;
            uint index_size   = (uint)(count * 0x18 + dir_entries * 8);

            if (index_size > file.View.Reserve(index_offset, index_size))
            {
                return(null);
            }
            List <DirEntry> folders = null;

            if (0 != dir_entries && 2 == dir_level)
            {
                folders = new List <DirEntry> (dir_entries);
                uint dir_offset = index_offset + (uint)count * 0x18;
                for (int i = 0; i < dir_entries; ++i)
                {
                    folders.Add(new DirEntry {
                        Name  = file.View.ReadString(dir_offset, 4),
                        Index = file.View.ReadInt32(dir_offset + 4)
                    });
                    dir_offset += 8;
                }
            }
            bool   is_mask_arc    = VFS.IsPathEqualsToFileName(file.Name, "mask.arc");
            var    dir            = new List <Entry> (count);
            int    next_folder    = null == folders ? count : folders[0].Index;
            int    folder         = 0;
            string current_folder = "";

            for (int i = 0; i < count; ++i)
            {
                while (i >= next_folder && folder < folders.Count)
                {
                    current_folder = folders[folder++].Name;
                    if (folders.Count == folder)
                    {
                        next_folder = count;
                    }
                    else
                    {
                        next_folder = folders[folder].Index;
                    }
                }
                string name = file.View.ReadString(index_offset, 0x10);
                if (0 == name.Length)
                {
                    return(null);
                }
                var offset = file.View.ReadUInt32(index_offset + 0x10);
                var entry  = new AutoEntry(Path.Combine(current_folder, name), () => {
                    if (is_mask_arc)
                    {
                        return(s_MskFormat.Value);
                    }
                    uint signature = file.View.ReadUInt32(offset);
                    switch (signature & 0xFFFF)
                    {
                    case 0x4D43: return(s_CmFormat.Value);

                    case 0x4D41: return(s_AmFormat.Value);

                    case 0x4D42: return(ImageFormat.Bmp);

                    default: return(AutoEntry.DetectFileType(signature));
                    }
                });
                entry.Offset = offset;
                entry.Size   = file.View.ReadUInt32(index_offset + 0x14);
                if (!entry.CheckPlacement(file.MaxOffset))
                {
                    return(null);
                }
                dir.Add(entry);
                index_offset += 0x18;
            }
            return(new ArcFile(file, this, dir));
        }