(PackOpener): tidy.

This commit is contained in:
morkt 2018-11-17 00:42:44 +04:00
parent e302e0b574
commit 8f21e7558a

View File

@ -29,6 +29,7 @@ using System.ComponentModel.Composition;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.IO; using System.IO;
using GameRes.Formats.Strings; using GameRes.Formats.Strings;
using GameRes.Utility;
namespace GameRes.Formats.Selene namespace GameRes.Formats.Selene
{ {
@ -70,23 +71,25 @@ namespace GameRes.Formats.Selene
static private string DefaultPassPhrase = "Selene.Default.Password"; static private string DefaultPassPhrase = "Selene.Default.Password";
public static Dictionary<string,string> KnownSchemes = new Dictionary<string,string>();
public PackOpener () public PackOpener ()
{ {
Extensions = new string[] { "pack" }; Extensions = new string[] { "pack" };
} }
static KcapScheme DefaultScheme = new KcapScheme { KnownSchemes = new Dictionary<string,string>() };
public static Dictionary<string,string> KnownSchemes { get { return DefaultScheme.KnownSchemes; } }
public override ResourceScheme Scheme public override ResourceScheme Scheme
{ {
get { return new KcapScheme { KnownSchemes = KnownSchemes }; } get { return DefaultScheme; }
set { KnownSchemes = ((KcapScheme)value).KnownSchemes; } set { DefaultScheme = (KcapScheme)value; }
} }
public override ArcFile TryOpen (ArcView file) public override ArcFile TryOpen (ArcView file)
{ {
int count = file.View.ReadInt32 (4); int count = file.View.ReadInt32 (4);
if (count <= 0 || count > 0xfffff) if (!IsSaneCount (count))
return null; return null;
uint index_size = (uint)count * 0x54u; uint index_size = (uint)count * 0x54u;
if (index_size > file.View.Reserve (8, index_size)) if (index_size > file.View.Reserve (8, index_size))
@ -97,14 +100,10 @@ namespace GameRes.Formats.Selene
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
string name = file.View.ReadString (index_offset, 0x40); string name = file.View.ReadString (index_offset, 0x40);
var entry = new KcapEntry var entry = Create<KcapEntry> (name);
{ entry.Offset = file.View.ReadUInt32 (index_offset+0x48);
Name = name, entry.Size = file.View.ReadUInt32 (index_offset+0x4C);
Type = FormatCatalog.Instance.GetTypeFromName (name), entry.Encrypted = 0 != file.View.ReadUInt32 (index_offset+0x50);
Offset = file.View.ReadUInt32 (index_offset+0x48),
Size = file.View.ReadUInt32 (index_offset+0x4c),
Encrypted = 0 != file.View.ReadUInt32 (index_offset+0x50),
};
if (!entry.CheckPlacement (file.MaxOffset)) if (!entry.CheckPlacement (file.MaxOffset))
return null; return null;
encrypted = encrypted || entry.Encrypted; encrypted = encrypted || entry.Encrypted;
@ -148,77 +147,84 @@ namespace GameRes.Formats.Selene
}; };
} }
static private byte[] CreateKeyTable (string pass) // (void *this, byte *a2) static private byte[] CreateKeyTable (string pass)
{ {
if (pass.Length < 8) if (pass.Length < 8)
pass = DefaultPassPhrase; pass = DefaultPassPhrase;
int pass_len = pass.Length; int pass_len = pass.Length;
int hash = PasskeyHash (pass); // sub_100E0390 uint seed = PasskeyHash (pass);
var hash_table = new KeyTableGenerator (hash); var rng = new KeyTableGenerator ((int)seed);
byte[] table = new byte[0x10000]; byte[] table = new byte[0x10000];
for (int i = 0; i < table.Length; ++i) for (int i = 0; i < table.Length; ++i)
{ {
int key = hash_table.Permutate(); // sub_100E06D0 int key = rng.Rand();
table[i] = (byte)((byte)pass[i % pass_len] ^ (key >> 16)); table[i] = (byte)(pass[i % pass_len] ^ (key >> 16));
} }
return table; return table;
} }
static int PasskeyHash (string pass) // sub_100E0390(int a1, unsigned int a2) static uint PasskeyHash (string pass)
{ {
int hash = -1; // eax@1 var bytes = Encodings.cp932.GetBytes (pass);
for (int i = 0; i < pass.Length; ++i) // ecx@1 return Crc32.Compute (bytes, 0, bytes.Length);
{
hash = (byte)pass[i] ^ hash; // eax@2
for (int j = 0; j < 8; ++j)
hash = (int)(((uint)hash >> 1) ^ (0 != (hash & 1) ? 0xEDB88320u : 0u));
}
return ~hash;
} }
/// <summary>
/// Mersenne Twister with signed integer arithmetics, resulting in a different sequence.
/// </summary>
internal class KeyTableGenerator internal class KeyTableGenerator
{ {
private int[] m_table = new int[0x270]; const int StateLength = 624;
const int StateM = 397;
const int MatrixA = -1727483681;
const int TemperingMaskB = -1658038656;
const int TemperingMaskC = -272236544;
private int[] m_table = new int[StateLength];
private int m_pos; private int m_pos;
public KeyTableGenerator (int first = 0) public KeyTableGenerator (int seed = 0)
{ {
Init (first); SRand (seed);
} }
public void Init (int first) public void SRand (int seed)
{ {
m_table[0] = first; m_table[0] = seed;
for (int i = 1; i < 0x270; ++i) for (int i = 1; i < StateLength; ++i)
m_table[i] = i + 0x6C078965 * (m_table[i-1] ^ (m_table[i-1] >> 30)); m_table[i] = i + 0x6C078965 * (m_table[i-1] ^ (m_table[i-1] >> 30));
m_pos = 0x270; m_pos = StateLength;
} }
private static int[] v14 = new int[2] { 0, -1727483681 }; // [sp+4h] [bp-4h]@1 private static int[] mag01 = new int[2] { 0, MatrixA };
public int Permutate () // sub_100E06D0 public int Rand ()
{ {
if (m_pos >= 0x270) if (m_pos >= StateLength)
{ {
for (int i = 0; i < 0xe3; ++i) int i;
for (i = 0; i < StateLength - StateM; ++i)
{ {
int v5 = m_table[i] ^ m_table[i+1]; int x = m_table[i] ^ m_table[i+1];
m_table[i] = m_table[i+0x18d] ^ v14[(m_table[i] ^ (byte)v5) & 1] ^ ((m_table[i] ^ v5 & 0x7FFFFFFF) >> 1); m_table[i] = m_table[i + StateM] ^ mag01[(m_table[i] ^ x) & 1]
^ ((m_table[i] ^ x & 0x7FFFFFFF) >> 1);
} }
for (int i = 0; i < 0x18c; ++i) for (; i < StateLength - 1; ++i)
{ {
int v6 = i + 0xe3; int x = m_table[i] ^ m_table[i + 1];
int v8 = m_table[v6] ^ m_table[v6+1]; m_table[i] = m_table[i + StateM - StateLength] ^ mag01[(m_table[i] ^ x) & 1]
m_table[v6] = m_table[i] ^ v14[(m_table[v6] ^ (byte)v8) & 1] ^ ((m_table[v6] ^ v8 & 0x7FFFFFFF) >> 1); ^ ((m_table[i] ^ x & 0x7FFFFFFF) >> 1);
} }
int v9 = m_table[0x26f] ^ (m_table[0] ^ m_table[0x26f]) & 0x7FFFFFFF; int z = m_table[StateLength - 1] ^ (m_table[0] ^ m_table[StateLength-1]) & 0x7FFFFFFF;
m_table[0x26f] = (v9 >> 1) ^ m_table[0x18c] ^ v14[v9 & 1]; m_table[StateLength - 1] = m_table[StateM-1] ^ (z >> 1) ^ mag01[z & 1];
m_pos = 0; m_pos = 0;
} }
int v11 = m_table[m_pos++]; // edx@7 int y = m_table[m_pos++];
int v12 = (int)((((((((v11 >> 11) ^ v11) & 0xFF3A58AD) << 7) ^ (v11 >> 11) ^ v11) & 0xFFFFDF8C) << 15) ^ ((((v11 >> 11) ^ v11) & 0xFF3A58AD) << 7) ^ (v11 >> 11) ^ v11); // edx@7 y ^= y >> 11;
y ^= (y << 7) & TemperingMaskB;
return v12 ^ (v12 >> 18); y ^= (y << 15) & TemperingMaskC;
y ^= y >> 18;
return y;
} }
} }