public Parser(IBinaryStream file) { m_file = file; m_is_bigendian = 0x2a004d4d == m_file.Signature; if (m_is_bigendian) { ReadUInt16 = () => Binary.BigEndian(m_file.ReadUInt16()); ReadUInt32 = () => Binary.BigEndian(m_file.ReadUInt32()); ReadUInt64 = () => Binary.BigEndian(m_file.ReadUInt64()); } else { ReadUInt16 = () => m_file.ReadUInt16(); ReadUInt32 = () => m_file.ReadUInt32(); ReadUInt64 = () => m_file.ReadUInt64(); } m_first_ifd = file.ReadHeader(8).ToUInt32(4); }
public List <Entry> Deserialize() { m_index.Position = 8; int count = Binary.BigEndian(m_index.ReadInt32()); m_name_list = new string[count]; for (int i = 0; i < count; ++i) { int length = m_index.ReadUInt8(); m_name_list[i] = m_index.ReadCString(length, Encoding.UTF8); } count = Binary.BigEndian(m_index.ReadInt32()); m_dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { m_index.ReadUInt16(); ushort flags = Binary.BigEndian(m_index.ReadUInt16()); uint offset = Binary.BigEndian(m_index.ReadUInt32()); uint size = Binary.BigEndian(m_index.ReadUInt32()); var entry = new SxEntry { Flags = flags, Offset = (long)offset << 4, Size = size, IsPacked = 0 != (flags & 0x03), }; if (!entry.CheckPlacement(m_max_offset)) { return(null); } m_dir.Add(entry); } count = Binary.BigEndian(m_index.ReadUInt16()); for (int i = 0; i < count; ++i) { m_index.ReadUInt32(); m_index.ReadUInt32(); m_index.ReadUInt32(); Binary.BigEndian(m_index.ReadUInt32()); // archive body length m_index.ReadUInt64(); m_index.Seek(16, SeekOrigin.Current); // MD5 sum } count = Binary.BigEndian(m_index.ReadUInt16()); if (count > 0) { m_index.Seek(count * 24, SeekOrigin.Current); } DeserializeTree(); return(m_dir); }
internal static object ReadField(this IBinaryStream input, FieldInfo field) { var field_type = field.FieldType; var type_code = Type.GetTypeCode(field_type); switch (type_code) { case TypeCode.SByte: return(input.ReadInt8()); case TypeCode.Byte: return(input.ReadUInt8()); case TypeCode.Int16: return(input.ReadInt16()); case TypeCode.UInt16: return(input.ReadUInt16()); case TypeCode.Int32: return(input.ReadInt32()); case TypeCode.UInt32: return(input.ReadUInt32()); case TypeCode.Int64: return(input.ReadInt64()); case TypeCode.UInt64: return(input.ReadUInt64()); case TypeCode.Char: return((char)input.ReadInt16()); case TypeCode.String: var cstring_attr = field.GetCustomAttribute <CStringAttribute>(); if (cstring_attr != null) { var encoding = cstring_attr.Encoding ?? Encodings.cp932; if (cstring_attr.IsLengthDefined) { return(input.ReadCString(cstring_attr.Length, encoding)); } else { return(input.ReadCString(encoding)); } } throw new FormatException("Serialization method for string field is not defined."); case TypeCode.Object: object val = Activator.CreateInstance(field_type); ReadStruct(input, field_type, ref val); // FIXME check object graph for cycles return(val); default: throw new NotSupportedException("Not supported serialization type."); } }
internal IEnumerable <ArcDatEntry> ReadIndex(IBinaryStream input, int count, Scheme scheme, uint key = 0) { int skipped = 0; var file_map = ReadFilenameMap(scheme); for (int i = 0; i < count; ++i) { var hash = input.ReadUInt64(); var entry = new ArcDatEntry { Hash = hash, Flags = input.ReadByte() ^ (byte)hash, Offset = input.ReadUInt32() ^ (uint)hash ^ key, Size = input.ReadUInt32() ^ (uint)hash, UnpackedSize = input.ReadUInt32() ^ (uint)hash, }; entry.IsPacked = 0 != (entry.Flags & 2); byte[] raw_name = null; if (file_map.TryGetValue(hash, out raw_name)) { entry.Name = Encodings.cp932.GetString(raw_name); entry.Type = FormatCatalog.Instance.GetTypeFromName(entry.Name); entry.RawName = raw_name; } if (0 == (entry.Flags & 2)) { if (null == raw_name) { // System.Diagnostics.Trace.WriteLine ("Unknown hash", hash.ToString ("X16")); ++skipped; continue; } entry.Offset ^= raw_name[raw_name.Length >> 1]; entry.Size ^= raw_name[raw_name.Length >> 2]; entry.UnpackedSize ^= raw_name[raw_name.Length >> 3]; } if (string.IsNullOrEmpty(entry.Name)) { entry.Name = hash.ToString("X16"); } yield return(entry); } if (skipped != 0) { System.Diagnostics.Trace.WriteLine(string.Format("Missing {0} names", skipped), "[noncolor]"); } }