diff --git a/ArcFormats/Entis/ArcNOA.cs b/ArcFormats/Entis/ArcNOA.cs index 16cf9503..262e8056 100644 --- a/ArcFormats/Entis/ArcNOA.cs +++ b/ArcFormats/Entis/ArcNOA.cs @@ -29,6 +29,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Xml; using GameRes.Formats.Strings; @@ -131,6 +132,15 @@ public override Stream OpenEntry (ArcFile arc, Entry entry) if (EncType.Raw == nent.Encryption || null == narc || null == narc.Password) return input; + if (EncType.SimpleCrypt32 == nent.Encryption) + { + if (0 != size % 4) + throw new InvalidFormatException (); + + using (input) + return DecodeSimpleCrypt32 (input, narc.Password, BitConverter.ToUInt32 (nent.Extra, 4)); + } + if (EncType.BSHFCrypt == nent.Encryption) { using (input) @@ -239,6 +249,37 @@ Stream DecodeBSHF (Stream input, string password) return new MemoryStream (buf); } + Stream DecodeSimpleCrypt32(Stream input, string password, uint imul_key) + { + var xor_key_map = Encoding.UTF8.GetBytes (password); + imul_key ^= Crc32.Compute (xor_key_map, 0, xor_key_map.Length); + + for (int i = 0; i < xor_key_map.Length; i++) + { + var key_byte = (byte)~xor_key_map[i]; + xor_key_map[i] = (byte)(key_byte ^ (key_byte * 7)); + } + + var buffer = new byte[input.Length]; + input.Read(buffer, 0, (int)input.Length); + + var buffer_span = MemoryMarshal.Cast (buffer); + var xor_key_span = MemoryMarshal.Cast (xor_key_map); + + for (int i = 0; i < buffer_span.Length; i += xor_key_span.Length) + { + var window_size = Math.Min (buffer_span.Length - i, xor_key_span.Length); + var window_span = buffer_span.Slice (i, window_size); + + for (int j = 0; j < window_size; j++) + { + window_span[j] = (window_span[j] * imul_key) ^ xor_key_span[j]; + } + } + + return new MemoryStream (buffer); + } + public override ResourceOptions GetDefaultOptions () { return new NoaOptions { diff --git a/ArcFormats/Resources/Formats.dat b/ArcFormats/Resources/Formats.dat index 02bcd82e..d55e233d 100644 Binary files a/ArcFormats/Resources/Formats.dat and b/ArcFormats/Resources/Formats.dat differ