Updated the Crypto Engine:

- Fixed several bugs in unedat;
- Improved EDAT/SDAT file decryption.
This commit is contained in:
Hykem 2014-10-01 14:57:44 +01:00
parent eada1fe12c
commit 6d6c1a9672
16 changed files with 1190 additions and 295 deletions

View file

@ -4,26 +4,20 @@
#include "lz.h"
int decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
{
if (!((*range) >> 24))
if (!((*range) >> 24))
{
(*range) <<= 8;
*code = ((*code) << 8) + (*src)++[5];
return 1;
}
else
return 0;
}
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c)
{
unsigned int val = *range;
if (decode_range(range, code, src))
val *= (*c);
else
val = (val >> 8) * (*c);
decode_range(range, code, src);
unsigned int val = ((*range) >> 8) * (*c);
*c -= ((*c) >> 3);
if (index) (*index) <<= 1;
@ -47,12 +41,12 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
{
int i = 1;
if (index >= 3)
if (index >= 3)
{
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978
if (index >= 4)
decode_bit(range, code, &i, src, ptr + 0x18);
if (index >= 4)
{
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978
decode_bit(range, code, &i, src, ptr + 0x18);
if (index >= 5)
{
decode_range(range, code, src);
@ -60,8 +54,8 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
{
i <<= 1;
(*range) >>= 1;
if (*code < *range)
i++;
if (*code < *range)
i++;
else
(*code) -= *range;
}
@ -69,16 +63,16 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
}
}
*bit_flag = decode_bit(range, code, &i, src, ptr); // Offset 0x960
*bit_flag = decode_bit(range, code, &i, src, ptr);
if (index >= 1)
if (index >= 1)
{
decode_bit(range, code, &i, src, ptr + 0x8); // Offset 0x968
if (index >= 2)
decode_bit(range, code, &i, src, ptr + 0x8);
if (index >= 2)
{
decode_bit(range, code, &i, src, ptr + 0x10); // Offset 0x970
decode_bit(range, code, &i, src, ptr + 0x10);
}
}
}
return i;
}
@ -88,12 +82,12 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
int i = 1;
index /= 8;
if (index >= 3)
if (index >= 3)
{
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8
if (index >= 4)
decode_bit(range, code, &i, src, ptr + 4);
if (index >= 4)
{
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8
decode_bit(range, code, &i, src, ptr + 4);
if (index >= 5)
{
decode_range(range, code, src);
@ -101,8 +95,8 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
{
i <<= 1;
(*range) >>= 1;
if (*code < *range)
i++;
if (*code < *range)
i++;
else
(*code) -= *range;
}
@ -110,16 +104,16 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
}
}
*bit_flag = decode_bit(range, code, &i, src, ptr + 3); // Offset 0x8A8 + 3
*bit_flag = decode_bit(range, code, &i, src, ptr);
if (index >= 1)
if (index >= 1)
{
decode_bit(range, code, &i, src, ptr + 2); // Offset 0x8A8 + 2
if (index >= 2)
decode_bit(range, code, &i, src, ptr + 1);
if (index >= 2)
{
decode_bit(range, code, &i, src, ptr + 1); // Offset 0x8A8 + 1
decode_bit(range, code, &i, src, ptr + 2);
}
}
}
return i;
}
@ -128,7 +122,7 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
{
int result;
unsigned char *tmp = new unsigned char[0xA70];
unsigned char *tmp = new unsigned char[0xCC8];
int offset = 0;
int bit_flag = 0;
@ -159,11 +153,11 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
else
{
// Set up a temporary buffer (sliding window).
memset(tmp, 0x80, 0xA60);
memset(tmp, 0x80, 0xCA8);
while (1)
{
// Start reading at 0x920.
tmp_sect1 = tmp + offset + 0x920;
// Start reading at 0xB68.
tmp_sect1 = tmp + offset + 0xB68;
if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char.
{
// Adjust offset and check for stream end.
@ -189,57 +183,65 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
int index = -1;
// Identify the data length bit field.
do {
tmp_sect1 += 8;
do
{
tmp_sect1 += 8;
bit_flag = decode_bit(&range, &code, 0, &in, tmp_sect1);
index += bit_flag;
} while ((bit_flag != 0) && (index < 6));
// Default block size is 0x40.
int b_size = 0x40;
// Default block size is 0x160.
int b_size = 0x160;
tmp_sect2 = tmp + index + 0x7F1;
// If the data length was found, parse it as a number.
if ((index >= 0) || (bit_flag != 0))
if ((index >= 0) || (bit_flag != 0))
{
// Locate next section.
int sect = (index << 5) | (((((start - out)) << index) & 3) << 3) | (offset & 7);
tmp_sect1 = tmp + 0x960 + sect;
int sect = (index << 5) | (((((int)(start - out)) << index) & 3) << 3) | (offset & 7);
tmp_sect1 = tmp + 0xBA8 + sect;
// Decode the data length (8 bit fields).
data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in);
// If we got valid parameters, seek to find data offset.
if ((data_length != 3) && ((index > 0) || (bit_flag != 0))) {
tmp_sect2 += 0x38;
b_size = 0x80; // Block size is now 0x80.
}
} else {
if (data_length == 0xFF) return (start - out); // End of stream.
}
else
{
// Assume one byte of advance.
data_length = 1;
}
// If we got valid parameters, seek to find data offset.
if ((data_length <= 2))
{
tmp_sect2 += 0xF8;
b_size = 0x40; // Block size is now 0x40.
}
int diff = 0;
int shift = 1;
// Identify the data offset bit field.
do {
do
{
diff = (shift << 4) - b_size;
bit_flag = decode_bit(&range, &code, &shift, &in, tmp_sect2 + (shift << 3));
} while (diff < 0);
// If the data offset was found, parse it as a number.
if ((diff > 0) || (bit_flag != 0))
if ((diff > 0) || (bit_flag != 0))
{
// Adjust diff if needed.
if (bit_flag == 0) diff -= 8;
// Locate section.
tmp_sect3 = tmp + 0x8A8 + diff;
tmp_sect3 = tmp + 0x928 + diff;
// Decode the data offset (1 bit fields).
data_offset = decode_word(tmp_sect3, diff, &bit_flag, &range, &code, &in);
} else {
}
else
{
// Assume one byte of advance.
data_offset = 1;
}
@ -260,7 +262,8 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
offset = ((((int)(buf_end - out)) + 1) & 1) + 6;
// Copy data.
do {
do
{
*start++ = *buf_start++;
} while (start < buf_end);
@ -271,4 +274,4 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
}
delete[] tmp;
return result;
}
}