Example #1
0
        int AddDirectory(string dir)
        {
            int folder_id = 0;

            if (m_directory_map.TryGetValue(dir, out folder_id))
            {
                return(folder_id);
            }
            string path = "";

            foreach (var component in dir.Split(Path.DirectorySeparatorChar))
            {
                path = Path.Combine(path, component);
                if (m_directory_map.TryGetValue(path, out folder_id))
                {
                    continue;
                }
                folder_id             = ++m_directory_count;
                m_directory_map[path] = folder_id;

                var npa_entry = new NpaEntry
                {
                    Name         = path,
                    Type         = "directory",
                    Offset       = 0,
                    Size         = 0,
                    UnpackedSize = 0,
                    IsPacked     = false,
                    RawName      = m_encoding.GetBytes(path),
                    FolderId     = folder_id,
                };
                AddEntry(npa_entry);
            }
            return(folder_id);
        }
Example #2
0
        public EncryptedStream(Stream output, NpaEntry entry, EncryptionScheme scheme, int arc_key)
        {
            m_read_mode        = false;
            m_encrypted_length = GetEncryptedLength(entry, scheme.TitleId);
            int key = NpaOpener.GetKeyFromEntry(entry, scheme, arc_key);

            m_stream    = output;
            m_encrypted = new Lazy <byte[]> (() => new byte[m_encrypted_length]);
            m_base_pos  = m_stream.Position;

            byte[] decrypt_table = NpaOpener.GenerateKeyTable(scheme);
            byte[] encrypt_table = new byte[256];
            for (int i = 0; i < 256; ++i)
            {
                encrypt_table[decrypt_table[i]] = (byte)i;
            }

            if (NpaTitleId.LAMENTO == scheme.TitleId)
            {
                Encrypt = (i, x) => encrypt_table[(x + key) & 0xff];
            }
            else
            {
                Encrypt = (i, x) => encrypt_table[(x + key + i) & 0xff];
            }
        }
Example #3
0
        int GetEncryptedLength(NpaEntry entry, NpaTitleId game_id)
        {
            int length = 0x1000;

            if (game_id != NpaTitleId.LAMENTO)
            {
                length += entry.RawName.Length;
            }
            return(length);
        }
Example #4
0
        public EncryptedStream(NpaArchive arc, NpaEntry entry)
        {
            m_read_mode        = true;
            m_encrypted_length = GetEncryptedLength(entry, arc.Scheme.TitleId);
            if (m_encrypted_length > entry.Size)
            {
                m_encrypted_length = (int)entry.Size;
            }
            int key = NpaOpener.GetKeyFromEntry(entry, arc.Scheme, arc.Key);

            m_stream    = arc.File.CreateStream(entry.Offset, entry.Size);
            m_encrypted = new Lazy <byte[]> (() => InitEncrypted(key, arc.Scheme.TitleId, arc.KeyTable));
            m_base_pos  = m_stream.Position;
        }
Example #5
0
        internal static byte GetKeyFromEntry(NpaEntry entry, EncryptionScheme scheme, int arc_key)
        {
            int key  = (int)scheme.NameKey;
            var name = entry.RawName;

            for (int i = 0; i < name.Length; ++i)
            {
                key -= name[i];
            }

            key *= name.Length;

            if (scheme.TitleId != NpaTitleId.LAMENTO) // if the game is not Lamento
            {
                key += arc_key;
                key *= (int)entry.UnpackedSize;
            }
            return((byte)key);
        }
Example #6
0
        public Indexer(IEnumerable <Entry> source_list, NpaOptions options)
        {
            m_entries = new List <NpaEntry> (source_list.Count());
            var title_id = null != options.Scheme ? options.Scheme.TitleId : NpaTitleId.NotEncrypted;

            m_key = NpaOpener.GetArchiveKey(title_id, options.Key1, options.Key2);

            foreach (var entry in source_list)
            {
                string name = entry.Name;
                try
                {
                    var dir       = Path.GetDirectoryName(name);
                    int folder_id = 0;
                    if (!string.IsNullOrEmpty(dir))
                    {
                        folder_id = AddDirectory(dir);
                    }

                    bool compress = options.CompressContents;
                    if (compress) // don't compress images
                    {
                        compress = !FormatCatalog.Instance.LookupFileName(name).OfType <ImageFormat>().Any();
                    }
                    var npa_entry = new NpaEntry
                    {
                        Name     = name,
                        IsPacked = compress,
                        RawName  = m_encoding.GetBytes(name),
                        FolderId = folder_id,
                    };
                    ++m_file_count;
                    AddEntry(npa_entry);
                }
                catch (EncoderFallbackException X)
                {
                    throw new InvalidFileName(name, arcStrings.MsgIllegalCharacters, X);
                }
            }
        }
Example #7
0
 void AddEntry(NpaEntry entry)
 {
     m_entries.Add(entry);
     m_size += 4 + entry.RawName.Length + 17;
 }
Example #8
0
        public override ArcFile TryOpen(ArcView file)
        {
            int  key1         = file.View.ReadInt32(7);
            int  key2         = file.View.ReadInt32(11);
            bool compressed   = 0 != file.View.ReadByte(15);
            bool encrypted    = 0 != file.View.ReadByte(16);
            int  total_count  = file.View.ReadInt32(17);
            int  folder_count = file.View.ReadInt32(21);
            int  file_count   = file.View.ReadInt32(25);

            if (total_count < folder_count + file_count)
            {
                return(null);
            }
            uint dir_size = file.View.ReadUInt32(37);

            if (dir_size >= file.MaxOffset)
            {
                return(null);
            }

            EncryptionScheme enc = null;
            var game_id          = NpaTitleId.NotEncrypted;

            if (encrypted)
            {
                enc = QueryGameEncryption(file.Name);
                if (null == enc)
                {
                    throw new OperationCanceledException(garStrings.MsgUnknownEncryption);
                }
                game_id = enc.TitleId;
            }

            int key = GetArchiveKey(game_id, key1, key2);

            long cur_offset = 41;
            var  dir        = new List <Entry> (file_count);

            for (int i = 0; i < total_count; ++i)
            {
                int name_size = file.View.ReadInt32(cur_offset);
                if ((uint)name_size >= dir_size)
                {
                    return(null);
                }
                int type = file.View.ReadByte(cur_offset + 4 + name_size);
                if (1 != type) // ignore directory entries
                {
                    var raw_name = new byte[name_size];
                    file.View.Read(cur_offset + 4, raw_name, 0, (uint)name_size);
                    for (int x = 0; x < name_size; ++x)
                    {
                        raw_name[x] += DecryptName(x, i, key);
                    }
                    var info_offset = cur_offset + 5 + name_size;

                    int  id            = file.View.ReadInt32(info_offset);
                    uint offset        = file.View.ReadUInt32(info_offset + 4);
                    uint size          = file.View.ReadUInt32(info_offset + 8);
                    uint unpacked_size = file.View.ReadUInt32(info_offset + 12);

                    var entry = new NpaEntry {
                        Name         = Encodings.cp932.GetString(raw_name),
                        Offset       = dir_size + offset + 41,
                        Size         = size,
                        UnpackedSize = unpacked_size,
                        RawName      = raw_name,
                        FolderId     = id,
                    };
                    if (!entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                    entry.Type     = FormatCatalog.Instance.GetTypeFromName(entry.Name);
                    entry.IsPacked = compressed && entry.Type != "image";
                    dir.Add(entry);
                }
                cur_offset += 4 + name_size + 17;
            }
            if (enc != null)
            {
                return(new NpaArchive(file, this, dir, enc, key));
            }
            else
            {
                return(new ArcFile(file, this, dir));
            }
        }