implemented '*_scr.med' archives decryption.

This commit is contained in:
morkt 2016-05-31 02:41:33 +04:00
parent acb32ac1fe
commit b18ede8684
7 changed files with 166 additions and 0 deletions

View File

@ -87,6 +87,9 @@
<Compile Include="Cri\ImageSPC.cs" />
<Compile Include="Cri\ImageXTX.cs" />
<Compile Include="DxLib\ArcMED.cs" />
<Compile Include="DxLib\WidgetSCR.xaml.cs">
<DependentUpon>WidgetSCR.xaml</DependentUpon>
</Compile>
<Compile Include="elf\ArcVOL.cs" />
<Compile Include="EmonEngine\ArcEME.cs" />
<Compile Include="EmonEngine\ImageBMP.cs" />
@ -532,6 +535,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="DxLib\WidgetSCR.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="FC01\WidgetMCG.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -27,9 +27,69 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using GameRes.Formats.Properties;
using GameRes.Formats.Strings;
using GameRes.Utility;
namespace GameRes.Formats.DxLib
{
public interface IScriptEncryption
{
int StartOffset { get; }
bool IsEncrypted (byte[] data);
void Decrypt (byte[] data, int offset, int length);
}
[Serializable]
public class FudegakiEncryption : IScriptEncryption
{
readonly byte[] Key;
public FudegakiEncryption (string keyword)
{
Key = Encodings.cp932.GetBytes (keyword);
}
public int StartOffset { get { return 0x10; } }
public bool IsEncrypted (byte[] data)
{
return LittleEndian.ToInt32 (data, 0) + 0x10 == data.Length && Key.Length > 0;
}
public void Decrypt (byte[] data, int offset, int length)
{
for (int i = 0; i < length; ++i)
{
data[offset+i] += Key[(offset+i) % Key.Length];
}
}
}
[Serializable]
public class MedOptions : ResourceOptions
{
public IScriptEncryption Encryption;
}
[Serializable]
public class ScrMedScheme : ResourceScheme
{
public Dictionary<string, IScriptEncryption> KnownSchemes;
}
internal class ScrMedArchive : ArcFile
{
public readonly IScriptEncryption Encryption;
public ScrMedArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, IScriptEncryption enc)
: base (arc, impl, dir)
{
Encryption = enc;
}
}
[Export(typeof(ArchiveFormat))]
public class MedOpener : ArchiveFormat
{
@ -41,6 +101,14 @@ namespace GameRes.Formats.DxLib
static readonly Lazy<ImageFormat> PrsFormat = new Lazy<ImageFormat> (() => ImageFormat.FindByTag ("PRS"));
public static Dictionary<string, IScriptEncryption> KnownSchemes = new Dictionary<string, IScriptEncryption>();
public override ResourceScheme Scheme
{
get { return new ScrMedScheme { KnownSchemes = KnownSchemes }; }
set { KnownSchemes = ((ScrMedScheme)value).KnownSchemes; }
}
public override ArcFile TryOpen (ArcView file)
{
if (!file.View.AsciiEqual (0, "MD"))
@ -72,7 +140,49 @@ namespace GameRes.Formats.DxLib
dir.Add (entry);
index_offset += 8;
}
var base_name = Path.GetFileNameWithoutExtension (file.Name);
if (base_name.EndsWith ("_scr", StringComparison.InvariantCultureIgnoreCase)
&& KnownSchemes.Count > 0)
{
var options = Query<MedOptions> (arcStrings.ArcEncryptedNotice);
if (options.Encryption != null)
return new ScrMedArchive (file, this, dir, options.Encryption);
}
return new ArcFile (file, this, dir);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
{
var scr_arc = arc as ScrMedArchive;
if (null == scr_arc || entry.Size <= scr_arc.Encryption.StartOffset)
return base.OpenEntry (arc, entry);
var data = arc.File.View.ReadBytes (entry.Offset, entry.Size);
if (scr_arc.Encryption.IsEncrypted (data))
{
var offset = scr_arc.Encryption.StartOffset;
scr_arc.Encryption.Decrypt (data, offset, data.Length-offset);
}
return new MemoryStream (data);
}
public override ResourceOptions GetDefaultOptions ()
{
return new MedOptions {
Encryption = GetEncryption (Settings.Default.MEDScriptScheme),
};
}
public override object GetAccessWidget ()
{
return new GUI.WidgetSCR();
}
public static IScriptEncryption GetEncryption (string scheme)
{
IScriptEncryption enc;
if (string.IsNullOrEmpty (scheme) || !KnownSchemes.TryGetValue (scheme, out enc))
return null;
return enc;
}
}
}

View File

@ -0,0 +1,9 @@
<StackPanel x:Class="GameRes.Formats.GUI.WidgetSCR"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:GameRes.Formats.Strings"
xmlns:p="clr-namespace:GameRes.Formats.Properties"
xmlns:d="clr-namespace:GameRes.Formats.DxLib">
<ComboBox Name="ScriptScheme" ItemsSource="{Binding}" Width="250"
SelectedValue="{Binding Source={x:Static p:Settings.Default}, Path=MEDScriptScheme, Mode=TwoWay}"/>
</StackPanel>

View File

@ -0,0 +1,22 @@
using System.Windows.Controls;
using System.Linq;
using GameRes.Formats.DxLib;
using GameRes.Formats.Strings;
namespace GameRes.Formats.GUI
{
/// <summary>
/// Interaction logic for WidgetSCR.xaml
/// </summary>
public partial class WidgetSCR : StackPanel
{
public WidgetSCR()
{
InitializeComponent();
var keys = new string[] { arcStrings.ArcIgnoreEncryption };
ScriptScheme.ItemsSource = keys.Concat (MedOpener.KnownSchemes.Keys.OrderBy (x => x));
if (-1 == ScriptScheme.SelectedIndex)
ScriptScheme.SelectedIndex = 0;
}
}
}

View File

@ -537,5 +537,17 @@ namespace GameRes.Formats.Properties {
this["NCARCScheme"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string MEDScriptScheme {
get {
return ((string)(this["MEDScriptScheme"]));
}
set {
this["MEDScriptScheme"] = value;
}
}
}
}

View File

@ -131,5 +131,8 @@
<Setting Name="NCARCScheme" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="MEDScriptScheme" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>

View File

@ -133,6 +133,9 @@
<setting name="NCARCScheme" serializeAs="String">
<value />
</setting>
<setting name="MEDScriptScheme" serializeAs="String">
<value />
</setting>
</GameRes.Formats.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>