From 13bb077b4690c0f4bdd5dd1cf12a00f9dec7348d Mon Sep 17 00:00:00 2001 From: morkt Date: Tue, 25 Oct 2016 18:29:07 +0400 Subject: [PATCH] (LINK): another encryption variant. --- ArcFormats/Kaguya/ArcLINK.cs | 131 ++++++++++++++++++++++------------- supported.html | 1 + 2 files changed, 84 insertions(+), 48 deletions(-) diff --git a/ArcFormats/Kaguya/ArcLINK.cs b/ArcFormats/Kaguya/ArcLINK.cs index 66d89863..81f44046 100644 --- a/ArcFormats/Kaguya/ArcLINK.cs +++ b/ArcFormats/Kaguya/ArcLINK.cs @@ -192,10 +192,7 @@ namespace GameRes.Formats.Kaguya using (var input = VFS.OpenBinaryStream (params_dat)) { var param = ParamsDeserializer.Create (input); - var key = param.GetKey(); - if (null == key) - return null; - return new LinkEncryption (key); + return param.GetEncryption(); } } @@ -426,7 +423,7 @@ namespace GameRes.Formats.Kaguya #endregion } - internal class ParamsDeserializer + internal abstract class ParamsDeserializer { protected IBinaryStream m_input; protected string m_title; @@ -442,54 +439,19 @@ namespace GameRes.Formats.Kaguya if (!header.AsciiEqual ("[SCR-PARAMS]")) return null; if (header.AsciiEqual (12, "v02")) - return new ParamsDeserializer (input); + return new ParamsV2Deserializer (input); else if (header.AsciiEqual (12, "v05.6")) return new ParamsV5Deserializer (input); return null; } - public virtual byte[] GetKey () + public virtual LinkEncryption GetEncryption () { - // 毎日がM! - m_input.Position = 0x17; - SkipChunk(); - m_title = ReadString(); - m_input.ReadCString(); - SkipString(); - SkipString(); - m_input.ReadByte(); - SkipString(); - SkipString(); - SkipDict(); - - m_input.ReadByte(); - int count = m_input.ReadUInt8(); - for (int i = 0; i < count; ++i) - { - m_input.ReadByte(); - SkipChunk(); - for (int j = 0; j < 2; ++j) - { - int n = m_input.ReadUInt8(); - for (int k = 0; k < n; ++k) - SkipChunk(); - } - } - SkipDict(); - count = m_input.ReadUInt8(); - for (int i = 0; i < count; ++i) - { - SkipChunk(); - for (int j = 0; j < 2; ++j) - { - int n = m_input.ReadUInt8(); - for (int k = 0; k < n; ++k) - SkipChunk(); - } - } - return ReadKey(); + return new LinkEncryption (GetKey()); } + public abstract byte[] GetKey (); + protected byte[] ReadKey () { int key_length = m_input.ReadInt32(); @@ -517,6 +479,13 @@ namespace GameRes.Formats.Kaguya Skip (m_input.ReadUInt8()); } + protected void SkipArray () + { + int count = m_input.ReadUInt8(); + for (int i = 0; i < count; ++i) + SkipChunk(); + } + protected void SkipDict () { int count = m_input.ReadUInt8(); @@ -528,6 +497,70 @@ namespace GameRes.Formats.Kaguya } } + internal class ParamsV2Deserializer : ParamsDeserializer + { + public ParamsV2Deserializer (IBinaryStream input) : base (input) + { + } + + public override LinkEncryption GetEncryption () + { + var key = GetKey(); + return new LinkEncryption (key, m_title != "幼なじみと甘~くエッチに過ごす方法"); + } + + public override byte[] GetKey () + { + m_input.Position = 0x17; + SkipChunk(); + m_title = ReadString(); + m_input.ReadCString(); + SkipString(); + SkipString(); + m_input.ReadByte(); + SkipString(); + SkipString(); + SkipDict(); + m_input.ReadByte(); + + if ("幼なじみと甘~くエッチに過ごす方法" == m_title) + { + int count = m_input.ReadUInt8(); + for (int i = 0; i < count; ++i) + { + m_input.ReadByte(); + SkipChunk(); + SkipArray(); + SkipChunk(); + } + SkipArray(); + SkipArray(); + m_input.ReadInt32(); + return m_input.ReadBytes (240000); + } + else // 毎日がM! + { + int count = m_input.ReadUInt8(); + for (int i = 0; i < count; ++i) + { + m_input.ReadByte(); + SkipChunk(); + SkipArray(); + SkipArray(); + } + SkipDict(); + count = m_input.ReadUInt8(); + for (int i = 0; i < count; ++i) + { + SkipChunk(); + SkipArray(); + SkipArray(); + } + return ReadKey(); + } + } + } + internal class ParamsV5Deserializer : ParamsDeserializer { public ParamsV5Deserializer (IBinaryStream input) : base (input) @@ -596,19 +629,21 @@ namespace GameRes.Formats.Kaguya delegate Stream Decryptor (LinkArchive arc, LinkEntry entry); - public LinkEncryption (byte[] key) + public LinkEncryption (byte[] key, bool anm_encrypted = true) { if (null == key || 0 == key.Length) throw new ArgumentException ("Invalid encryption key"); m_key = key; - m_type_table = new [] + var table = new List> { new Tuple ("BM", (a, e) => DecryptImage (a, e, 0x36)), new Tuple ("AP-2", (a, e) => DecryptImage (a, e, 0x18)), new Tuple ("AP-3", (a, e) => DecryptImage (a, e, 0x18)), new Tuple ("AP", (a, e) => DecryptImage (a, e, 0xC)), - new Tuple ("AN00", (a, e) => DecryptAn00 (a, e)), }; + if (anm_encrypted) + table.Add (new Tuple ("AN00", (a, e) => DecryptAn00 (a, e))); + m_type_table = table.ToArray(); } public Stream DecryptEntry (LinkArchive arc, LinkEntry entry) diff --git a/supported.html b/supported.html index 673a89a6..57ff6271 100644 --- a/supported.html +++ b/supported.html @@ -961,6 +961,7 @@ Harami Tama
Mahokoi ~Ecchi na Mahou de Koi x Koi Shichau~
Mainichi ga M!
Ningyou no Yakata
+Osananajimi to Ama~ku Ecchi ni Sugosu Houhou
*.alpAP-0
AP-2No *.anmAN00No