diff --git a/GameRes/ArcFile.cs b/GameRes/ArcFile.cs index 8911d4f3..5cd0d1e5 100644 --- a/GameRes/ArcFile.cs +++ b/GameRes/ArcFile.cs @@ -43,6 +43,9 @@ namespace GameRes /// Short archive format description. public string Description { get { return m_interface.Description; } } + /// Tags of formats related to this archive format (could be null). + public IEnumerable ContainedFormats { get { return m_interface.ContainedFormats; } } + /// Memory-mapped view of the archive. public ArcView File { get { return m_arc; } } diff --git a/GameRes/ArchiveFormat.cs b/GameRes/ArchiveFormat.cs index 00a989b3..6a5ca538 100644 --- a/GameRes/ArchiveFormat.cs +++ b/GameRes/ArchiveFormat.cs @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; namespace GameRes { @@ -41,8 +42,34 @@ namespace GameRes /// public abstract bool IsHierarchic { get; } + /// + /// Tags of formats related to this archive format (could be null). + /// + public IEnumerable ContainedFormats { get; protected set; } + public abstract ArcFile TryOpen (ArcView view); + /// + /// Create GameRes.Entry corresponding to extension. + /// + /// May be thrown if filename contains invalid + /// characters. + public EntryType Create (string filename) where EntryType : Entry, new() + { + EntryType entry = null; + var formats = FormatCatalog.Instance.LookupFileName (filename); + if (formats.Any()) + { + if (ContainedFormats != null && ContainedFormats.Any()) + formats = formats.OrderByDescending (f => ContainedFormats.Contains (f.Tag)); + entry = new EntryType { Type = formats.First().Type }; + } + if (null == entry) + entry = new EntryType(); + entry.Name = filename; + return entry; + } + /// /// Extract file referenced by into current directory. /// diff --git a/GameRes/FormatCatalog.cs b/GameRes/FormatCatalog.cs index 7b46a4fa..1e2c520a 100644 --- a/GameRes/FormatCatalog.cs +++ b/GameRes/FormatCatalog.cs @@ -239,6 +239,13 @@ namespace GameRes { var ext = new Lazy (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant(), false); var tried = Enumerable.Empty(); + IEnumerable preferred = null; + if (VFS.IsVirtual) + { + var arc_fs = VFS.Top as ArchiveFileSystem; + if (arc_fs != null) + preferred = arc_fs.Source.ContainedFormats; + } for (;;) { var range = LookupSignature (signature); @@ -247,6 +254,8 @@ namespace GameRes // check formats that match filename extension first if (range.Skip (1).Any()) // if range.Count() > 1 range = range.OrderByDescending (f => f.Extensions.Any (e => e == ext.Value)); + if (preferred != null && preferred.Any()) + range = range.OrderByDescending (f => preferred.Contains (f.Tag)); foreach (var impl in range) { yield return impl; @@ -268,7 +277,7 @@ namespace GameRes EntryType entry = null; var formats = LookupFileName (filename); if (formats.Any()) - entry = formats.First().Create(); + entry = new EntryType { Type = formats.First().Type }; if (null == entry) entry = new EntryType(); entry.Name = filename; diff --git a/GameRes/GameRes.cs b/GameRes/GameRes.cs index 30958893..aa0f82b2 100644 --- a/GameRes/GameRes.cs +++ b/GameRes/GameRes.cs @@ -109,14 +109,6 @@ namespace GameRes /// Resource access scheme suitable for serialization. public virtual ResourceScheme Scheme { get; set; } - /// - /// Create empty Entry that corresponds to implemented resource. - /// - public EntryType Create () where EntryType : Entry, new() - { - return new EntryType { Type = this.Type }; - } - protected IResource () { Extensions = new string[] { GetDefaultExtension() };