public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(0); if ((count & 0xFFFF) != 0) { return(null); } count = (count >> 16) - 1; if (!IsSaneCount(count)) { return(null); } uint index_offset = 0xC; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { var name = file.View.ReadUInt32(index_offset).ToString("D5"); var entry = new PackedEntry { Name = name, Offset = file.View.ReadUInt32(index_offset + 4) << 11, Size = file.View.ReadUInt32(index_offset + 8), }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } dir.Add(entry); index_offset += 12; } foreach (PackedEntry entry in dir) { uint signature; if (entry.Size > 13 && file.View.AsciiEqual(entry.Offset + 2, "ike")) { int unpacked_size = IkeReader.DecodeSize(file.View.ReadByte(entry.Offset + 10), file.View.ReadByte(entry.Offset + 11), file.View.ReadByte(entry.Offset + 12)); entry.IsPacked = true; entry.UnpackedSize = (uint)unpacked_size; signature = file.View.ReadUInt32(entry.Offset + 0xF); entry.Offset += 13; entry.Size -= 13; } else { signature = file.View.ReadUInt32(entry.Offset); } entry.ChangeType(AutoEntry.DetectFileType(signature)); } return(new ArcFile(file, this, dir)); }
public override ArcFile TryOpen(ArcView file) { int count = file.View.ReadInt32(0); if (!IsSaneCount(count)) { return(null); } var base_name = Path.GetFileNameWithoutExtension(file.Name); int index_offset = 4; int index_end = 4 + 8 * count; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { var entry = new PackedEntry { Offset = file.View.ReadUInt32(index_offset), Size = file.View.ReadUInt32(index_offset + 4), }; if (entry.Offset < index_end || !entry.CheckPlacement(file.MaxOffset)) { return(null); } entry.Name = string.Format("{0}#{1:D5}", base_name, i); dir.Add(entry); index_offset += 8; } foreach (PackedEntry entry in dir) { var n = file.View.ReadInt32(entry.Offset); if (n <= 0) { return(null); } var offset = file.View.ReadUInt32(entry.Offset + 4); var size = file.View.ReadUInt32(entry.Offset + 8); entry.Offset += offset; entry.Size = size & 0x3FFFFFFF; entry.IsPacked = 2 != (size >> 30); if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } var res = AutoEntry.DetectFileType(file.View.ReadUInt32(entry.Offset)); if (res != null) { entry.ChangeType(res); } } 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.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) { 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)); }