diff --git a/ArcFormats/AZSys/ArcAZSys.cs b/ArcFormats/AZSys/ArcAZSys.cs index b8b96704..53d6c7af 100644 --- a/ArcFormats/AZSys/ArcAZSys.cs +++ b/ArcFormats/AZSys/ArcAZSys.cs @@ -2,7 +2,7 @@ //! \date Wed Apr 22 09:52:23 2015 //! \brief AZ system archive implementation. // -// Copyright (C) 2015 by morkt +// Copyright (C) 2015-2016 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 @@ -28,11 +28,34 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.IO; using GameRes.Compression; +using GameRes.Formats.Properties; using GameRes.Formats.Strings; using GameRes.Utility; namespace GameRes.Formats.AZSys { + [Serializable] + public class AsbScheme : ResourceScheme + { + public Dictionary KnownKeys; + } + + internal class AsbOptions : ResourceOptions + { + public uint AsbKey; + } + + internal class AsbArchive : ArcFile + { + public readonly uint Key; + + public AsbArchive (ArcView arc, ArchiveFormat impl, ICollection dir, uint key) + : base (arc, impl, dir) + { + Key = key; + } + } + [Export(typeof(ArchiveFormat))] public class ArcOpener : ArchiveFormat { @@ -47,6 +70,14 @@ namespace GameRes.Formats.AZSys Extensions = new string[] { "arc" }; } + public static Dictionary KnownKeys = new Dictionary(); + + public override ResourceScheme Scheme + { + get { return new AsbScheme { KnownKeys = KnownKeys }; } + set { KnownKeys = ((AsbScheme)value).KnownKeys; } + } + public override ArcFile TryOpen (ArcView file) { int ext_count = file.View.ReadInt32 (4); @@ -65,6 +96,7 @@ namespace GameRes.Formats.AZSys var reader = new IndexReader (packed_index, count); var index = reader.Unpack(); int index_offset = 0; + bool contains_scripts = false; var dir = new List (count); for (int i = 0; i < count; ++i) { @@ -75,21 +107,27 @@ namespace GameRes.Formats.AZSys entry.Offset = base_offset + LittleEndian.ToUInt32 (index, index_offset); entry.Size = LittleEndian.ToUInt32 (index, index_offset + 4); if (entry.CheckPlacement (file.MaxOffset)) + { dir.Add (entry); + contains_scripts = contains_scripts || name.EndsWith (".asb", StringComparison.InvariantCultureIgnoreCase); + } } index_offset += 0x40; } if (0 == dir.Count) return null; - return new ArcFile (file, this, dir); + if (!contains_scripts || 0 == KnownKeys.Count) + return new ArcFile (file, this, dir); + var options = Query (arcStrings.ArcEncryptedNotice); + if (0 == options.AsbKey) + return new ArcFile (file, this, dir); + return new AsbArchive (file, this, dir, options.AsbKey); } - static readonly uint[] KnownKeys = new uint[] { 0x1de71cb9 }; // Triptych - public override Stream OpenEntry (ArcFile arc, Entry entry) { - if (entry.Size < 20 - || !entry.Name.EndsWith (".asb", StringComparison.InvariantCultureIgnoreCase) + var azarc = arc as AsbArchive; + if (null == azarc || entry.Size < 20 || !arc.File.View.AsciiEqual (entry.Offset, "ASB\x1a")) return arc.File.CreateStream (entry.Offset, entry.Size); uint packed = arc.File.View.ReadUInt32 (entry.Offset+4); @@ -97,7 +135,7 @@ namespace GameRes.Formats.AZSys if (12 + packed != entry.Size) return arc.File.CreateStream (entry.Offset, entry.Size); - uint key = KnownKeys[0] ^ unpacked; + uint key = azarc.Key ^ unpacked; key ^= ((key << 12) | key) << 11; uint first = arc.File.View.ReadUInt16 (entry.Offset+16); @@ -121,6 +159,24 @@ namespace GameRes.Formats.AZSys return new ZLibStream (new MemoryStream (input, 4, input.Length-4), CompressionMode.Decompress); } + public override ResourceOptions GetDefaultOptions () + { + return new AsbOptions { AsbKey = GetAsbKey (Settings.Default.AZScriptScheme) }; + } + + public override object GetAccessWidget () + { + return new GUI.WidgetAZ(); + } + + uint GetAsbKey (string scheme) + { + uint key; + if (KnownKeys.TryGetValue (scheme, out key)) + return key; + return 0; + } + internal class IndexReader { byte[] m_input; diff --git a/ArcFormats/AZSys/WidgetAZ.xaml b/ArcFormats/AZSys/WidgetAZ.xaml new file mode 100644 index 00000000..0d10c1d4 --- /dev/null +++ b/ArcFormats/AZSys/WidgetAZ.xaml @@ -0,0 +1,7 @@ + + + diff --git a/ArcFormats/AZSys/WidgetAZ.xaml.cs b/ArcFormats/AZSys/WidgetAZ.xaml.cs new file mode 100644 index 00000000..6b908a51 --- /dev/null +++ b/ArcFormats/AZSys/WidgetAZ.xaml.cs @@ -0,0 +1,19 @@ +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using GameRes.Formats.AZSys; + +namespace GameRes.Formats.GUI +{ + /// + /// Interaction logic for WidgetAZ.xaml + /// + public partial class WidgetAZ : StackPanel + { + public WidgetAZ() + { + InitializeComponent(); + Scheme.ItemsSource = ArcOpener.KnownKeys.Keys.OrderBy (x => x); + } + } +} diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index c2b72d2a..d924c796 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -68,6 +68,9 @@ + + WidgetAZ.xaml + @@ -489,6 +492,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/ArcFormats/Properties/Settings.Designer.cs b/ArcFormats/Properties/Settings.Designer.cs index 2bfbf676..374e085c 100644 --- a/ArcFormats/Properties/Settings.Designer.cs +++ b/ArcFormats/Properties/Settings.Designer.cs @@ -501,5 +501,17 @@ namespace GameRes.Formats.Properties { this["ZIPEncodingCP"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string AZScriptScheme { + get { + return ((string)(this["AZScriptScheme"])); + } + set { + this["AZScriptScheme"] = value; + } + } } } diff --git a/ArcFormats/Properties/Settings.settings b/ArcFormats/Properties/Settings.settings index 87049644..a4bf7820 100644 --- a/ArcFormats/Properties/Settings.settings +++ b/ArcFormats/Properties/Settings.settings @@ -122,5 +122,8 @@ 932 + + + \ No newline at end of file diff --git a/ArcFormats/app.config b/ArcFormats/app.config index 5f06f0cb..f3cb6ae3 100644 --- a/ArcFormats/app.config +++ b/ArcFormats/app.config @@ -124,6 +124,9 @@ 932 + + +