diff --git a/ArcFormats/ArcFormats.csproj b/ArcFormats/ArcFormats.csproj
index f8d2c8aa..c9850e37 100644
--- a/ArcFormats/ArcFormats.csproj
+++ b/ArcFormats/ArcFormats.csproj
@@ -103,6 +103,7 @@
+
diff --git a/ArcFormats/KiriKiri/ArcXP3.cs b/ArcFormats/KiriKiri/ArcXP3.cs
index 3f723c98..9bad7268 100644
--- a/ArcFormats/KiriKiri/ArcXP3.cs
+++ b/ArcFormats/KiriKiri/ArcXP3.cs
@@ -2,7 +2,7 @@
//! \date Wed Jul 16 13:58:17 2014
//! \brief KiriKiri engine archive implementation.
//
-// Copyright (C) 2014-2015 by morkt
+// Copyright (C) 2014-2016 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
@@ -837,505 +837,4 @@ NextEntry:
}
#endregion
}
-
- [Serializable]
- public abstract class ICrypt
- {
- ///
- /// whether Adler32 checksum should be calculated after contents have been encrypted.
- ///
- public virtual bool HashAfterCrypt { get { return false; } }
-
- ///
- /// whether XP3 index is obfuscated:
- /// - duplicate entries
- /// - entries have additional dummy segments
- ///
- public virtual bool ObfuscatedIndex { get { return false; } }
-
- public virtual byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- byte[] buffer = new byte[1] { value };
- Decrypt (entry, offset, buffer, 0, 1);
- return buffer[0];
- }
-
- public abstract void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count);
-
- public virtual void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- throw new NotImplementedException (arcStrings.MsgEncNotImplemented);
- }
- }
-
- [Serializable]
- public class NoCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- return value;
- }
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- return;
- }
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- return;
- }
- }
-
- [Serializable]
- public class FateCrypt : ICrypt
- {
- public override bool HashAfterCrypt { get { return true; } }
-
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- byte result = (byte)(value ^ 0x36);
- if (0x13 == offset)
- result ^= 1;
- else if (0x2ea29 == offset)
- result ^= 3;
- return result;
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- values[pos+i] ^= 0x36;
- }
- if (offset > 0x2ea29)
- return;
- if (offset + count > 0x2ea29)
- values[pos+0x2ea29-offset] ^= 3;
- if (offset > 0x13)
- return;
- if (offset + count > 0x13)
- values[pos+0x13-offset] ^= 1;
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
-
- [Serializable]
- public class HashCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- return (byte)(value ^ entry.Hash);
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- byte key = (byte)entry.Hash;
- for (int i = 0; i < count; ++i)
- {
- values[pos+i] ^= key;
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
-
- [Serializable]
- public class XorCrypt : ICrypt
- {
- private byte m_key;
-
- public byte Key
- {
- get { return m_key; }
- set { m_key = value; }
- }
-
- public XorCrypt (uint key)
- {
- m_key = (byte)key;
- }
-
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- return (byte)(value ^ m_key);
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- values[pos+i] ^= m_key;
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
-
- [Serializable]
- public class SwanSongCrypt : ICrypt
- {
- static private byte Adjust (uint hash, out int shift)
- {
- int cl = (int)(hash & 0xff);
- if (0 == cl) cl = 0x0f;
- shift = cl & 7;
- int ch = (int)((hash >> 8) & 0xff);
- if (0 == ch) ch = 0xf0;
- return (byte)ch;
- }
-
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- int shift;
- byte xor = Adjust (entry.Hash, out shift);
- uint data = (uint)(value ^ xor);
- return (byte)((data >> shift) | (data << (8 - shift)));
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- int shift;
- byte xor = Adjust (entry.Hash, out shift);
- for (int i = 0; i < count; ++i)
- {
- uint data = (uint)(values[pos+i] ^ xor);
- values[pos+i] = (byte)((data >> shift) | (data << (8 - shift)));
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- int shift;
- byte xor = Adjust (entry.Hash, out shift);
- for (int i = 0; i < count; ++i)
- {
- uint data = values[pos+i];
- data = (byte)((data << shift) | (data >> (8 - shift)));
- values[pos+i] = (byte)(data ^ xor);
- }
- }
- }
-
- [Serializable]
- public class SeitenCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- uint key = entry.Hash ^ (uint)offset;
- if (0 != (key & 2))
- {
- int ecx = (int)key & 0x18;
- value ^= (byte)((key >> ecx) | (key >> (ecx & 8)));
- }
- if (0 != (key & 4))
- {
- value += (byte)key;
- }
- if (0 != (key & 8))
- {
- value -= (byte)(key >> (int)(key & 0x10));
- }
- return value;
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] buffer, int pos, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- int shift;
- uint key = entry.Hash ^ (uint)offset;
- byte v = buffer[pos+i];
- if (0 != (key & 2))
- {
- shift = (int)key & 0x18;
- uint ebx = key >> shift;
- shift &= 8;
- v ^= (byte)(ebx | (key >> shift));
- }
- if (0 != (key & 4))
- {
- v += (byte)key;
- }
- if (0 != (key & 8))
- {
- shift = (int)key & 0x10;
- v -= (byte)(key >> shift);
- }
- buffer[pos+i] = v;
- ++offset;
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- uint key = entry.Hash ^ (uint)offset;
- if (0 != (key & 8))
- {
- values[pos+i] += (byte)(key >> (int)(key & 0x10));
- }
- if (0 != (key & 4))
- {
- values[pos+i] -= (byte)key;
- }
- if (0 != (key & 2))
- {
- int ecx = (int)key & 0x18;
- values[pos+i] ^= (byte)((key >> ecx) | (key >> (ecx & 8)));
- }
- }
- }
- }
-
- [Serializable]
- public class OkibaCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- if (offset < 0x65)
- return (byte)(value ^ (byte)(entry.Hash >> 4));
- uint key = entry.Hash;
- // 0,1,2,3 -> 1,0,3,2
- key = ((key & 0xff0000) << 8) | ((key & 0xff000000) >> 8)
- | ((key & 0xff00) >> 8) | ((key & 0xff) << 8);
- key >>= 8 * ((int)(offset - 0x65) & 3);
- return (byte)(value ^ (byte)key);
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- int i = 0;
- if (offset < 0x65)
- {
- uint key = entry.Hash >> 4;
- int limit = Math.Min (count, (int)(0x65 - offset));
- for (; i < limit; ++i)
- {
- values[pos+i] ^= (byte)key;
- ++offset;
- }
- }
- if (i < count)
- {
- offset -= 0x65;
- uint key = entry.Hash;
- key = ((key & 0xff0000) << 8) | ((key & 0xff000000) >> 8)
- | ((key & 0xff00) >> 8) | ((key & 0xff) << 8);
- do
- {
- values[pos+i] ^= (byte)(key >> (8 * ((int)offset & 3)));
- ++offset;
- }
- while (++i < count);
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
-
- [Serializable]
- public class SaiminCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- byte key = (byte)entry.Hash;
- if (offset < 0x7B)
- value ^= (byte)(21 * key);
- else if (offset < 0xF6)
- value += (byte)(-32 * key);
- else if (offset < 0x171)
- value ^= (byte)(43 * key);
- else if (offset <= 0xffffffffL)
- value += (byte)(-54 * key);
- return value;
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- byte key = (byte)entry.Hash;
- for (int i = 0; i < count && offset <= 0xffffffffL; ++i, ++offset)
- {
- if (offset < 0x7B)
- values[pos+i] ^= (byte)(21 * key);
- else if (offset < 0xF6)
- values[pos+i] += (byte)(-32 * key);
- else if (offset >= 0x171)
- values[pos+i] += (byte)(-54 * key);
- else
- values[pos+i] ^= (byte)(43 * key);
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- byte key = (byte)entry.Hash;
- for (int i = 0; i < count && offset <= 0xffffffffL; ++i, ++offset)
- {
- if (offset < 0x7B)
- values[pos+i] ^= (byte)(21 * key);
- else if (offset < 0xF6)
- values[pos+i] -= (byte)(-32 * key);
- else if (offset >= 0x171)
- values[pos+i] -= (byte)(-54 * key);
- else
- values[pos+i] ^= (byte)(43 * key);
- }
- }
- }
-
- [Serializable]
- public class DameganeCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- if (0 != (offset & 1))
- return (byte)(value ^ entry.Hash);
- else
- return (byte)(value ^ offset);
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- for (int i = 0; i < count; ++i, ++offset)
- {
- if (0 != (offset & 1))
- values[pos+i] ^= (byte)entry.Hash;
- else
- values[pos+i] ^= (byte)offset;
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
-
- [Serializable]
- public class GakuenButouCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- if (0 != (offset & 1))
- return (byte)(value ^ offset);
- else
- return (byte)(value ^ entry.Hash);
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- for (int i = 0; i < count; ++i, ++offset)
- {
- if (0 != (offset & 1))
- values[pos+i] ^= (byte)offset;
- else
- values[pos+i] ^= (byte)entry.Hash;
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
-
- [Serializable]
- public class AlteredPinkCrypt : ICrypt
- {
- static readonly byte[] KeyTable = {
- 0x43, 0xF8, 0xAD, 0x08, 0xDF, 0xB7, 0x26, 0x44, 0xF0, 0xD9, 0xE9, 0x24, 0x1A, 0xC1, 0xEE, 0xB4,
- 0x11, 0x4B, 0xE4, 0xAF, 0x01, 0x5B, 0xF0, 0xAB, 0x6A, 0x70, 0x78, 0x84, 0xB0, 0x78, 0x4F, 0xED,
- 0x39, 0x52, 0x69, 0xAF, 0xC4, 0x92, 0x2A, 0x21, 0xDE, 0xDC, 0x6E, 0x63, 0x9D, 0x9B, 0x63, 0xE1,
- 0xB1, 0x94, 0x40, 0x6E, 0x3A, 0x52, 0x5A, 0x28, 0x08, 0x4D, 0xFB, 0x22, 0x18, 0xEB, 0xBA, 0x98,
- 0x49, 0x77, 0xBF, 0xAA, 0x43, 0x75, 0xF5, 0xD3, 0x83, 0x71, 0x58, 0xA4, 0xAF, 0x1B, 0x53, 0x99,
- 0x8A, 0x27, 0x5B, 0xC2, 0x7F, 0x7A, 0xCD, 0x8D, 0x33, 0x59, 0xEB, 0xA6, 0xFA, 0x7C, 0x00, 0x19,
- 0xC4, 0xAA, 0x24, 0xF8, 0x84, 0xCD, 0xF7, 0x20, 0x4B, 0xAB, 0xF1, 0xD5, 0x01, 0x6F, 0x7C, 0x91,
- 0x08, 0x7D, 0x8D, 0x89, 0x7C, 0x71, 0x65, 0x99, 0x9B, 0x6F, 0x3A, 0x1C, 0x49, 0xE3, 0xAF, 0x1F,
- 0xC6, 0xA5, 0x79, 0xFE, 0xAE, 0xA1, 0xCA, 0x59, 0x3C, 0xEE, 0xC1, 0x02, 0xBD, 0x2B, 0x8E, 0xC5,
- 0x7D, 0x38, 0x80, 0x8F, 0x72, 0xF3, 0x86, 0x5D, 0xF4, 0x20, 0x0A, 0x5B, 0xA0, 0xE3, 0x85, 0xB5,
- 0x67, 0x43, 0x96, 0xBB, 0x75, 0x86, 0x8D, 0x7E, 0x7E, 0xE6, 0xAA, 0x18, 0x57, 0xC4, 0xAA, 0x87,
- 0xDC, 0x74, 0x05, 0xAA, 0xBD, 0x5E, 0x4F, 0xA9, 0xB5, 0x5E, 0xC5, 0xE8, 0x11, 0x6D, 0x68, 0x89,
- 0x17, 0x7C, 0x10, 0x05, 0xA2, 0xBA, 0x43, 0x01, 0xD6, 0xFD, 0x26, 0x19, 0x57, 0xFA, 0x4D, 0x01,
- 0xB0, 0xED, 0x3A, 0x55, 0xEB, 0x65, 0x8E, 0xD1, 0x58, 0x27, 0xAD, 0xA1, 0x5E, 0x57, 0x3F, 0xA0,
- 0xEF, 0x59, 0x3E, 0xA4, 0xEB, 0x12, 0x15, 0x60, 0xBE, 0x95, 0x61, 0x0B, 0x98, 0xF5, 0xF4, 0x12,
- 0x1C, 0xD8, 0x62, 0x3F, 0xFD, 0xCF, 0x01, 0x3A, 0xE7, 0xC2, 0x19, 0x38, 0x6C, 0xC3, 0x90, 0x3E,
- };
-
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- return (byte)(value ^ KeyTable[offset & 0xFF]);
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- values[pos+i] ^= KeyTable[(offset+i) & 0xFF];
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
-
- [Serializable]
- public class NatsupochiCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- return (byte)(value ^ (entry.Hash >> 3));
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- byte key = (byte)(entry.Hash >> 3);
- for (int i = 0; i < count; ++i)
- {
- values[pos+i] ^= key;
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
-
- [Serializable]
- public class IncubusCrypt : ICrypt
- {
- public override byte Decrypt (Xp3Entry entry, long offset, byte value)
- {
- return (byte)~(value ^ (entry.Hash + 1));
- }
-
- public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- byte key = (byte)~(entry.Hash + 1);
- for (int i = 0; i < count; ++i)
- {
- values[pos+i] ^= key;
- }
- }
-
- public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
- {
- Decrypt (entry, offset, values, pos, count);
- }
- }
}
diff --git a/ArcFormats/KiriKiri/CryptAlgorithms.cs b/ArcFormats/KiriKiri/CryptAlgorithms.cs
new file mode 100644
index 00000000..c84089fd
--- /dev/null
+++ b/ArcFormats/KiriKiri/CryptAlgorithms.cs
@@ -0,0 +1,530 @@
+//! \file CryptAlgorithms.cs
+//! \date Thu Feb 04 12:08:40 2016
+//! \brief KiriKiri engine encryption algorithms.
+//
+// Copyright (C) 2016 by morkt
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//
+
+using System;
+
+namespace GameRes.Formats.KiriKiri
+{
+ [Serializable]
+ public abstract class ICrypt
+ {
+ ///
+ /// whether Adler32 checksum should be calculated after contents have been encrypted.
+ ///
+ public virtual bool HashAfterCrypt { get { return false; } }
+
+ ///
+ /// whether XP3 index is obfuscated:
+ /// - duplicate entries
+ /// - entries have additional dummy segments
+ ///
+ public virtual bool ObfuscatedIndex { get { return false; } }
+
+ public virtual byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ byte[] buffer = new byte[1] { value };
+ Decrypt (entry, offset, buffer, 0, 1);
+ return buffer[0];
+ }
+
+ public abstract void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count);
+
+ public virtual void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ throw new NotImplementedException (Strings.arcStrings.MsgEncNotImplemented);
+ }
+ }
+
+ [Serializable]
+ public class NoCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ return value;
+ }
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ return;
+ }
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ return;
+ }
+ }
+
+ [Serializable]
+ public class FateCrypt : ICrypt
+ {
+ public override bool HashAfterCrypt { get { return true; } }
+
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ byte result = (byte)(value ^ 0x36);
+ if (0x13 == offset)
+ result ^= 1;
+ else if (0x2ea29 == offset)
+ result ^= 3;
+ return result;
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ values[pos+i] ^= 0x36;
+ }
+ if (offset > 0x2ea29)
+ return;
+ if (offset + count > 0x2ea29)
+ values[pos+0x2ea29-offset] ^= 3;
+ if (offset > 0x13)
+ return;
+ if (offset + count > 0x13)
+ values[pos+0x13-offset] ^= 1;
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+
+ [Serializable]
+ public class HashCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ return (byte)(value ^ entry.Hash);
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ byte key = (byte)entry.Hash;
+ for (int i = 0; i < count; ++i)
+ {
+ values[pos+i] ^= key;
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+
+ [Serializable]
+ public class XorCrypt : ICrypt
+ {
+ private byte m_key;
+
+ public byte Key
+ {
+ get { return m_key; }
+ set { m_key = value; }
+ }
+
+ public XorCrypt (uint key)
+ {
+ m_key = (byte)key;
+ }
+
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ return (byte)(value ^ m_key);
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ values[pos+i] ^= m_key;
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+
+ [Serializable]
+ public class SwanSongCrypt : ICrypt
+ {
+ static private byte Adjust (uint hash, out int shift)
+ {
+ int cl = (int)(hash & 0xff);
+ if (0 == cl) cl = 0x0f;
+ shift = cl & 7;
+ int ch = (int)((hash >> 8) & 0xff);
+ if (0 == ch) ch = 0xf0;
+ return (byte)ch;
+ }
+
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ int shift;
+ byte xor = Adjust (entry.Hash, out shift);
+ uint data = (uint)(value ^ xor);
+ return (byte)((data >> shift) | (data << (8 - shift)));
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ int shift;
+ byte xor = Adjust (entry.Hash, out shift);
+ for (int i = 0; i < count; ++i)
+ {
+ uint data = (uint)(values[pos+i] ^ xor);
+ values[pos+i] = (byte)((data >> shift) | (data << (8 - shift)));
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ int shift;
+ byte xor = Adjust (entry.Hash, out shift);
+ for (int i = 0; i < count; ++i)
+ {
+ uint data = values[pos+i];
+ data = (byte)((data << shift) | (data >> (8 - shift)));
+ values[pos+i] = (byte)(data ^ xor);
+ }
+ }
+ }
+
+ [Serializable]
+ public class SeitenCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ uint key = entry.Hash ^ (uint)offset;
+ if (0 != (key & 2))
+ {
+ int ecx = (int)key & 0x18;
+ value ^= (byte)((key >> ecx) | (key >> (ecx & 8)));
+ }
+ if (0 != (key & 4))
+ {
+ value += (byte)key;
+ }
+ if (0 != (key & 8))
+ {
+ value -= (byte)(key >> (int)(key & 0x10));
+ }
+ return value;
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] buffer, int pos, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ int shift;
+ uint key = entry.Hash ^ (uint)offset;
+ byte v = buffer[pos+i];
+ if (0 != (key & 2))
+ {
+ shift = (int)key & 0x18;
+ uint ebx = key >> shift;
+ shift &= 8;
+ v ^= (byte)(ebx | (key >> shift));
+ }
+ if (0 != (key & 4))
+ {
+ v += (byte)key;
+ }
+ if (0 != (key & 8))
+ {
+ shift = (int)key & 0x10;
+ v -= (byte)(key >> shift);
+ }
+ buffer[pos+i] = v;
+ ++offset;
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ uint key = entry.Hash ^ (uint)offset;
+ if (0 != (key & 8))
+ {
+ values[pos+i] += (byte)(key >> (int)(key & 0x10));
+ }
+ if (0 != (key & 4))
+ {
+ values[pos+i] -= (byte)key;
+ }
+ if (0 != (key & 2))
+ {
+ int ecx = (int)key & 0x18;
+ values[pos+i] ^= (byte)((key >> ecx) | (key >> (ecx & 8)));
+ }
+ }
+ }
+ }
+
+ [Serializable]
+ public class OkibaCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ if (offset < 0x65)
+ return (byte)(value ^ (byte)(entry.Hash >> 4));
+ uint key = entry.Hash;
+ // 0,1,2,3 -> 1,0,3,2
+ key = ((key & 0xff0000) << 8) | ((key & 0xff000000) >> 8)
+ | ((key & 0xff00) >> 8) | ((key & 0xff) << 8);
+ key >>= 8 * ((int)(offset - 0x65) & 3);
+ return (byte)(value ^ (byte)key);
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ int i = 0;
+ if (offset < 0x65)
+ {
+ uint key = entry.Hash >> 4;
+ int limit = Math.Min (count, (int)(0x65 - offset));
+ for (; i < limit; ++i)
+ {
+ values[pos+i] ^= (byte)key;
+ ++offset;
+ }
+ }
+ if (i < count)
+ {
+ offset -= 0x65;
+ uint key = entry.Hash;
+ key = ((key & 0xff0000) << 8) | ((key & 0xff000000) >> 8)
+ | ((key & 0xff00) >> 8) | ((key & 0xff) << 8);
+ do
+ {
+ values[pos+i] ^= (byte)(key >> (8 * ((int)offset & 3)));
+ ++offset;
+ }
+ while (++i < count);
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+
+ [Serializable]
+ public class SaiminCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ byte key = (byte)entry.Hash;
+ if (offset < 0x7B)
+ value ^= (byte)(21 * key);
+ else if (offset < 0xF6)
+ value += (byte)(-32 * key);
+ else if (offset < 0x171)
+ value ^= (byte)(43 * key);
+ else if (offset <= 0xffffffffL)
+ value += (byte)(-54 * key);
+ return value;
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ byte key = (byte)entry.Hash;
+ for (int i = 0; i < count && offset <= 0xffffffffL; ++i, ++offset)
+ {
+ if (offset < 0x7B)
+ values[pos+i] ^= (byte)(21 * key);
+ else if (offset < 0xF6)
+ values[pos+i] += (byte)(-32 * key);
+ else if (offset >= 0x171)
+ values[pos+i] += (byte)(-54 * key);
+ else
+ values[pos+i] ^= (byte)(43 * key);
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ byte key = (byte)entry.Hash;
+ for (int i = 0; i < count && offset <= 0xffffffffL; ++i, ++offset)
+ {
+ if (offset < 0x7B)
+ values[pos+i] ^= (byte)(21 * key);
+ else if (offset < 0xF6)
+ values[pos+i] -= (byte)(-32 * key);
+ else if (offset >= 0x171)
+ values[pos+i] -= (byte)(-54 * key);
+ else
+ values[pos+i] ^= (byte)(43 * key);
+ }
+ }
+ }
+
+ [Serializable]
+ public class DameganeCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ if (0 != (offset & 1))
+ return (byte)(value ^ entry.Hash);
+ else
+ return (byte)(value ^ offset);
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ for (int i = 0; i < count; ++i, ++offset)
+ {
+ if (0 != (offset & 1))
+ values[pos+i] ^= (byte)entry.Hash;
+ else
+ values[pos+i] ^= (byte)offset;
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+
+ [Serializable]
+ public class GakuenButouCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ if (0 != (offset & 1))
+ return (byte)(value ^ offset);
+ else
+ return (byte)(value ^ entry.Hash);
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ for (int i = 0; i < count; ++i, ++offset)
+ {
+ if (0 != (offset & 1))
+ values[pos+i] ^= (byte)offset;
+ else
+ values[pos+i] ^= (byte)entry.Hash;
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+
+ [Serializable]
+ public class AlteredPinkCrypt : ICrypt
+ {
+ static readonly byte[] KeyTable = {
+ 0x43, 0xF8, 0xAD, 0x08, 0xDF, 0xB7, 0x26, 0x44, 0xF0, 0xD9, 0xE9, 0x24, 0x1A, 0xC1, 0xEE, 0xB4,
+ 0x11, 0x4B, 0xE4, 0xAF, 0x01, 0x5B, 0xF0, 0xAB, 0x6A, 0x70, 0x78, 0x84, 0xB0, 0x78, 0x4F, 0xED,
+ 0x39, 0x52, 0x69, 0xAF, 0xC4, 0x92, 0x2A, 0x21, 0xDE, 0xDC, 0x6E, 0x63, 0x9D, 0x9B, 0x63, 0xE1,
+ 0xB1, 0x94, 0x40, 0x6E, 0x3A, 0x52, 0x5A, 0x28, 0x08, 0x4D, 0xFB, 0x22, 0x18, 0xEB, 0xBA, 0x98,
+ 0x49, 0x77, 0xBF, 0xAA, 0x43, 0x75, 0xF5, 0xD3, 0x83, 0x71, 0x58, 0xA4, 0xAF, 0x1B, 0x53, 0x99,
+ 0x8A, 0x27, 0x5B, 0xC2, 0x7F, 0x7A, 0xCD, 0x8D, 0x33, 0x59, 0xEB, 0xA6, 0xFA, 0x7C, 0x00, 0x19,
+ 0xC4, 0xAA, 0x24, 0xF8, 0x84, 0xCD, 0xF7, 0x20, 0x4B, 0xAB, 0xF1, 0xD5, 0x01, 0x6F, 0x7C, 0x91,
+ 0x08, 0x7D, 0x8D, 0x89, 0x7C, 0x71, 0x65, 0x99, 0x9B, 0x6F, 0x3A, 0x1C, 0x49, 0xE3, 0xAF, 0x1F,
+ 0xC6, 0xA5, 0x79, 0xFE, 0xAE, 0xA1, 0xCA, 0x59, 0x3C, 0xEE, 0xC1, 0x02, 0xBD, 0x2B, 0x8E, 0xC5,
+ 0x7D, 0x38, 0x80, 0x8F, 0x72, 0xF3, 0x86, 0x5D, 0xF4, 0x20, 0x0A, 0x5B, 0xA0, 0xE3, 0x85, 0xB5,
+ 0x67, 0x43, 0x96, 0xBB, 0x75, 0x86, 0x8D, 0x7E, 0x7E, 0xE6, 0xAA, 0x18, 0x57, 0xC4, 0xAA, 0x87,
+ 0xDC, 0x74, 0x05, 0xAA, 0xBD, 0x5E, 0x4F, 0xA9, 0xB5, 0x5E, 0xC5, 0xE8, 0x11, 0x6D, 0x68, 0x89,
+ 0x17, 0x7C, 0x10, 0x05, 0xA2, 0xBA, 0x43, 0x01, 0xD6, 0xFD, 0x26, 0x19, 0x57, 0xFA, 0x4D, 0x01,
+ 0xB0, 0xED, 0x3A, 0x55, 0xEB, 0x65, 0x8E, 0xD1, 0x58, 0x27, 0xAD, 0xA1, 0x5E, 0x57, 0x3F, 0xA0,
+ 0xEF, 0x59, 0x3E, 0xA4, 0xEB, 0x12, 0x15, 0x60, 0xBE, 0x95, 0x61, 0x0B, 0x98, 0xF5, 0xF4, 0x12,
+ 0x1C, 0xD8, 0x62, 0x3F, 0xFD, 0xCF, 0x01, 0x3A, 0xE7, 0xC2, 0x19, 0x38, 0x6C, 0xC3, 0x90, 0x3E,
+ };
+
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ return (byte)(value ^ KeyTable[offset & 0xFF]);
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ values[pos+i] ^= KeyTable[(offset+i) & 0xFF];
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+
+ [Serializable]
+ public class NatsupochiCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ return (byte)(value ^ (entry.Hash >> 3));
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ byte key = (byte)(entry.Hash >> 3);
+ for (int i = 0; i < count; ++i)
+ {
+ values[pos+i] ^= key;
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+
+ [Serializable]
+ public class IncubusCrypt : ICrypt
+ {
+ public override byte Decrypt (Xp3Entry entry, long offset, byte value)
+ {
+ return (byte)~(value ^ (entry.Hash + 1));
+ }
+
+ public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ byte key = (byte)~(entry.Hash + 1);
+ for (int i = 0; i < count; ++i)
+ {
+ values[pos+i] ^= key;
+ }
+ }
+
+ public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
+ {
+ Decrypt (entry, offset, values, pos, count);
+ }
+ }
+}