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); }
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]; } }
int GetEncryptedLength(NpaEntry entry, NpaTitleId game_id) { int length = 0x1000; if (game_id != NpaTitleId.LAMENTO) { length += entry.RawName.Length; } return(length); }
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; }
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); }
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); } } }
void AddEntry(NpaEntry entry) { m_entries.Add(entry); m_size += 4 + entry.RawName.Length + 17; }
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)); } }