diff --git a/ArcFormats/ArcISA.cs b/ArcFormats/ArcISA.cs index ca2d748e..86f44f7b 100644 --- a/ArcFormats/ArcISA.cs +++ b/ArcFormats/ArcISA.cs @@ -2,7 +2,7 @@ //! \date Tue Mar 17 09:21:03 2015 //! \brief ISM engine resource archive. // -// Copyright (C) 2015 by morkt +// Copyright (C) 2015-2018 by morkt // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -47,23 +47,50 @@ namespace GameRes.Formats.ISM int version = file.View.ReadUInt16 (0x0E); bool is_encrypted = (version & 0x8000) != 0; version &= 0x7FFF; + var reader = new IsaIndexReader (file, count); + List dir = null; + if (version != 1) + dir = reader.ReadIndex (0x0C, 0x14); + if (null == dir) + dir = reader.ReadIndex (0x30, 0x10); + if (null == dir) + return null; + return new ArcFile (file, this, dir); + } + } + + internal class IsaIndexReader + { + ArcView m_file; + List m_dir; + int m_count; + + public IsaIndexReader (ArcView file, int count) + { + m_file = file; + m_dir = new List (count); + m_count = count; + } + + public List ReadIndex (uint name_length, uint record_length) + { + m_dir.Clear(); uint index_offset = 0x10; - uint name_length = 1 == version ? 0x30u : 0x0Cu; - uint record_length = 1 == version ? 0x10u : 0x14u; - var dir = new List (count); - for (int i = 0; i < count; ++i) + for (int i = 0; i < m_count; ++i) { - var name = file.View.ReadString (index_offset, name_length); + var name = m_file.View.ReadString (index_offset, name_length); + if (0 == name.Length) + return null; var entry = FormatCatalog.Instance.Create (name); index_offset += name_length; - entry.Offset = file.View.ReadUInt32 (index_offset+4); - entry.Size = file.View.ReadUInt32 (index_offset+8); - if (!entry.CheckPlacement (file.MaxOffset)) + entry.Offset = m_file.View.ReadUInt32 (index_offset+4); + entry.Size = m_file.View.ReadUInt32 (index_offset+8); + if (!entry.CheckPlacement (m_file.MaxOffset)) return null; - dir.Add (entry); + m_dir.Add (entry); index_offset += record_length; } - return new ArcFile (file, this, dir); + return m_dir; } unsafe void DecryptIndex (byte[] data)