public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(0xC); if (!IsSaneCount(count)) { return(null); } uint index_offset = file.View.ReadUInt32(4); if (index_offset >= file.MaxOffset) { return(null); } var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { var entry = new PackedEntry { UnpackedSize = file.View.ReadUInt32(index_offset), Size = file.View.ReadUInt32(index_offset + 4), Offset = file.View.ReadUInt32(index_offset + 8), }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } uint name_length = file.View.ReadUInt32(index_offset + 0xC); if (0 == name_length || name_length > 0x100) { return(null); } entry.Name = file.View.ReadString(index_offset + 0x10, name_length); entry.Type = FormatCatalog.Instance.GetTypeFromName(entry.Name); entry.IsPacked = entry.UnpackedSize != entry.Size; dir.Add(entry); index_offset += 0x10 + name_length; } return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(0); if (!IsSaneCount(count)) { return(null); } uint index_offset = 0x20; long data_offset = index_offset + count * 0x110; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { var name = file.View.ReadString(index_offset, 0x100); if (string.IsNullOrWhiteSpace(name)) { return(null); } var entry = new PackedEntry(); entry.IsPacked = name.HasExtension(".pr3"); if (entry.IsPacked) { name = name.Substring(0, name.Length - 4); } entry.Name = name; entry.Type = FormatCatalog.Instance.GetTypeFromName(name); entry.Size = file.View.ReadUInt32(index_offset + 0x100); entry.Offset = file.View.ReadUInt32(index_offset + 0x104); entry.UnpackedSize = entry.Size; if (entry.Offset < data_offset || entry.Offset > file.MaxOffset) { return(null); } dir.Add(entry); index_offset += 0x110; } return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { int version = file.View.ReadByte(3) - '0'; int count = file.View.ReadInt32(4); if (!IsSaneCount(count)) { return(null); } var index = ReadIndex(file, 8, count); var dir = new List <Entry>(); foreach (var section in index) { int index_offset = section.Item1; for (int section_size = section.Item2; section_size > 0;) { int entry_size = file.View.ReadByte(index_offset); if (entry_size < 5) { break; } var entry = new PackedEntry { Offset = Binary.BigEndian(file.View.ReadUInt32(index_offset + 1)), Name = file.View.ReadString(index_offset + 5, (uint)entry_size - 5), }; if (entry.Offset > file.MaxOffset) { return(null); } index_offset += entry_size; section_size -= entry_size; dir.Add(entry); } } DetectFileTypes(file, dir); return(new ArcFile(file, this, dir)); }
internal List <Entry> ReadIndex(ArcView file, uint index_offset, int count) { var base_name = Path.GetFileNameWithoutExtension(file.Name); long offset = index_offset + count * 4; if (offset >= file.MaxOffset) { return(null); } var dir = new List <Entry> (count / 2); for (int i = 0; i < count; ++i) { uint size = file.View.ReadUInt32(index_offset); if (size != 0 && size != uint.MaxValue) { var entry = new PackedEntry { Name = string.Format("{0}#{1:D5}", base_name, i), Offset = offset, Size = size, IsPacked = false, }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } dir.Add(entry); offset += size; } index_offset += 4; } if (0 == dir.Count || (file.MaxOffset - offset) > 0x80000) { return(null); } DetectFileTypes(file, dir); return(dir); }
int UpdateFileTable(IDictionary <uint, PackedEntry> table, IEnumerable <Entry> list) { int update_count = 0; foreach (var entry in list) { if (entry.Type != "image" && !entry.Name.HasExtension(".scr")) { continue; } uint id; if (!uint.TryParse(Path.GetFileNameWithoutExtension(entry.Name), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out id)) { continue; } PackedEntry existing; if (table.TryGetValue(id, out existing) && !(existing is AmiEntry)) { var file_new = new FileInfo(entry.Name); if (!file_new.Exists) { continue; } var file_old = new FileInfo(existing.Name); if (file_new.LastWriteTime <= file_old.LastWriteTime) { continue; } } table[id] = new PackedEntry { Name = entry.Name, Type = entry.Type }; ++update_count; } return(update_count); }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(0); if (!IsSaneCount(count) || !file.Name.HasExtension(".dat")) { return(null); } uint first_offset = file.View.ReadUInt32(0x14); if (first_offset != 4 + count * 0x14) { return(null); } uint index_offset = 4; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { var name = file.View.ReadString(index_offset, 0xC); if (string.IsNullOrEmpty(name)) { return(null); } var entry = new PackedEntry { Name = name, Size = file.View.ReadUInt32(index_offset + 0xC), Offset = file.View.ReadUInt32(index_offset + 0x10), }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } dir.Add(entry); index_offset += 0x14; } DetectFileTypes(file, dir); return(new ArcFile(file, this, dir)); }
uint WriteAmiEntry(PackedEntry entry, Stream output) { uint packed_size = 0; using (var input = VFS.OpenBinaryStream(entry)) { long file_size = input.Length; if (file_size > uint.MaxValue) { throw new FileSizeException(); } entry.UnpackedSize = (uint)file_size; if ("image" == entry.Type) { packed_size = WriteImageEntry(entry, input, output); } else { input.AsStream.CopyTo(output); } } return(packed_size); }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(4); if (!IsSaneCount(count)) { return(null); } var base_name = Path.GetFileNameWithoutExtension(file.Name); uint index_offset = 0x20; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { var entry = new PackedEntry { Offset = file.View.ReadUInt32(index_offset), UnpackedSize = file.View.ReadUInt32(index_offset + 4), Size = file.View.ReadUInt32(index_offset + 8), Name = string.Format("{0}#{1:D5}", base_name, i), }; entry.IsPacked = entry.Size != 0; if (!entry.IsPacked) { entry.Size = entry.UnpackedSize; } if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } index_offset += 0x10; dir.Add(entry); } DetectFileTypes(file, dir); return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { if (0 != file.View.ReadInt32(4)) { return(null); } long index_offset = file.View.ReadInt64(8); if (index_offset >= file.MaxOffset) { return(null); } if (!file.View.AsciiEqual(index_offset, "GCE3")) { return(null); } int count = file.View.ReadInt32(index_offset + 0x18); if (!IsSaneCount(count)) { return(null); } bool index_packed = 0x11 == file.View.ReadInt32(index_offset + 4); uint index_size = file.View.ReadUInt32(index_offset + 8); byte[] index = null; if (index_packed) { index_size -= 0x28; int unpacked_size = file.View.ReadInt32(index_offset + 0x20); using (var input = file.CreateStream(index_offset + 0x28, index_size)) using (var reader = new GceReader(input, unpacked_size)) index = reader.Data; } else { index_size -= 0x20; index = new byte[index_size]; if (index.Length != file.View.Read(index_offset + 0x20, index, 0, index_size)) { return(null); } } int current_index = 0; int current_filename = 0x20 * count; long current_offset = 0x10; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { int name_length = LittleEndian.ToUInt16(index, current_filename); if (current_filename + 2 + name_length > index.Length) { return(null); } uint size = LittleEndian.ToUInt32(index, current_index + 0x18); if (size != 0) { string name = Encodings.cp932.GetString(index, current_filename + 2, name_length); var entry = new PackedEntry { Name = name, Type = FormatCatalog.Instance.GetTypeFromName(name), Offset = current_offset, Size = size, UnpackedSize = LittleEndian.ToUInt32(index, current_index + 0x10), }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } entry.IsPacked = entry.Size != entry.UnpackedSize; current_offset += entry.Size; dir.Add(entry); } current_index += 0x20; current_filename += 2 + name_length; } return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(0); if (!IsSaneCount(count)) { return(null); } uint index_size = (uint)count * 4 + 8; if (index_size > file.View.Reserve(0, index_size)) { return(null); } uint index_offset = 4; uint offset = file.View.ReadUInt32(index_offset); if (offset != index_size) { return(null); } uint last_offset = file.View.ReadUInt32(index_size - 4); if (last_offset != file.MaxOffset) { return(null); } string default_type = ""; if (file.Name.HasExtension("fx")) { default_type = "audio"; } else if (file.Name.HasExtension("gx")) { default_type = "image"; } var base_name = Path.GetFileNameWithoutExtension(file.Name); var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { index_offset += 4; var entry = new PackedEntry { Name = string.Format("{0}#{1:D4}", base_name, i), Type = default_type, Offset = offset, }; offset = file.View.ReadUInt32(index_offset); entry.Size = (uint)(offset - entry.Offset); if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } dir.Add(entry); } if (string.IsNullOrEmpty(default_type)) { foreach (var entry in dir) { uint signature = file.View.ReadUInt32(entry.Offset); entry.ChangeType(AutoEntry.DetectFileType(signature)); } } return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { int version = file.View.ReadByte(3) - 0x30; int count = file.View.ReadInt32(4); if (!IsSaneCount(count)) { return(null); } var name_buf = new byte[32]; var dir = new List <Entry> (count); long index_offset = 8; uint next_offset = file.View.ReadUInt32(index_offset); for (int i = 0; i < count; ++i) { uint offset = next_offset; uint size = file.View.ReadUInt32(index_offset + 4); int name_length = file.View.ReadByte(index_offset + 8); if (name_length > name_buf.Length) { name_buf = new byte[name_length]; } file.View.Read(index_offset + 9, name_buf, 0, (uint)name_length); if (i + 1 == count) { next_offset = (uint)file.MaxOffset; } else { next_offset = file.View.ReadUInt32(index_offset + 9 + name_length); } if (0 != offset && offset != file.MaxOffset) { if (2 == version) { for (int j = 0; j < name_length; ++j) { name_buf[j] ^= 0xff; } } uint packed_size; if (0 == next_offset) { packed_size = size; } else if (next_offset >= offset) { packed_size = next_offset - offset; } else { return(null); } string name = Encodings.cp932.GetString(name_buf, 0, name_length); var entry = new PackedEntry { Name = name, Type = FormatCatalog.Instance.GetTypeFromName(name), Offset = offset, Size = packed_size, UnpackedSize = size, IsPacked = packed_size != size, }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } dir.Add(entry); } index_offset += 9 + name_length; } if (2 == version) { return(new AstArchive(file, this, dir)); } else { return(new ArcFile(file, this, dir)); } }
public override ArcFile TryOpen(ArcView file) { uint first_offset = file.View.ReadUInt32(0); if (first_offset < 8 || first_offset >= file.MaxOffset) { return(null); } int count = (int)(first_offset - 8) / 4; if (!IsSaneCount(count)) { return(null); } var base_name = Path.GetFileNameWithoutExtension(file.Name); uint index_offset = 0; uint next_offset = first_offset; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { var entry = new PackedEntry { Offset = next_offset }; index_offset += 4; next_offset = file.View.ReadUInt32(index_offset); if (next_offset < entry.Offset) { return(null); } entry.Size = (uint)(next_offset - entry.Offset); entry.UnpackedSize = entry.Size; if (entry.Size != 0) { if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } entry.Name = string.Format("{0}#{1:D4}", base_name, i); dir.Add(entry); } } if (0 == dir.Count) { return(null); } foreach (PackedEntry entry in dir) { if (entry.Size < 4) { continue; } uint unpacked_size = file.View.ReadUInt32(entry.Offset); if (entry.Size > 8 && file.View.AsciiEqual(entry.Offset + 4, "HDJ\0")) { if (file.View.AsciiEqual(entry.Offset + 12, "BM")) { entry.Name = Path.ChangeExtension(entry.Name, "bmp"); entry.Type = "image"; } entry.UnpackedSize = unpacked_size; entry.IsPacked = true; } else if (entry.Size > 12 && file.View.AsciiEqual(entry.Offset + 8, "RIFF")) { entry.Name = Path.ChangeExtension(entry.Name, "wav"); entry.Type = "audio"; entry.UnpackedSize = unpacked_size; entry.IsPacked = true; } else if (0x4D42 == (unpacked_size & 0xFFFF)) { entry.Name = Path.ChangeExtension(entry.Name, "bmp"); entry.Type = "image"; } } return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32 (0); if (!IsSaneCount (count)) return null; long offset = 4+count*4; if (offset >= file.MaxOffset) return null; uint index_offset = 4; var dir = new List<Entry>(); for (int i = 0; i < count; ++i) { uint size = file.View.ReadUInt32 (index_offset); if (0 != size) { var entry = new PackedEntry { Name = i.ToString ("D5"), Offset = offset, Size = size, IsPacked = false, }; if (!entry.CheckPlacement (file.MaxOffset)) return null; dir.Add (entry); offset += size; } index_offset += 4; } if (offset != file.MaxOffset || 0 == dir.Count) return null; byte[] preview = new byte[16]; byte[] sign_buf = new byte[4]; foreach (PackedEntry entry in dir) { uint extra = 6; if (extra > entry.Size) continue; int label = file.View.ReadUInt16 (entry.Offset); if (1 == label) { entry.IsPacked = true; entry.UnpackedSize = file.View.ReadUInt32 (entry.Offset+2); } entry.Offset += extra; entry.Size -= extra; uint signature; if (entry.IsPacked) { file.View.Read (entry.Offset, preview, 0, (uint)preview.Length); using (var input = new MemoryStream (preview)) { LzssUnpack (input, sign_buf); signature = LittleEndian.ToUInt32 (sign_buf, 0); } } else { signature = file.View.ReadUInt32 (entry.Offset); } if (0 != signature) SetEntryType (entry, signature); } return new ArcFile (file, this, dir); }
int UpdateFileTable(IDictionary<uint, PackedEntry> table, IEnumerable<Entry> list) { int update_count = 0; foreach (var entry in list) { if (entry.Type != "image" && !entry.Name.EndsWith (".scr", StringComparison.InvariantCultureIgnoreCase)) continue; uint id; if (!uint.TryParse (Path.GetFileNameWithoutExtension (entry.Name), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out id)) continue; PackedEntry existing; if (table.TryGetValue (id, out existing) && !(existing is AmiEntry)) { var file_new = new FileInfo (entry.Name); if (!file_new.Exists) continue; var file_old = new FileInfo (existing.Name); if (file_new.LastWriteTime <= file_old.LastWriteTime) continue; } table[id] = new PackedEntry { Name = entry.Name, Type = entry.Type }; ++update_count; } return update_count; }
uint WriteAmiEntry(PackedEntry entry, Stream output) { uint packed_size = 0; using (var input = File.OpenRead (entry.Name)) { long file_size = input.Length; if (file_size > uint.MaxValue) throw new FileSizeException(); entry.UnpackedSize = (uint)file_size; if ("image" == entry.Type) { packed_size = WriteImageEntry (entry, input, output); } else { input.CopyTo (output); } } return packed_size; }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32 (4); if (!IsSaneCount (count)) return null; var base_name = Path.GetFileNameWithoutExtension (file.Name); var dir = new List<Entry> (count); int index_offset = 8; long data_offset = count * 4 + 8; uint next_offset = file.View.ReadUInt32 (index_offset); for (int i = 0; i < count; ++i) { index_offset += 4; var entry = new PackedEntry { Offset = next_offset }; next_offset = i + 1 < count ? file.View.ReadUInt32 (index_offset) : (uint)file.MaxOffset; entry.Size = next_offset - (uint)entry.Offset; if (entry.Offset < data_offset || !entry.CheckPlacement (file.MaxOffset)) return null; entry.Name = string.Format ("{0}#{1:D4}", base_name, i); dir.Add (entry); } DetectFileTypes (file, dir); return new ArcFile (file, this, dir); }
public override ArcFile TryOpen(ArcView file) { if (!file.Name.EndsWith (".mgr", StringComparison.InvariantCultureIgnoreCase)) return null; int count = file.View.ReadInt16 (0); if (count <= 0 || count >= 0x100) return null; uint current = 2; uint first_offset = current; if (count > 1) { first_offset = file.View.ReadUInt32 (current); if (first_offset != 2 + count * 4) return null; } if (!file.View.AsciiEqual (first_offset+9, "BM")) return null; string base_name = Path.GetFileNameWithoutExtension (file.Name); var dir = new List<Entry> (count); if (count > 1) { for (int i = 0; i < count; ++i) { var entry = new PackedEntry { Name = string.Format ("{0}#{1:D4}.bmp", base_name, i), Type = "image", Offset = file.View.ReadUInt32 (current), }; if (entry.Offset < first_offset || entry.Offset >= file.MaxOffset) return null; dir.Add (entry); current += 4; } } else { dir.Add (new PackedEntry { Name = base_name+".bmp", Type = "image", Offset = current }); } foreach (PackedEntry entry in dir) { entry.UnpackedSize = file.View.ReadUInt32 (entry.Offset); entry.Size = file.View.ReadUInt32 (entry.Offset+4); entry.IsPacked = true; if (entry.UnpackedSize < 0x36 || entry.Size > file.MaxOffset-entry.Offset) return null; entry.Offset += 8; } return new ArcFile (file, this, dir); }
public List <Entry> ReadIndex() { uint section_size = ReadSectionSize("Fver"); m_offset += section_size; section_size = ReadSectionSize("Fcdr"); /* * int Mcdr_size; * var Mcdr = ZlibUnpack (m_offset, section_size, out Mcdr_size); */ m_offset += section_size; uint abmp_size = ReadSectionSize("ABMP"); int max_count = m_file.View.Read(m_offset, m_size_buffer, 0, Math.Min(10, abmp_size)); int size_offset = 0; ReadValue(m_size_buffer, ref size_offset, max_count); max_count -= size_offset; int bmp_unpacked_size = (int)ReadValue(m_size_buffer, ref size_offset, max_count); m_offset += size_offset; abmp_size -= (uint)size_offset; int index_size; var index = ZlibUnpack(m_offset, abmp_size, out index_size, bmp_unpacked_size); m_offset += abmp_size; section_size = ReadSectionSize("FGEI"); if (0 != section_size) { throw new NotSupportedException(); } int index_offset = 0; ReadValue(index, ref index_offset, index_size - index_offset); ReadValue(index, ref index_offset, index_size - index_offset); int entry_count = (int)ReadValue(index, ref index_offset, index_size - index_offset); if (entry_count <= 0 || entry_count > 0xfffff) { return(null); } var type_buf = new char[4]; var dir = new List <Entry> (entry_count); for (int i = 0; i < entry_count; ++i) { uint id = ReadValue(index, ref index_offset, index_size - index_offset); uint offset = ReadValue(index, ref index_offset, index_size - index_offset); uint size = ReadValue(index, ref index_offset, index_size - index_offset); uint unpacked_size = ReadValue(index, ref index_offset, index_size - index_offset); uint flag = ReadValue(index, ref index_offset, index_size - index_offset); if (index_size - index_offset < 4) { return(null); } uint type_id = LittleEndian.ToUInt32(index, index_offset); index_offset += 4; if (0 == type_id || uint.MaxValue == offset) { continue; } Encoding.ASCII.GetChars(index, index_offset - 4, 4, type_buf, 0); var entry = new PackedEntry { Name = CreateName(id, type_buf), Offset = (long)m_offset + offset, Size = size, UnpackedSize = unpacked_size, IsPacked = 0 == flag, }; if (entry.CheckPlacement(m_file.MaxOffset)) { dir.Add(entry); } } return(dir); }
public override ArcFile TryOpen(ArcView file) { if (!file.View.AsciiEqual (0, "KOTORI") || 0x1A1A00 != file.View.ReadInt32 (6)) return null; int count = file.View.ReadUInt16 (0x14); if (0x0100A618 != file.View.ReadInt32 (0x10) || !IsSaneCount (count)) return null; string base_name = Path.GetFileNameWithoutExtension (file.Name); uint current_offset = 0x18; long next_offset = file.View.ReadUInt32 (current_offset); var dir = new List<Entry> (count); for (int i = 0; i < count; ++i) { var entry = new PackedEntry { Name = string.Format ("{0}#{1:D4}.ogg", base_name, i), Type = "audio", Offset = next_offset, }; if (i+1 != count) { current_offset += 6; next_offset = file.View.ReadUInt32 (current_offset); } else next_offset = file.MaxOffset; entry.Size = (uint)(next_offset - entry.Offset); if (entry.Size >= 0x32) { entry.IsPacked = true; entry.UnpackedSize = entry.Size - 0x32; } if (!entry.CheckPlacement (file.MaxOffset)) return null; dir.Add (entry); } return new ArcFile (file, this, dir); }
bool ReadV1(Stream input) { // NOTE CryptoStream will close an input stream using (var xored = new CryptoStream (input, new NotTransform(), CryptoStreamMode.Read)) using (var lzss = new LzssStream (xored)) lzss.Read (m_index, 0, m_index.Length); int index_offset = Array.IndexOf (m_index, (byte)0); if (-1 == index_offset || 0 == index_offset) return false; Password = m_index.Take (index_offset++).ToArray(); long base_offset = 0x20 + m_packed_size; for (int i = 0; i < m_count; ++i) { var entry = new PackedEntry(); entry.Offset = LittleEndian.ToUInt32 (m_index, index_offset) + base_offset; entry.Size = LittleEndian.ToUInt32 (m_index, index_offset + 4); entry.UnpackedSize = LittleEndian.ToUInt32 (m_index, index_offset + 8); entry.IsPacked = entry.UnpackedSize != 0; if (!entry.CheckPlacement (m_file.MaxOffset)) return false; int name_len = LittleEndian.ToInt32 (m_index, index_offset + 0xC); entry.Name = Encodings.cp932.GetString (m_index, index_offset+0x18, name_len); entry.Type = FormatCatalog.Instance.GetTypeFromName (entry.Name); m_dir.Value.Add (entry); index_offset += 0x18 + name_len; } return true; }
bool ReadV0(Stream input) { long current_offset = 0x20 + m_packed_size; uint offset_table_size = (uint)m_count * 0x10; if (offset_table_size > m_file.View.Reserve (current_offset, offset_table_size)) return false; using (var lzss = new LzssStream (input, LzssMode.Decompress, true)) lzss.Read (m_index, 0, m_index.Length); for (int i = 0; i < m_index.Length; ++i) { m_index[i] = (byte)(~m_index[i] - 5); } int index_offset = Array.IndexOf (m_index, (byte)0); if (-1 == index_offset || 0 == index_offset) return false; index_offset++; // Password = m_index.Take (index_offset++).ToArray(); for (int i = 0; i < m_count && index_offset < m_index.Length; ++i) { int name_end = Array.IndexOf (m_index, (byte)0, index_offset); if (-1 == name_end) name_end = m_index.Length; if (index_offset == name_end) return false; var entry = new PackedEntry(); entry.Offset = m_file.View.ReadUInt32 (current_offset); entry.Size = m_file.View.ReadUInt32 (current_offset+4); entry.UnpackedSize = m_file.View.ReadUInt32 (current_offset+8); entry.IsPacked = entry.UnpackedSize != 0; if (!entry.CheckPlacement (m_file.MaxOffset)) return false; entry.Name = Encodings.cp932.GetString (m_index, index_offset, name_end-index_offset); entry.Type = FormatCatalog.Instance.GetTypeFromName (entry.Name); m_dir.Value.Add (entry); index_offset = name_end+1; current_offset += 0x10; } return true; }
public override ArcFile TryOpen(ArcView file) { if (!file.View.AsciiEqual(4, "OFST")) { return(null); } int index_size = file.View.ReadInt32(8); int count = index_size / 4; if (!IsSaneCount(count)) { return(null); } var base_name = Path.GetFileNameWithoutExtension(file.Name); string content_ext = "", content_type = ""; if (base_name.EndsWith("flac", StringComparison.InvariantCultureIgnoreCase)) { content_ext = "flac"; content_type = "audio"; base_name = base_name.Substring(0, base_name.Length - 4); } else if (base_name.EndsWith("ogg", StringComparison.InvariantCultureIgnoreCase)) { content_ext = "ogg"; content_type = "audio"; base_name = base_name.Substring(0, base_name.Length - 3); } var filenames = GetFileNames(VFS.GetDirectoryName(file.Name), base_name); if (null == filenames) { filenames = new List <string> (count); } for (int i = filenames.Count; i < count; ++i) { filenames.Add(string.Format("{0}#{1:D5}", base_name, i)); } uint index_offset = 0xC; var dir = new List <Entry> (count); uint next_offset = file.View.ReadUInt32(index_offset); for (int i = 0; i < count; ++i) { index_offset += 4; var entry = new PackedEntry { Name = filenames[i] }; entry.Offset = next_offset; next_offset = i + 1 < count?file.View.ReadUInt32(index_offset) : (uint)file.MaxOffset; entry.Size = next_offset - (uint)entry.Offset; if (entry.Size > 0 && !entry.CheckPlacement(file.MaxOffset)) { return(null); } if (!string.IsNullOrEmpty(content_type)) { entry.Type = content_type; entry.Name = Path.ChangeExtension(entry.Name, content_ext); } dir.Add(entry); } foreach (PackedEntry entry in dir.Where(e => e.Size > 4)) { entry.IsPacked = file.View.AsciiEqual(entry.Offset, "DFLT"); if (entry.IsPacked) { entry.Size = file.View.ReadUInt32(entry.Offset + 4); entry.UnpackedSize = file.View.ReadUInt32(entry.Offset + 8); entry.Offset += 12; } else if (file.View.AsciiEqual(entry.Offset, "DATA")) { entry.Size = file.View.ReadUInt32(entry.Offset + 4); entry.UnpackedSize = entry.Size; entry.Offset += 8; if (string.IsNullOrEmpty(entry.Type)) { uint signature = file.View.ReadUInt32(entry.Offset); if (0x43614C66 == signature) // 'fLaC' { entry.Type = "audio"; entry.Name = Path.ChangeExtension(entry.Name, "flac"); } else { var res = AutoEntry.DetectFileType(signature); if (null != res) { entry.ChangeType(res); } } } } } return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { uint first_offset = file.View.ReadUInt32 (0); if (first_offset < 8 || first_offset >= file.MaxOffset) return null; int count = (int)(first_offset - 8) / 4; if (!IsSaneCount (count)) return null; var base_name = Path.GetFileNameWithoutExtension (file.Name); uint index_offset = 0; uint next_offset = first_offset; var dir = new List<Entry> (count); for (int i = 0; i < count; ++i) { var entry = new PackedEntry { Offset = next_offset }; index_offset += 4; next_offset = file.View.ReadUInt32 (index_offset); if (next_offset < entry.Offset) return null; entry.Size = (uint)(next_offset - entry.Offset); entry.UnpackedSize = entry.Size; if (entry.Size != 0) { if (!entry.CheckPlacement (file.MaxOffset)) return null; entry.Name = string.Format ("{0}#{1:D4}", base_name, i); dir.Add (entry); } } if (0 == dir.Count) return null; foreach (PackedEntry entry in dir) { if (entry.Size < 4) continue; uint unpacked_size = file.View.ReadUInt32 (entry.Offset); if (entry.Size > 8 && file.View.AsciiEqual (entry.Offset+4, "HDJ\0")) { if (file.View.AsciiEqual (entry.Offset+12, "BM")) { entry.Name = Path.ChangeExtension (entry.Name, "bmp"); entry.Type = "image"; } entry.UnpackedSize = unpacked_size; entry.IsPacked = true; } else if (entry.Size > 12 && file.View.AsciiEqual (entry.Offset+8, "RIFF")) { entry.Name = Path.ChangeExtension (entry.Name, "wav"); entry.Type = "audio"; entry.UnpackedSize = unpacked_size; entry.IsPacked = true; } else if (0x4D42 == (unpacked_size & 0xFFFF)) { entry.Name = Path.ChangeExtension (entry.Name, "bmp"); entry.Type = "image"; } } return new ArcFile (file, this, dir); }
public override ArcFile TryOpen(ArcView file) { if (!file.Name.EndsWith(".mgr", StringComparison.InvariantCultureIgnoreCase)) { return(null); } int count = file.View.ReadInt16(0); if (count <= 0 || count >= 0x100) { return(null); } uint current = 2; uint first_offset = current; if (count > 1) { first_offset = file.View.ReadUInt32(current); if (first_offset != 2 + count * 4) { return(null); } } if (!file.View.AsciiEqual(first_offset + 9, "BM")) { return(null); } string base_name = Path.GetFileNameWithoutExtension(file.Name); var dir = new List <Entry> (count); if (count > 1) { for (int i = 0; i < count; ++i) { var entry = new PackedEntry { Name = string.Format("{0}#{1:D4}.bmp", base_name, i), Type = "image", Offset = file.View.ReadUInt32(current), }; if (entry.Offset < first_offset || entry.Offset >= file.MaxOffset) { return(null); } dir.Add(entry); current += 4; } } else { dir.Add(new PackedEntry { Name = base_name + ".bmp", Type = "image", Offset = current }); } foreach (PackedEntry entry in dir) { entry.UnpackedSize = file.View.ReadUInt32(entry.Offset); entry.Size = file.View.ReadUInt32(entry.Offset + 4); entry.IsPacked = true; if (entry.UnpackedSize < 0x36 || entry.Size > file.MaxOffset - entry.Offset) { return(null); } entry.Offset += 8; } return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(0); if (!IsSaneCount(count)) { return(null); } uint first_offset = file.View.ReadUInt32(4); if (4 + count * 8 != first_offset) { return(null); } var base_name = Path.GetFileNameWithoutExtension(file.Name); bool is_msg = base_name == "msg"; uint index_offset = 4; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { uint offset = file.View.ReadUInt32(index_offset); uint size = file.View.ReadUInt32(index_offset + 4); var entry = new PackedEntry { Name = string.Format("{0}#{1:D5}", base_name, i), Offset = offset, Size = size, }; if (!is_msg && !entry.CheckPlacement(file.MaxOffset)) { return(null); } dir.Add(entry); index_offset += 8; } foreach (PackedEntry entry in dir) { if (is_msg) { uint size = file.View.ReadUInt32(entry.Offset); entry.Offset += 4; entry.UnpackedSize = entry.Size; entry.Size = size; entry.IsPacked = true; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } continue; } uint pos = file.View.ReadUInt32(entry.Offset + 4); if (pos > entry.Size) { continue; } uint unpacked_size = file.View.ReadUInt32(entry.Offset + 8); uint flags = unpacked_size >> 30; unpacked_size &= 0x3FFFFFFF; entry.IsPacked = 0 == flags; uint signature = 0; if (entry.IsPacked) { entry.UnpackedSize = unpacked_size; entry.Size = file.View.ReadUInt32(entry.Offset + pos); entry.Offset += pos + 4; if ((file.View.ReadByte(entry.Offset) & 0xF) == 0xF) { signature = file.View.ReadUInt32(entry.Offset + 1); } } else { entry.Size = unpacked_size; entry.Offset += pos; signature = file.View.ReadUInt32(entry.Offset); } var res = AutoEntry.DetectFileType(signature); if (res != null) { entry.ChangeType(res); } } return(new ArcFile(file, this, dir)); }
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)); }
public async Task <List <PackedEntry> > PackServerData(bool saveExecutable, ServerPresetPackMode mode, bool evbMode, CancellationToken cancellation) { var result = new List <PackedEntry>(); // Wrapper if (ProvideDetails && DetailsMode == ServerPresetDetailsMode.ViaWrapper) { if (saveExecutable) { string wrapper; switch (mode) { case ServerPresetPackMode.Linux32: wrapper = await LoadLinux32Wrapper(cancellation); break; case ServerPresetPackMode.Linux64: wrapper = await LoadLinux64Wrapper(cancellation); break; case ServerPresetPackMode.Windows: wrapper = await LoadWinWrapper(cancellation); break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null); } if (cancellation.IsCancellationRequested) { return(null); } if (wrapper == null) { throw new InformativeException("Can’t pack server", "Can’t load server wrapper."); } // Actual wrapper, compiled to a single exe-file result.Add(PackedEntry.FromFile( mode == ServerPresetPackMode.Windows ? @"acServerWrapper.exe" : @"acServerWrapper", wrapper)); // For EVB if (evbMode) { result.Add(PackedEntry.FromContent("arguments.json", new JArray { @"--copy-executable-to=acServer_tmp.exe", }.ToString(Formatting.Indented))); } } // Params var wrapperParams = _wrapperParamsJson?.DeepClone() as JObject; SetWrapperParams(ref wrapperParams); result.Add(PackedEntry.FromContent(@"cfg/cm_wrapper_params.json", wrapperParams.ToString(Formatting.Indented))); // Content if (DetailsContentJObject != null) { void ProcessPiece(JObject piece) { var file = (string)piece?[@"file"]; if (piece == null || file == null) { return; } var filename = Path.IsPathRooted(file) ? file : Path.Combine(WrapperContentDirectory, file); if (!FileUtils.ArePathsEqual(WrapperContentDirectory, Path.GetDirectoryName(filename))) { piece[@"file"] = Path.GetFileName(filename); } result.Add(PackedEntry.FromFile($"cfg/cm_content/{Path.GetFileName(filename)}", filename)); } void ProcessPieces(JToken token, string childrenKey = null) { if (!(token is JObject o)) { return; } foreach (var t in o) { var b = (JObject)t.Value; if (b == null) { continue; } ProcessPiece(b); if (childrenKey != null) { ProcessPieces(b[childrenKey]); } } } var content = DetailsContentJObject.DeepClone(); ProcessPieces(content[@"cars"], @"skins"); ProcessPiece(content[@"track"] as JObject); ProcessPieces(content[@"weather"]); result.Add(PackedEntry.FromContent("cfg/cm_content/content.json", content.ToString(Formatting.Indented))); } else { result.Add(PackedEntry.FromContent("cfg/cm_content/content.json", @"{}")); } } // Executable if (saveExecutable) { var serverDirectory = ServerPresetsManager.ServerDirectory; result.Add(PackedEntry.FromFile( mode == ServerPresetPackMode.Windows ? @"acServer.exe" : @"acServer", Path.Combine(serverDirectory, mode == ServerPresetPackMode.Windows ? @"acServer.exe" : @"acServer"))); } // Main config file var serverCfg = IniObject?.Clone() ?? new IniFile(IniFileMode.ValuesWithSemicolons); var dataSection = serverCfg["DATA"]; SaveData(serverCfg); if (ProvideDetails) { if (DetailsMode == ServerPresetDetailsMode.ViaWrapper) { serverCfg["SERVER"].Set("NAME", $"{Name} {ServerEntry.ExtendedSeparator}{WrapperPort}"); } else { await EnsureDetailsNameIsActualAsync(serverCfg); } } // Welcome message if (!string.IsNullOrEmpty(WelcomeMessage)) { result.Add(PackedEntry.FromContent("cfg/welcome.txt", WelcomeMessage)); serverCfg["SERVER"].Set("WELCOME_MESSAGE", "cfg/welcome.txt"); dataSection.Set("WELCOME_PATH", "cfg/welcome.txt"); } // Setups var setupIndex = 0; foreach (var key in dataSection.Keys.Where(x => x.StartsWith(@"FIXED_SETUP_")).ToList()) { dataSection.Remove(key); } foreach (var item in SetupItems) { if (!File.Exists(item.Filename)) { continue; } var name = $@"cfg/setup_{setupIndex}_{item.CarId}.ini"; result.Add(PackedEntry.FromFile(name, item.Filename)); dataSection[@"FIXED_SETUP_" + setupIndex] = $@"{(item.IsDefault ? @"1" : @"0")}|{name}"; setupIndex++; } result.Add(PackedEntry.FromContent("cfg/server_cfg.ini", serverCfg.Stringify())); // Entry list var entryList = EntryListIniObject?.Clone() ?? new IniFile(); entryList.SetSections("CAR", DriverEntries, (entry, section) => entry.SaveTo(section)); result.Add(PackedEntry.FromContent("cfg/entry_list.ini", entryList.Stringify())); // Cars var root = AcRootDirectory.Instance.RequireValue; for (var i = 0; i < CarIds.Length; i++) { var carId = CarIds[i]; var packedData = Path.Combine(AcPaths.GetCarDirectory(root, carId), "data.acd"); if (File.Exists(packedData)) { result.Add(PackedEntry.FromFile(Path.Combine(@"content", @"cars", carId, @"data.acd"), packedData)); } } // Track var localPath = TrackLayoutId != null?Path.Combine(TrackId, TrackLayoutId) : TrackId; foreach (var file in TrackDataToKeep) { var actualData = Path.Combine(AcPaths.GetTracksDirectory(root), localPath, @"data", file); if (File.Exists(actualData)) { result.Add(PackedEntry.FromFile(Path.Combine(@"content", @"tracks", localPath, @"data", file), actualData)); } } // System var systemSurfaces = Path.Combine(ServerPresetsManager.ServerDirectory, "system", "data", "surfaces.ini"); if (File.Exists(systemSurfaces)) { result.Add(PackedEntry.FromFile("system/data/surfaces.ini", systemSurfaces)); } return(result); }
public override ArcFile TryOpen(ArcView file) { int version = file.View.ReadByte (3) - '0'; int count = file.View.ReadInt32 (4); if (!IsSaneCount (count)) return null; int index_offset = 8; var index = new List<Tuple<int, int>> (count); for (int i = 0; i < count; ++i) { int size = file.View.ReadInt32 (index_offset); int offset = file.View.ReadInt32 (index_offset+4); index_offset += 8; if (size != 0) index.Add (Tuple.Create (offset, size)); } var dir = new List<Entry>(); foreach (var section in index) { index_offset = section.Item1; for (int section_size = section.Item2; section_size > 0; ) { int entry_size = file.View.ReadByte (index_offset); if (entry_size < 5) break; var entry = new PackedEntry { Offset = Binary.BigEndian (file.View.ReadUInt32 (index_offset+1)), Name = file.View.ReadString (index_offset+5, (uint)entry_size-5), }; if (entry.Offset > file.MaxOffset) return null; index_offset += entry_size; section_size -= entry_size; dir.Add (entry); } } DetectFileTypes (file, dir); return new ArcFile (file, this, dir); }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32 (4); if (!IsSaneCount (count)) return null; long next_offset = file.View.ReadUInt32 (8); uint index_offset = 0xC; var dir = new List<Entry> (count); for (int i = 0; i < count; ++i) { if (next_offset > file.MaxOffset) return null; var entry = new PackedEntry { Name = i.ToString ("D5"), Offset = next_offset, }; next_offset = i + 1 == count ? file.MaxOffset : file.View.ReadUInt32 (index_offset); index_offset += 4; entry.Size = (uint)(next_offset - entry.Offset); dir.Add (entry); } DetectFileTypes (file, dir); return new ArcFile (file, this, dir); }
uint WriteImageEntry(PackedEntry entry, Stream input, Stream output) { var grp = s_grp_format.Value; if (null == grp) // probably never happens throw new FileFormatException ("GRP image encoder not available"); bool is_grp = grp.Signature == FormatCatalog.ReadSignature (input); input.Position = 0; var start = output.Position; using (var zstream = new ZLibStream (output, CompressionMode.Compress, CompressionLevel.Level9, true)) { if (is_grp) { input.CopyTo (zstream); } else { var image = ImageFormat.Read (input); if (null == image) throw new InvalidFormatException (string.Format (arcStrings.MsgInvalidImageFormat, entry.Name)); grp.Write (zstream, image); entry.UnpackedSize = (uint)zstream.TotalIn; } } return (uint)(output.Position - start); }
Stream OpenTpw(ArcFile arc, PackedEntry entry) { var output = new byte[entry.UnpackedSize]; using (var input = arc.File.CreateStream(entry.Offset, entry.Size)) { input.Position = 8; var offsets = new int[4]; offsets[0] = input.ReadUInt16(); offsets[1] = offsets[0] * 2; offsets[2] = offsets[0] * 3; offsets[3] = offsets[0] * 4; int dst = 0; while (dst < output.Length) { byte ctl = input.ReadUInt8(); if (0 == ctl) { break; } int count; if (ctl < 0x40) { input.Read(output, dst, ctl); dst += ctl; } else if (ctl <= 0x6F) { if (0x6F == ctl) { count = input.ReadUInt16(); } else { count = (ctl + 0xC3) & 0xFF; } byte v = input.ReadUInt8(); while (count-- > 0) { output[dst++] = v; } } else if (ctl <= 0x9F) { if (ctl == 0x9F) { count = input.ReadUInt16(); } else { count = (ctl + 0x92) & 0xFF; } byte v1 = input.ReadUInt8(); byte v2 = input.ReadUInt8(); while (count-- > 0) { output[dst++] = v1; output[dst++] = v2; } } else if (ctl <= 0xBF) { if (ctl == 0xBF) { count = input.ReadUInt16(); } else { count = ((ctl + 0x62) & 0xFF); } input.Read(output, dst, 3); if (count > 0) { count *= 3; Binary.CopyOverlapped(output, dst, dst + 3, count - 3); dst += count; } } else { count = (ctl & 0x3F) + 3; int offset = input.ReadUInt8(); offset = (offset & 0x3F) - offsets[offset >> 6]; Binary.CopyOverlapped(output, dst + offset, dst, count); dst += count; } } return(new BinMemoryStream(output, entry.Name)); } }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(0); if (!IsSaneCount(count)) { return(null); } long offset = 4 + count * 4; if (offset >= file.MaxOffset) { return(null); } uint index_offset = 4; var dir = new List <Entry>(); for (int i = 0; i < count; ++i) { uint size = file.View.ReadUInt32(index_offset); if (0 != size) { var entry = new PackedEntry { Name = i.ToString("D5"), Offset = offset, Size = size, IsPacked = false, }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } dir.Add(entry); offset += size; } index_offset += 4; } if (offset != file.MaxOffset || 0 == dir.Count) { return(null); } byte[] preview = new byte[16]; byte[] sign_buf = new byte[4]; foreach (PackedEntry entry in dir) { uint extra = 6; if (extra > entry.Size) { continue; } int label = file.View.ReadUInt16(entry.Offset); if (1 == label) { entry.IsPacked = true; entry.UnpackedSize = file.View.ReadUInt32(entry.Offset + 2); } entry.Offset += extra; entry.Size -= extra; uint signature; if (entry.IsPacked) { file.View.Read(entry.Offset, preview, 0, (uint)preview.Length); using (var input = new MemoryStream(preview)) { LzssUnpack(input, sign_buf); signature = LittleEndian.ToUInt32(sign_buf, 0); } } else { signature = file.View.ReadUInt32(entry.Offset); } if (0 != signature) { SetEntryType(entry, signature); } } return(new ArcFile(file, this, dir)); }