diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj
index 7794eb1b..7e7fdf44 100644
--- a/ArcFormats/ArcFormats.csproj
+++ b/ArcFormats/ArcFormats.csproj
@@ -216,6 +216,9 @@
Code
WidgetLPK.xaml
+
+ WidgetMBL.xaml
+
WidgetNOA.xaml
@@ -320,6 +323,10 @@
MSBuild:Compile
Designer
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/ArcFormats/ArcMBL.cs b/ArcFormats/ArcMBL.cs
index fb6e1119..4e394a6b 100644
--- a/ArcFormats/ArcMBL.cs
+++ b/ArcFormats/ArcMBL.cs
@@ -28,10 +28,28 @@ using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
+using GameRes.Formats.Properties;
+using GameRes.Formats.Strings;
using GameRes.Utility;
namespace GameRes.Formats.Marble
{
+ public class MblOptions : ResourceOptions
+ {
+ public string PassPhrase;
+ }
+
+ public class MblArchive : ArcFile
+ {
+ public readonly byte[] Key;
+
+ public MblArchive (ArcView arc, ArchiveFormat impl, ICollection dir, string password)
+ : base (arc, impl, dir)
+ {
+ Key = Encodings.cp932.GetBytes (password);
+ }
+ }
+
[Export(typeof(ArchiveFormat))]
public class MblOpener : ArchiveFormat
{
@@ -64,6 +82,7 @@ namespace GameRes.Formats.Marble
return null;
try
{
+ bool contains_scripts = false;
var dir = new List (count);
for (int i = 0; i < count; ++i)
{
@@ -79,13 +98,22 @@ namespace GameRes.Formats.Marble
name = name.ToLowerInvariant();
index_offset += (uint)filename_len;
uint offset = file.View.ReadUInt32 (index_offset);
- var entry = new AutoEntry (name, () => {
- uint signature = file.View.ReadUInt32 (offset);
- var res = FormatCatalog.Instance.LookupSignature (signature);
- if (!res.Any() && 0x4259 == (0xffff & signature))
- res = FormatCatalog.Instance.ImageFormats.Where (x => x.Tag == "PRS");
- return res.FirstOrDefault();
- });
+ Entry entry;
+ if (name.EndsWith (".s"))
+ {
+ entry = new Entry { Name = name, Type = "script" };
+ contains_scripts = true;
+ }
+ else
+ {
+ entry = new AutoEntry (name, () => {
+ uint signature = file.View.ReadUInt32 (offset);
+ var res = FormatCatalog.Instance.LookupSignature (signature);
+ if (!res.Any() && 0x4259 == (0xffff & signature))
+ res = FormatCatalog.Instance.ImageFormats.Where (x => x.Tag == "PRS");
+ return res.FirstOrDefault();
+ });
+ }
entry.Offset = offset;
entry.Size = file.View.ReadUInt32 (index_offset+4);
if (offset < index_size || !entry.CheckPlacement (file.MaxOffset))
@@ -95,6 +123,12 @@ namespace GameRes.Formats.Marble
}
if (0 == dir.Count)
return null;
+ if (contains_scripts)
+ {
+ var options = Query ("Archive contains encrypted scripts.\nChoose encryption scheme or enter a passphrase.");
+ if (options.PassPhrase.Length > 0)
+ return new MblArchive (file, this, dir, options.PassPhrase);
+ }
return new ArcFile (file, this, dir);
}
catch
@@ -102,5 +136,44 @@ namespace GameRes.Formats.Marble
return null;
}
}
+
+ public static Dictionary KnownKeys = new Dictionary {
+ { arcStrings.ArcDefault, "" },
+ { "Chikatetsu Fuusa Jiken", "naze" }
+ };
+
+ public override Stream OpenEntry (ArcFile arc, Entry entry)
+ {
+ if (entry.Type != "script" || !entry.Name.EndsWith (".s"))
+ return arc.File.CreateStream (entry.Offset, entry.Size);
+ var marc = arc as MblArchive;
+ var data = new byte[entry.Size];
+ arc.File.View.Read (entry.Offset, data, 0, entry.Size);
+ if (null == marc || null == marc.Key)
+ {
+ for (int i = 0; i < data.Length; ++i)
+ {
+ data[i] = (byte)-data[i];
+ }
+ }
+ else
+ {
+ for (int i = 0; i < data.Length; ++i)
+ {
+ data[i] ^= marc.Key[i % marc.Key.Length];
+ }
+ }
+ return new MemoryStream (data);
+ }
+
+ public override ResourceOptions GetDefaultOptions ()
+ {
+ return new MblOptions { PassPhrase = Settings.Default.MBLPassPhrase };
+ }
+
+ public override object GetAccessWidget ()
+ {
+ return new GUI.WidgetMBL();
+ }
}
}
diff --git a/ArcFormats/Properties/Settings.Designer.cs b/ArcFormats/Properties/Settings.Designer.cs
index 10de39ac..75a85724 100644
--- a/ArcFormats/Properties/Settings.Designer.cs
+++ b/ArcFormats/Properties/Settings.Designer.cs
@@ -357,5 +357,17 @@ namespace GameRes.Formats.Properties {
this["DPKLastScheme"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string MBLPassPhrase {
+ get {
+ return ((string)(this["MBLPassPhrase"]));
+ }
+ set {
+ this["MBLPassPhrase"] = value;
+ }
+ }
}
}
diff --git a/ArcFormats/Properties/Settings.settings b/ArcFormats/Properties/Settings.settings
index 5cdab448..eaf3d888 100644
--- a/ArcFormats/Properties/Settings.settings
+++ b/ArcFormats/Properties/Settings.settings
@@ -86,5 +86,8 @@
+
+
+
\ No newline at end of file
diff --git a/ArcFormats/Strings/arcStrings.Designer.cs b/ArcFormats/Strings/arcStrings.Designer.cs
index 4ba844ff..244899de 100644
--- a/ArcFormats/Strings/arcStrings.Designer.cs
+++ b/ArcFormats/Strings/arcStrings.Designer.cs
@@ -279,6 +279,15 @@ namespace GameRes.Formats.Strings {
}
}
+ ///
+ /// Looks up a localized string similar to Archive contains encrypted scripts.Choose encryption scheme or enter a passphrase..
+ ///
+ public static string MBLNotice {
+ get {
+ return ResourceManager.GetString("MBLNotice", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Adding file.
///
diff --git a/ArcFormats/Strings/arcStrings.resx b/ArcFormats/Strings/arcStrings.resx
index 1d26a4d3..75b2b4b9 100644
--- a/ArcFormats/Strings/arcStrings.resx
+++ b/ArcFormats/Strings/arcStrings.resx
@@ -318,4 +318,8 @@ Enter archive encryption key.
Default
-
\ No newline at end of file
+
+ Archive contains encrypted scripts.
+Choose encryption scheme or enter a passphrase.
+
+
diff --git a/ArcFormats/Strings/arcStrings.ru-RU.resx b/ArcFormats/Strings/arcStrings.ru-RU.resx
index 02a5194c..02393dd6 100644
--- a/ArcFormats/Strings/arcStrings.ru-RU.resx
+++ b/ArcFormats/Strings/arcStrings.ru-RU.resx
@@ -174,6 +174,10 @@
Вариант
+
+ Архив содержит зашифрованные скрипты.
+Выберите способ шифрования или введите текстовый пароль.
+
Добавляется файл
diff --git a/ArcFormats/WidgetMBL.xaml b/ArcFormats/WidgetMBL.xaml
new file mode 100644
index 00000000..1ca9e3b3
--- /dev/null
+++ b/ArcFormats/WidgetMBL.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
diff --git a/ArcFormats/WidgetMBL.xaml.cs b/ArcFormats/WidgetMBL.xaml.cs
new file mode 100644
index 00000000..46c8be9f
--- /dev/null
+++ b/ArcFormats/WidgetMBL.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace GameRes.Formats.GUI
+{
+ ///
+ /// Interaction logic for WidgetMBL.xaml
+ ///
+ public partial class WidgetMBL : Grid
+ {
+ public WidgetMBL ()
+ {
+ InitializeComponent ();
+ }
+ }
+}
diff --git a/ArcFormats/app.config b/ArcFormats/app.config
index 390df4ea..dddbbe5b 100644
--- a/ArcFormats/app.config
+++ b/ArcFormats/app.config
@@ -88,6 +88,9 @@
+
+
+