mirror of
https://github.com/crskycode/GARbro.git
synced 2025-01-11 20:39:29 +08:00
implemented QLIE archives versions 1 and 3.
This commit is contained in:
parent
9e5990b118
commit
91af591363
@ -62,16 +62,25 @@ namespace GameRes.Formats.Qlie
|
|||||||
|| !file.View.AsciiEqual (index_offset+0xC, ".0"))
|
|| !file.View.AsciiEqual (index_offset+0xC, ".0"))
|
||||||
return null;
|
return null;
|
||||||
int pack_version = file.View.ReadByte (index_offset+0xB) - '0';
|
int pack_version = file.View.ReadByte (index_offset+0xB) - '0';
|
||||||
if (pack_version != 2)
|
if (pack_version < 1 || pack_version > 3)
|
||||||
throw new NotSupportedException ("Not supported QLIE archive version");
|
throw new NotSupportedException ("Not supported QLIE archive version");
|
||||||
int count = file.View.ReadInt32 (index_offset+0x10);
|
int count = file.View.ReadInt32 (index_offset+0x10);
|
||||||
if (count <= 0 || count > 0xfffff)
|
if (!IsSaneCount (count))
|
||||||
return null;
|
return null;
|
||||||
index_offset = file.View.ReadInt64 (index_offset+0x14);
|
index_offset = file.View.ReadInt64 (index_offset+0x14);
|
||||||
if (index_offset < 0 || index_offset >= file.MaxOffset)
|
if (index_offset < 0 || index_offset >= file.MaxOffset)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
int pack_key = 0xC4;
|
uint pack_key;
|
||||||
|
if (3 == pack_version)
|
||||||
|
{
|
||||||
|
var key_data = new byte[0x100];
|
||||||
|
file.View.Read (file.MaxOffset-0x41C, key_data, 0, 0x100);
|
||||||
|
pack_key = GenerateKey (key_data) & 0x0FFFFFFFu;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pack_key = 0xC4;
|
||||||
|
|
||||||
var name_buffer = new byte[0x100];
|
var name_buffer = new byte[0x100];
|
||||||
var dir = new List<Entry> (count);
|
var dir = new List<Entry> (count);
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
@ -82,7 +91,7 @@ namespace GameRes.Formats.Qlie
|
|||||||
if (name_length != file.View.Read (index_offset+2, name_buffer, 0, (uint)name_length))
|
if (name_length != file.View.Read (index_offset+2, name_buffer, 0, (uint)name_length))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
int key = name_length + (pack_key ^ 0x3e);
|
int key = name_length + ((int)pack_key ^ 0x3e);
|
||||||
for (int k = 0; k < name_length; ++k)
|
for (int k = 0; k < name_length; ++k)
|
||||||
name_buffer[k] ^= (byte)(((k + 1) ^ key) + k + 1);
|
name_buffer[k] ^= (byte)(((k + 1) ^ key) + k + 1);
|
||||||
|
|
||||||
@ -99,7 +108,7 @@ namespace GameRes.Formats.Qlie
|
|||||||
entry.IsEncrypted = 0 != file.View.ReadInt32 (index_offset+0x14);
|
entry.IsEncrypted = 0 != file.View.ReadInt32 (index_offset+0x14);
|
||||||
entry.Hash = file.View.ReadUInt32 (index_offset+0x18);
|
entry.Hash = file.View.ReadUInt32 (index_offset+0x18);
|
||||||
if (3 == pack_version)
|
if (3 == pack_version)
|
||||||
entry.Key = (uint)pack_key;
|
entry.Key = pack_key;
|
||||||
else
|
else
|
||||||
entry.Key = 0;
|
entry.Key = 0;
|
||||||
dir.Add (entry);
|
dir.Add (entry);
|
||||||
@ -135,28 +144,19 @@ namespace GameRes.Formats.Qlie
|
|||||||
if (length > buffer.Length || offset > buffer.Length - length)
|
if (length > buffer.Length || offset > buffer.Length - length)
|
||||||
throw new ArgumentOutOfRangeException ("length");
|
throw new ArgumentOutOfRangeException ("length");
|
||||||
|
|
||||||
var table = new uint[2,2];
|
ulong hash = 0xA73C5F9DA73C5F9Dul;
|
||||||
var xor = new uint[2];
|
ulong xor = ((uint)length + key) ^ 0xFEC9753Eu;
|
||||||
|
xor |= xor << 32;
|
||||||
for (int i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
table[0,i] = 0xA73C5F9Du;
|
|
||||||
table[1,i] = 0xCE24F523u;
|
|
||||||
xor[i] = ((uint)length + key) ^ 0xFEC9753Eu;
|
|
||||||
}
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
fixed (byte* raw = buffer)
|
fixed (byte* raw = buffer)
|
||||||
{
|
{
|
||||||
uint* encoded = (uint*)(raw + offset);
|
ulong* encoded = (ulong*)(raw + offset);
|
||||||
for (int i = 0; i < length / 8; ++i)
|
for (int i = 0; i < length / 8; ++i)
|
||||||
{
|
{
|
||||||
for (int k = 0; k < 2; ++k)
|
hash = MMX.PAddD (hash, 0xCE24F523CE24F523ul) ^ xor;
|
||||||
{
|
xor = *encoded ^ hash;
|
||||||
table[0,k] = (table[0,k] + table[1,k]) ^ xor[k];
|
*encoded++ = xor;
|
||||||
*encoded ^= table[0,k];
|
|
||||||
xor[k] = *encoded++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,5 +246,24 @@ namespace GameRes.Formats.Qlie
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint GenerateKey (byte[] key_data)
|
||||||
|
{
|
||||||
|
ulong hash = 0;
|
||||||
|
ulong key = 0;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* data = key_data)
|
||||||
|
{
|
||||||
|
ulong* data64 = (ulong*)data;
|
||||||
|
for (int i = key_data.Length / 8; i > 0; --i)
|
||||||
|
{
|
||||||
|
hash = MMX.PAddW (hash, 0x0307030703070307);
|
||||||
|
key = MMX.PAddW (key, *data64++ ^ hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (uint)(key ^ (key >> 32));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user