From 97a6b331c51591d5462b06493f70304021c1c969 Mon Sep 17 00:00:00 2001 From: morkt Date: Fri, 3 Feb 2017 11:48:54 +0400 Subject: [PATCH] (WARC): another decryptor. --- ArcFormats/ArcFormats.csproj | 1 + ArcFormats/ShiinaRio/ArcWARC.cs | 16 +++++++------ ArcFormats/ShiinaRio/WarcEncryption.cs | 31 ++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj index 40f9b9a5..3d2d73f8 100644 --- a/ArcFormats/ArcFormats.csproj +++ b/ArcFormats/ArcFormats.csproj @@ -93,6 +93,7 @@ + diff --git a/ArcFormats/ShiinaRio/ArcWARC.cs b/ArcFormats/ShiinaRio/ArcWARC.cs index d308722c..3efb004a 100644 --- a/ArcFormats/ShiinaRio/ArcWARC.cs +++ b/ArcFormats/ShiinaRio/ArcWARC.cs @@ -158,13 +158,15 @@ namespace GameRes.Formats.ShiinaRio // 椎名里緒 uint unpacked_size = LittleEndian.ToUInt32 (enc_data, 4); sig ^= (unpacked_size ^ 0x82AD82) & 0xffffff; - if (0 != (wentry.Flags & 0x80000000u) && entry.Size > 8) // encrypted entry - warc.Decoder.Decrypt (enc_data, 8, entry.Size-8); - if (warc.Decoder.ExtraCrypt != null) - warc.Decoder.ExtraCrypt.Decrypt (enc_data, 8, entry.Size-8, 0x202); - if (0 != (wentry.Flags & 0x20000000u) && entry.Size > 8) - warc.Decoder.Decrypt2 (enc_data, 8, entry.Size-8); - + if (entry.Size > 8) + { + if (0 != (wentry.Flags & 0x80000000u)) // encrypted entry + warc.Decoder.Decrypt (enc_data, 8, entry.Size-8); + if (warc.Decoder.ExtraCrypt != null) + warc.Decoder.ExtraCrypt.Decrypt (enc_data, 8, entry.Size-8, 0x202); + if (0 != (wentry.Flags & 0x20000000u)) + warc.Decoder.Decrypt2 (enc_data, 8, entry.Size-8); + } byte[] unpacked = enc_data; UnpackMethod unpack = null; switch (sig & 0xffffff) diff --git a/ArcFormats/ShiinaRio/WarcEncryption.cs b/ArcFormats/ShiinaRio/WarcEncryption.cs index 69665878..b1bd0daa 100644 --- a/ArcFormats/ShiinaRio/WarcEncryption.cs +++ b/ArcFormats/ShiinaRio/WarcEncryption.cs @@ -1126,4 +1126,35 @@ namespace GameRes.Formats.ShiinaRio } } } + + [Serializable] + public class CountCrypt : IDecryptExtra + { + public void Decrypt (byte[] data, int index, uint length, uint flags) + { + if (length >= 0x200 && (flags & 0x204) == 0x204) + DoCountCrypt (data, index, (int)length); + } + + public void Encrypt (byte[] data, int index, uint length, uint flags) + { + if (length >= 0x200 && (flags & 0x104) == 0x104) + DoCountCrypt (data, index, (int)length); + } + + void DoCountCrypt (byte[] data, int index, int length) + { + length = (length & 0x7E) | 1; + byte count_00 = 0, count_FF = 0; + for (int i = 0; i < length; ++i) + { + if (0xFF == data[index+i]) + count_FF++; + else if (0 == data[index+i]) + count_00++; + } + data[index + 0x100] ^= count_00; + data[index + 0x104] ^= count_FF; + } + } }