#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <vector>
#include <sstream>
#include <fstream>
#ifdef _WIN32 || _WIN64
#include <windows.h>
#include <conio.h>
#define mkfolder(dirname) CreateDirectoryA(dirname, NULL)
#else
#ifdef __linux__ //untested
#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>
#include <unistd.h>
#define mkfolder(dirname) mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
int getch(void)
{
struct termios oldt,
newt;
int ch;
tcgetattr( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
return ch;
}
#else
#error "THIS OS NOT SUPPORTED YET!"
#endif
#endif
#define FourCC 0x5A4F434D
#define ItemFourCC 0x5850494D
#define MobFourCC 0x5450494D
#define IndexHeader 0x444B5045
#define IndexVersion 2
#define IndexBlockSize 0xC0
#define delta -1640531527 //-0x61C88647
#define LZO_E_OK 1
#define LZO_E_INPUT_OVERRUN (-1)
#define LZO_E_EOF_NOT_FOUND (-2)
#define LZO_E_INPUT_NOT_CONSUMED (-3)
#define IndexName ".eix"
#define DataName ".epk"
int crashi = 0;
unsigned char IndexXTEA[] = {0xB9, 0x9E, 0xB0, 0x02, 0x6F, 0x69, 0x81, 0x05, 0x63, 0x98, 0x9B, 0x28, 0x79, 0x18, 0x1A, 0x00,};
unsigned char DataXTEA[] = {0x22, 0xB8, 0xB4, 0x04, 0x64, 0xB2, 0x6E, 0x1F, 0xAE, 0xEA, 0x18, 0x00, 0xA6, 0xF6, 0xFB, 0x1C,};
int XteaEncrypt(unsigned long* output, unsigned long* input, unsigned char* XTEA, int size)
{
int round_count = 32;
int rounds = 0;
if (size & 7) size = (size & 0xFFFFFFF8) + 8;
if(size) {
do {
output[0] = input[0];
output[1] = input[1];
unsigned int sum = 0;
for (int i=0; i < round_count; i++) {
output[0] += (((output[1] << 4) ^ (output[1] >> 5)) + output[1]) ^ (sum + *(unsigned long*)(XTEA + 4 * (sum & 3)));
sum += delta;
output[1] += (((output[0] << 4) ^ (output[0] >> 5)) + output[0]) ^ (sum + *(unsigned long*)(XTEA + 4 * ((sum >> 11) & 3)));
}
input += 2;
output += 2;
++rounds;
} while ( size/8 > rounds );
}
return size;
}
int XteaDecrypt(unsigned long* output, unsigned long* input, unsigned char* XTEA, int size)
{
int round_count = 32;
int rounds = 0;
if (size & 7) size = (size & 0xFFFFFFF8) + 8;
if(size) {
do {
output[0] = input[0];
output[1] = input[1];
unsigned int sum = delta * round_count;
for (int i=0; i < round_count; i++) {
output[1] -= (((output[0] << 4) ^ (output[0] >> 5)) + output[0]) ^ (sum + *(unsigned long*)(XTEA + 4 * ((sum >> 11) & 3)));
sum -= delta;
output[0] -= (((output[1] << 4) ^ (output[1] >> 5)) + output[1]) ^ (sum + *(unsigned long*)(XTEA + 4 * (sum & 3)));
}
input += 2;
output += 2;
++rounds;
} while ( size/8 > rounds );
}
return size;
}
static unsigned long lzo_docompress(const unsigned char* in , unsigned long in_len, unsigned char* out, unsigned long* out_len, unsigned long ti, void* wrkmem)
{
register const unsigned char* ip;
unsigned char* op;
const unsigned char* const in_end = in + in_len;
const unsigned char* const ip_end = in + in_len - 20;
const unsigned char* ii;
unsigned short* const dict = (unsigned short*)wrkmem;
op = out;
ip = in;
ii = ip;
ip += ti < 4 ? 4 - ti : 0;
for (;;)
{
const unsigned char* m_pos;
unsigned long m_off;
unsigned long m_len;
{
int dv;
unsigned long dindex;
literal:
ip += 1 + ((ip - ii) >> 5);
next:
if (ip >= ip_end)
break;
dv = (* (volatile const int*) (volatile const void*) (ip));
dindex = ((unsigned long) (((((((unsigned long) ((0x1824429d) * (dv)))) >> (32-14))) & ( ((1u << 14) - 1) >> (0))) << (0)));
m_pos = in+dict[dindex];
dict[dindex] = ((unsigned short) ((unsigned long) ((ip)-(in))));
if (dv != (* (volatile const int*) (volatile const void*) (m_pos)))
goto literal;
}
ii -= ti; ti = 0;
{
register unsigned long t = (unsigned long) ((ip)-(ii));
if (t != 0)
{
if (t <= 3)
{
op[-2] |= (unsigned char)(t);
((* (volatile int*) (volatile void*) (op)) = (int) ((* (volatile const int*) (volatile const void*) (ii))));
op += t;
}
else if (t <= 16)
{
*op++ = (unsigned char)(t - 3);
((* (volatile int*) (volatile void*) (op)) = (int) ((* (volatile const int*) (volatile const void*) (ii))));
((* (volatile int*) (volatile void*) (op+4)) = (int) ((* (volatile const int*) (volatile const void*) (ii+4))));
((* (volatile int*) (volatile void*) (op+8)) = (int) ((* (volatile const int*) (volatile const void*) (ii+8))));
((* (volatile int*) (volatile void*) (op+12)) = (int) ((* (volatile const int*) (volatile const void*) (ii+12))));
op += t;
}
else
{
if (t <= 18)
*op++ = (unsigned char)(t - 3);
else
{
register unsigned long tt = t - 18;
*op++ = 0;
while (tt > 255)
{
tt -= 255;
* (volatile unsigned char *) op++ = 0;
}
*op++ = (unsigned char)(tt);
}
do {
((* (volatile int*) (volatile void*) (op)) = (int) ((* (volatile const int*) (volatile const void*) (ii))));
((* (volatile int*) (volatile void*) (op+4)) = (int) ((* (volatile const int*) (volatile const void*) (ii+4))));
((* (volatile int*) (volatile void*) (op+8)) = (int) ((* (volatile const int*) (volatile const void*) (ii+8))));
((* (volatile int*) (volatile void*) (op+12)) = (int) ((* (volatile const int*) (volatile const void*) (ii+12))));
op += 16; ii += 16; t -= 16;
} while (t >= 16); if (t > 0)
{ do *op++ = *ii++; while (--t > 0); }
}
}
}
m_len = 4;
{
int v;
v = (* (volatile const int*) (volatile const void*) (ip + m_len)) ^ (* (volatile const int*) (volatile const void*) (m_pos + m_len));
if (v == 0) {
do {
m_len += 4;
v = (* (volatile const int*) (volatile const void*) (ip + m_len)) ^ (* (volatile const int*) (volatile const void*) (m_pos + m_len));
if (ip + m_len >= ip_end)
goto m_len_done;
} while (v == 0);
}
unsigned long res;
m_len += res / 8;
}
m_len_done:
m_off = (unsigned long) ((ip)-(m_pos));
ip += m_len;
ii = ip;
if (m_len <= 8 && m_off <= 0x0800)
{
m_off -= 1;
*op++ = (unsigned char)(((m_len - 1) << 5) | ((m_off & 7) << 2));
*op++ = (unsigned char)(m_off >> 3);
}
else if (m_off <= 0x4000)
{
m_off -= 1;
if (m_len <= 33)
*op++ = (unsigned char)(32 | (m_len - 2));
else
{
m_len -= 33;
*op++ = 32 | 0;
while (m_len > 255)
{
m_len -= 255;
* (volatile unsigned char *) op++ = 0;
}
*op++ = (unsigned char)(m_len);
}
*op++ = (unsigned char)(m_off << 2);
*op++ = (unsigned char)(m_off >> 6);
}
else
{
m_off -= 0x4000;
if (m_len <= 9)
*op++ = (unsigned char)(16 | ((m_off >> 11) & 8) | (m_len - 2));
else
{
m_len -= 9;
*op++ = (unsigned char)(16 | ((m_off >> 11) & 8));
while (m_len > 255)
{
m_len -= 255;
* (volatile unsigned char *) op++ = 0;
}
*op++ = (unsigned char)(m_len);
}
*op++ = (unsigned char)(m_off << 2);
*op++ = (unsigned char)(m_off >> 6);
}
goto next;
}
*out_len = (unsigned long) ((op)-(out));
return (unsigned long) ((in_end)-(ii-ti));
}
int lzo_compress(const unsigned char* in , unsigned long in_len, unsigned char* out, unsigned long* out_len)
{
const unsigned char* ip = in;
unsigned char* op = out;
unsigned long l = in_len;
unsigned long t = 0;
void* wrkmem = new void*[16384];
while (l > 20)
{
unsigned long ll = l;
size_t ll_end;
ll = ((ll) <= (49152) ? (ll) : (49152));
ll_end = (size_t)ip + ll;
if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const unsigned char*)(ll_end + ((t + ll) >> 5)) <= ip + ll) break;
memset(wrkmem, 0, ((unsigned long)1 << 14) * sizeof(unsigned short));
t = lzo_docompress(ip,ll,op,out_len,t,wrkmem);
ip += ll;
op += *out_len;
l -= ll;
}
t += l;
if (t > 0)
{
const unsigned char* ii = in + in_len - t;
if (op == out && t <= 238)
*op++ = (unsigned char)(17 + t);
else if (t <= 3)
op[-2] |= (unsigned char)(t);
else if (t <= 18)
*op++ = (unsigned char)(t - 3);
else
{
unsigned long tt = t - 18;
*op++ = 0;
while (tt > 255)
{
tt -= 255;
* (volatile unsigned char *) op++ = 0;
}
*op++ = (unsigned char)(tt);
}
do *op++ = *ii++; while (--t > 0);
}
*op++ = 16 | 1;
*op++ = 0;
*op++ = 0;
*out_len = (unsigned long) ((op)-(out));
return LZO_E_OK;
}
int lzo_decompress( const unsigned char* in , unsigned long in_len, unsigned char* out, unsigned long* out_len)
{
register unsigned char* op;
register const unsigned char* ip;
register unsigned long t;
register const unsigned char* m_pos;
const unsigned char* const ip_end = in + in_len;
unsigned char* const op_end = out + *out_len;
*out_len = 0;
op = out;
ip = in;
if (*ip > 17)
{
t = *ip++ - 17;
if (t < 4) goto match_next;
do *op++ = *ip++; while (--t > 0);
goto first_literal_run;
}
while (ip < ip_end)
{
t = *ip++;
if (t >= 16)
goto match;
if (t == 0)
{
while (*ip == 0)
{
t += 255;
ip++;
}
t += 15 + *ip++;
}
((* (volatile unsigned int*) (volatile void*) (op)) = (unsigned long) (* (volatile const unsigned int*) (volatile const void*) (ip)));
op += 4; ip += 4;
if (--t > 0)
{
if (t >= 4)
{
do {
((* (volatile unsigned int*) (volatile void*) (op)) = (unsigned long) (* (volatile const unsigned int*) (volatile const void*) (ip)));
op += 4; ip += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *ip++; while (--t > 0);
}
else
do *op++ = *ip++; while (--t > 0);
}
first_literal_run:
t = *ip++;
if (t >= 16) goto match;
m_pos = op - (1 + 0x0800);
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
*op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
goto match_done;
do {
match:
if (t >= 64)
{
m_pos = op - 1;
m_pos -= (t >> 2) & 7;
m_pos -= *ip++ << 3;
t = (t >> 5) - 1;
goto copy_match;
}
else if (t >= 32)
{
t &= 31;
if (t == 0)
{
while (*ip == 0)
{
t += 255;
ip++;
}
t += 31 + *ip++;
}
m_pos = op - 1;
m_pos -= (* (volatile const unsigned short*) (volatile const void*) (ip)) >> 2;
ip += 2;
}
else if (t >= 16)
{
m_pos = op;
m_pos -= (t & 8) << 11;
t &= 7;
if (t == 0)
{
while (*ip == 0)
{
t += 255;
ip++;
}
t += 7 + *ip++;
}
m_pos -= (* (volatile const unsigned short*) (volatile const void*) (ip)) >> 2;
ip += 2;
if (m_pos == op)
goto eof_found;
m_pos -= 0x4000;
}
else
{
m_pos = op - 1;
m_pos -= t >> 2;
m_pos -= *ip++ << 2;
*op++ = *m_pos++; *op++ = *m_pos;
goto match_done;
}
if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
{
((* (volatile unsigned int*) (volatile void*) (op)) = (unsigned long) (* (volatile const unsigned int*) (volatile const void*) (m_pos)));
op += 4; m_pos += 4; t -= 4 - (3 - 1);
do {
((* (volatile unsigned int*) (volatile void*) (op)) = (unsigned long) (* (volatile const unsigned int*) (volatile const void*) (m_pos)));
op += 4; m_pos += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *m_pos++; while (--t > 0);
}
else
{
copy_match:
*op++ = *m_pos++; *op++ = *m_pos++;
do *op++ = *m_pos++; while (--t > 0);
}
match_done:
t = ip[-2] & 3;
if (t == 0)
break;
match_next:
*op++ = *ip++;
if (t > 1) {
*op++ = *ip++;
if (t > 2)
{
*op++ = *ip++;
}
}
t = *ip++;
} while (ip < ip_end);
}
*out_len = ((unsigned long) ((op)-(out)));
return LZO_E_EOF_NOT_FOUND;
eof_found:
*out_len = ((unsigned long) ((op)-(out)));
return (ip == ip_end ? LZO_E_OK :
(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
}
static const int crctable[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
unsigned long CRC32(unsigned char* buffer, int size) {
unsigned long crc = 0xffffffff;
for (int i = 0; i < size; i++) crc = (crc >> 8) ^ crctable[buffer[i] ^ crc & 0x000000FF];
return ~crc;
}
void pause()
{
printf("Press a key to continue...\n");
getch();
}
int main(int argc, char * argv[])
{
printf("Metin2 File Tool By balika011\nVersion: 1.1\n\nThanks to:\n Memory leak fix, r26+ type2 --> tim66613\n Used sources --> pushedx, wikipedia, Markus F.X.J. Oberhumer\n\n");
if(argc != 2)
{
std::string exename = argv[0];
exename = exename.substr(exename.find_last_of("\\") + 1, exename.find_last_of(".") - exename.find_last_of("\\") - 1);
printf("Usage: %s <.dat file>\n\nunpack:\n unpack|pack_name|out_folder|out_dat_name\npack:\n pack|pack_name\n\tfile_name|file_path|file_type\ncomment:\n start line whit \"--\"\n", exename.c_str());
pause();
return -1;
}
std::ifstream myfile(argv[1]);
if (myfile.is_open())
{
while(1)
{
std::string line;
std::getline(myfile,line);
LAB1:
if(strlen(line.c_str()) == 0 || line.substr(0, 2) == "--") if(!myfile.good()) break; else continue;
if(line.substr(0, 4) == "pack")
{
if(strlen(line.c_str())-5 < 1) continue;
std::string outfile = line.substr(5, strlen(line.c_str())-5);
bool agin = 0;
std::string file[9999];
std::string path[9999];
int type[9999];
int filecount = 0;
while(1)
{
std::getline(myfile,line);
if(strlen(line.c_str()) == 0 || line.substr(0, 2) == "--") if(!myfile.good()) break; else continue;
if(line.substr(0, 1) != "\t")
{
agin = 1;
break;
}
if(strlen(line.c_str())-1 < 1 || line.substr(2, 3) == "--") if(!myfile.good()) break; else continue;
std::string filename = line.substr(1, strlen(line.c_str())-1);
file[filecount] = strtok((char*)(filename.c_str()),"|");
path[filecount] = strtok(NULL, "|");
type[filecount] = atoi(strtok(NULL, "|"));
++filecount;
if(!myfile.good()) break;
}
unsigned char* eixdecompressedBuffer = new unsigned char[0x0C + filecount * IndexBlockSize];
memset(eixdecompressedBuffer, 0, 0x0C + filecount * IndexBlockSize);
eixdecompressedBuffer += 0x0C;
unsigned char* epkBuffer = new unsigned char[536870911]; //512MB
int lastoffset = 0;
int donefiles = 0;
for(int i=0; i < filecount; ++i) {
unsigned char* Buffer;
unsigned long Size;
FILE* File = fopen(path[i].c_str() , "rb" );
if (File == NULL) {
printf("Could not open %s file.\n", path[i].c_str());
if(agin) goto LAB1; else return 0;
}
fseek(File , 0 , SEEK_END);
Size = ftell(File);
rewind(File);
Buffer = new unsigned char[Size];
if (Buffer == NULL) {
printf("Memory error when make buffer for %s file.\n", path[i].c_str());
if(agin) goto LAB1; else return 0;
}
if (fread(Buffer,1,Size,File) != Size) {
printf("Could not read %s file.\n", path[i].c_str());
if(agin) goto LAB1; else return 0;
}
fclose(File);
*(unsigned long*)eixdecompressedBuffer = i;
memcpy(eixdecompressedBuffer + 4, file[i].c_str(), strlen(file[i].c_str()));
*(unsigned long*)(eixdecompressedBuffer + 168) = CRC32((unsigned char*)file[i].c_str(),strlen(file[i].c_str()));
*(unsigned long*)(eixdecompressedBuffer + 184) = lastoffset;
*(unsigned char*)(eixdecompressedBuffer + 188) = type[i];
if(type[i] == 0){
*(unsigned long*)(eixdecompressedBuffer + 172) = Size;
*(unsigned long*)(eixdecompressedBuffer + 176) = Size;
*(unsigned long*)(eixdecompressedBuffer + 180) = CRC32(Buffer, Size);
memset(epkBuffer + lastoffset, 0, Size);
memcpy(epkBuffer + lastoffset, Buffer, Size);
lastoffset += Size;
}
else if(type[i] == 1){
unsigned char* compressedBuffer = new unsigned char[Size + (Size / 16) + 64 + 3 + 20];
memset(compressedBuffer, 0, Size + (Size / 16) + 64 + 3 + 20);
unsigned long compSize = 0;
if(lzo_compress(Buffer, Size, compressedBuffer + 20, &compSize) != LZO_E_OK)
{
printf("Error when compressing %s.\n", file[i].c_str());
delete [] compressedBuffer;
pause();
if(agin) goto LAB1; else return 0;
}
*(unsigned long*)compressedBuffer = FourCC;
*(unsigned long*)(compressedBuffer + 8) = compSize;
*(unsigned long*)(compressedBuffer + 12) = Size;
*(unsigned long*)(compressedBuffer + 16) = FourCC;
memset(epkBuffer + lastoffset, 0, compSize + 20);
memcpy(epkBuffer + lastoffset, compressedBuffer, compSize + 20);
*(unsigned long*)(eixdecompressedBuffer + 172) = Size;
*(unsigned long*)(eixdecompressedBuffer + 176) = compSize + 4;
*(unsigned long*)(eixdecompressedBuffer + 180) = CRC32(Buffer, Size);
lastoffset += compSize + 20;
delete[] compressedBuffer;
}
else if(type[i] == 2)
{
unsigned char* compressedBuffer = new unsigned char[Size + (Size / 16) + 64 + 3 + 4];
memset(compressedBuffer, 0, Size + (Size / 16) + 64 + 3 + 4);
unsigned long compSize = 0;
if(lzo_compress(Buffer, Size, compressedBuffer + 4, &compSize) != LZO_E_OK)
{
printf("Error when compressing %s.\n", file[i].c_str());
delete [] compressedBuffer;
pause();
if(agin) goto LAB1; else return 0;
}
*(unsigned long*)compressedBuffer = FourCC;
unsigned char* encryptedBuffer = new unsigned char[compSize + 4 + 7];
memset(encryptedBuffer, 0, compSize + 4 + 7);
unsigned long cryptSize = XteaEncrypt((unsigned long*)encryptedBuffer, (unsigned long*)compressedBuffer, DataXTEA, compSize + 4);
memset(epkBuffer + lastoffset, 0, cryptSize + 16);
*(unsigned long*)(epkBuffer + lastoffset) = FourCC;
*(unsigned long*)(epkBuffer + lastoffset + 4) = cryptSize;
*(unsigned long*)(epkBuffer + lastoffset + 8) = compSize;
*(unsigned long*)(epkBuffer + lastoffset + 12) = Size;
memcpy(epkBuffer + lastoffset + 16, encryptedBuffer, cryptSize);
*(unsigned long*)(eixdecompressedBuffer + 172) = 512 + (512 / (cryptSize + 16));
*(unsigned long*)(eixdecompressedBuffer + 176) = cryptSize;
*(unsigned long*)(eixdecompressedBuffer + 180) = CRC32(epkBuffer + lastoffset, cryptSize);
lastoffset += cryptSize + 16;
delete[] compressedBuffer;
delete[] encryptedBuffer;
}
else
{
printf("type %i is unsupported\n", type[i]);
delete [] Buffer;
continue;
}
eixdecompressedBuffer += IndexBlockSize;
++donefiles;
delete [] Buffer;
}
unsigned long eixdecompressedSize = 0x0C + donefiles * IndexBlockSize;
eixdecompressedBuffer -= eixdecompressedSize;
*(unsigned long*)eixdecompressedBuffer = IndexHeader;
*(unsigned long*)(eixdecompressedBuffer + 4) = IndexVersion;
*(unsigned long*)(eixdecompressedBuffer + 8) = donefiles;
unsigned char* compressedBuffer = new unsigned char[eixdecompressedSize + (eixdecompressedSize / 16) + 64 + 3 + 4];
memset(compressedBuffer, 0, eixdecompressedSize + (eixdecompressedSize / 16) + 64 + 3 + 4);
unsigned long compSize = 0;
if(lzo_compress(eixdecompressedBuffer, eixdecompressedSize, compressedBuffer + 4, &compSize) != LZO_E_OK)
{
printf("Error when compressing index.\n");
delete [] compressedBuffer;
pause();
if(agin) goto LAB1; else return 0;
}
*(unsigned long*)compressedBuffer = FourCC;
unsigned char* encryptedBuffer = new unsigned char[compSize + 4];
memset(encryptedBuffer, 0, compSize + 4);
unsigned long cryptSize = XteaEncrypt((unsigned long*)encryptedBuffer, (unsigned long*)compressedBuffer, IndexXTEA, compSize + 4);
unsigned char* DoneBuffer = new unsigned char[cryptSize + 16];
memset(DoneBuffer, 0, cryptSize + 16);
*(unsigned long*)DoneBuffer = FourCC;
*(unsigned long*)(DoneBuffer + 4) = cryptSize;
*(unsigned long*)(DoneBuffer + 8) = compSize;
*(unsigned long*)(DoneBuffer + 12) = eixdecompressedSize;
memcpy(DoneBuffer + 16, encryptedBuffer, cryptSize);
FILE * indexof = fopen((outfile + IndexName).c_str(), "wb");
if(indexof)
{
fwrite(DoneBuffer, 1, cryptSize + 16, indexof);
fclose(indexof);
}
FILE * dataof = fopen((outfile + DataName).c_str(), "wb");
if(dataof)
{
fwrite(epkBuffer, 1, lastoffset + 16, dataof);
fclose(dataof);
}
printf("Done!\n");
if(agin) goto LAB1;
}
else if(line.substr(0, 6) == "unpack")
{
if(strlen(line.c_str())-7 < 1) continue;
std::string in = line.substr(7, strlen(line.c_str())-7);
char* infile = strtok((char*)(in.c_str()),"|");
std::string outfolder = strtok(NULL, "|");
char* outfile = strtok(NULL, "|");
std::string eixName_ = (std::string)infile + IndexName;
std::string epkName_ = (std::string)infile + DataName;
const char * eixName = eixName_.c_str();
const char * epkName = epkName_.c_str();
unsigned char* eixBuffer;
unsigned long eixSize;
FILE* eixFile = fopen(eixName , "rb" );
if (eixFile == NULL) {
printf("Could not open %s file.\n", eixName);
if(!myfile.good()) {pause(); return 0;} else goto LAB1;
}
fseek(eixFile , 0 , SEEK_END);
eixSize = ftell(eixFile);
rewind(eixFile);
eixBuffer = new unsigned char[eixSize];
if (eixBuffer == NULL) {
printf("Memory error when make buffer for %s file.\n", eixName);
if(!myfile.good()) {pause(); return 0;} else goto LAB1;
}
if (fread(eixBuffer,1,eixSize,eixFile) != eixSize) {
printf("Could not read %s file.\n", eixName);
if(!myfile.good()) {pause(); return 0;} else goto LAB1;
}
fclose(eixFile);
unsigned char* epkBuffer;
unsigned long epkSize;
FILE* epkFile = fopen(epkName , "rb" );
if (epkFile == NULL) {
printf("Could not open %s file.\n", epkName);
if(!myfile.good()) {pause(); return 0;} else goto LAB1;
}
fseek(epkFile , 0 , SEEK_END);
epkSize = ftell(epkFile);
rewind(epkFile);
epkBuffer = new unsigned char[epkSize];
if (epkBuffer == NULL) {
printf("Memory error when make buffer for %s file.\n", epkName);
if(!myfile.good()) {pause(); return 0;} else goto LAB1;
}
if (fread(epkBuffer,1,epkSize,epkFile) != epkSize) {
printf("Could not read %s file.\n", epkName);
if(!myfile.good()) {pause(); return 0;} else goto LAB1;
}
fclose(epkFile);
if(eixSize < 0x0C)
{
printf("The file size for the %s file is too small. The program will now exit.\n", eixName);
pause();
if(!myfile.good()) {pause(); return 0;} else goto LAB1;
}
unsigned char* eixdecompressedBuffer;
unsigned long eixdecompressedSize;
if (*(unsigned long*)eixBuffer != IndexHeader)
{
unsigned long eixheader = *(unsigned long*)eixBuffer;
unsigned long eixcryptedSize = *(unsigned long*)(eixBuffer + 4);
unsigned long eixcompressedSize = *(unsigned long*)(eixBuffer + 8);
eixdecompressedSize = *(unsigned long*)(eixBuffer + 12);
if (eixheader != FourCC)
{
printf("The FourCC of %s is incorrect.\n", eixName);
pause();
if(!myfile.good()) return 0; else goto LAB1;
}
if(eixcryptedSize == 0)
{
printf("[TODO] -- Index of %s is not encrypted!\n", eixName);
pause();
if(!myfile.good()) return 0; else goto LAB1;
}
unsigned char* eixcompressedBuffer = new unsigned char[eixcryptedSize];
memset(eixcompressedBuffer, 0, eixcryptedSize);
XteaDecrypt((unsigned long*)eixcompressedBuffer, (unsigned long*)(eixBuffer + 0x10), IndexXTEA, eixcryptedSize);
if(*(unsigned long*)eixcompressedBuffer != FourCC)
{
delete [] eixcompressedBuffer;
printf("The XTEA Key of %s is incorrect.\n", eixName);
pause();
if(!myfile.good()) return 0; else goto LAB1;
}
eixdecompressedBuffer = new unsigned char[eixdecompressedSize];
memset(eixdecompressedBuffer, 0, eixdecompressedSize);
unsigned long finalSize = 0;
if(lzo_decompress(eixcompressedBuffer + 4, eixcompressedSize, eixdecompressedBuffer, &finalSize) != LZO_E_OK || finalSize != eixdecompressedSize)
{
delete [] eixdecompressedBuffer;
delete [] eixcompressedBuffer;
printf("There was an error when decompressing %s.\n", eixName);
if(!myfile.good()) return 0; else goto LAB1;
}
delete [] eixcompressedBuffer;
}
else
{
eixdecompressedBuffer = eixBuffer + 4;
eixdecompressedSize = eixSize - 4;
}
unsigned long eixheader2 = *(unsigned long*)eixdecompressedBuffer;
unsigned long eixversion = *(unsigned long*)(eixdecompressedBuffer + 4);
unsigned long eixfileCount = *(unsigned long*)(eixdecompressedBuffer + 8);
if(eixversion != IndexVersion)
{
delete [] eixdecompressedBuffer;
printf("The version of %s file is incorrect. Found: %i Supported: %i).\n", eixName, eixversion, IndexVersion);
pause();
if(!myfile.good()) return 0; else goto LAB1;
}
std::string filename = ((std::string)infile).substr(1 + ((std::string)infile).find_last_of("\\/"));
eixdecompressedBuffer += 0x0C;
FILE * of = fopen(outfile, "w");
if(!of)
{
printf("There was an error creating %s file.\n", "name");
pause();
if(!myfile.good()) return 0; else goto LAB1;
}
if(of) fprintf(of, "pack|%s\n", infile);
for(unsigned long x = 0; x < eixfileCount; ++x)
{
unsigned long index = *(unsigned long*)eixdecompressedBuffer;
char filename[160];
memcpy(filename,eixdecompressedBuffer + 4,160);
unsigned long filenameCRC = *(unsigned long*)(eixdecompressedBuffer + 168);
unsigned long dw3 = *(unsigned long*)(eixdecompressedBuffer + 172);
unsigned long dwSrcSize = *(unsigned long*)(eixdecompressedBuffer + 176);
unsigned long unpackedCRC = *(unsigned long*)(eixdecompressedBuffer + 180);
unsigned long dwFileOffset = *(unsigned long*)(eixdecompressedBuffer + 184);
unsigned char packedType = *(unsigned char*)(eixdecompressedBuffer + 188);
eixdecompressedBuffer += IndexBlockSize;
std::string outfilename;
if(packedType == 0)
{
std::stringstream dirPath;
std::vector<std::string> pathTokens;
size_t p0 = 0, p1 = std::string::npos;
while(p0 != std::string::npos)
{
p1 = ((const std::string&)filename).find_first_of("\\/", p0);
if(p1 != p0)
{
std::string token = ((const std::string&)filename).substr(p0, p1 - p0);
pathTokens.push_back(token);
}
p0 = ((const std::string&)filename).find_first_not_of("\\/", p1);
}
dirPath << outfolder;
mkfolder(dirPath.str().c_str());
dirPath << "\\";
size_t index = 0;
for(index = 0; index < pathTokens.size() - 1; ++index)
{
if(pathTokens[index].find_first_of(":") != std::string::npos)
continue;
dirPath << pathTokens[index];
mkfolder(dirPath.str().c_str());
dirPath << "\\";
}
dirPath << pathTokens[index];
outfilename = dirPath.str();
FILE * of = fopen(outfilename.c_str(), "wb");
if(!of)
{
std::string buff = outfolder + "\\crashfile" + (char)crashi;
++crashi;
of = fopen(buff.c_str(), "wb");
printf("Crash file %s saved as: %s\n", outfilename.c_str(), buff.c_str());
outfilename = buff;
}
if(of)
{
fwrite(epkBuffer + dwFileOffset, 1, dwSrcSize, of);
fclose(of);
}
else
{
printf("Could not save the file %s\n", outfilename.c_str());
}
}
else if(packedType == 1)
{
unsigned long dataheader = *(unsigned long*)(epkBuffer + dwFileOffset);
unsigned long datacryptedSize = *(unsigned long*)(epkBuffer + dwFileOffset + 4);
unsigned long datacompressedSize = *(unsigned long*)(epkBuffer + dwFileOffset + 8);
unsigned long datadecompressedSize = *(unsigned long*)(epkBuffer + dwFileOffset + 12);
if(dataheader != FourCC)
{
printf("The FourCC is incorrect of %s.\n", filename);
continue;
}
unsigned char* datauncompressedBuffer = new unsigned char[datadecompressedSize];
memset(datauncompressedBuffer, 0, datadecompressedSize);
unsigned long finalSize = 0;
if(lzo_decompress(epkBuffer + dwFileOffset + 16 + 4, datacompressedSize, datauncompressedBuffer, &finalSize) == LZO_E_OK && finalSize == datadecompressedSize)
{
std::stringstream dirPath;
std::vector<std::string> pathTokens;
size_t p0 = 0, p1 = std::string::npos;
while(p0 != std::string::npos)
{
p1 = ((const std::string&)filename).find_first_of("\\/", p0);
if(p1 != p0)
{
std::string token = ((const std::string&)filename).substr(p0, p1 - p0);
pathTokens.push_back(token);
}
p0 = ((const std::string&)filename).find_first_not_of("\\/", p1);
}
dirPath << outfolder;
mkfolder(dirPath.str().c_str());
dirPath << "\\";
size_t index = 0;
for(index = 0; index < pathTokens.size() - 1; ++index)
{
if(pathTokens[index].find_first_of(":") != std::string::npos)
continue;
dirPath << pathTokens[index];
mkfolder(dirPath.str().c_str());
dirPath << "\\";
}
dirPath << pathTokens[index];
outfilename = dirPath.str();
FILE * of = fopen(outfilename.c_str(), "wb");
if(!of)
{
std::string buff = outfolder + "\\crashfile" + (char)crashi;
++crashi;
of = fopen(buff.c_str(), "wb");
printf("Crash file %s saved as: %s\n", outfilename.c_str(), buff.c_str());
outfilename = buff;
}
if(of)
{
fwrite(datauncompressedBuffer, 1, datadecompressedSize, of);
fclose(of);
}
else
{
printf("Could not save the file %s\n", outfilename.c_str());
}
}
else
{
printf("There was an error when decompressing %s file.\n", filename);
}
delete [] datauncompressedBuffer;
}
else if(packedType == 2)
{
unsigned long dataheader = *(unsigned long*)(epkBuffer + dwFileOffset);
unsigned long datacryptedSize = *(unsigned long*)(epkBuffer + dwFileOffset + 4);
unsigned long datacompressedSize = *(unsigned long*)(epkBuffer + dwFileOffset + 8);
unsigned long datadecompressedSize = *(unsigned long*)(epkBuffer + dwFileOffset + 12);
if(dataheader != FourCC)
{
printf("The FourCC is incorrect of %s.\n", filename);
continue;
}
unsigned char* datadecryptedBuffer = new unsigned char[datacryptedSize];
memset(datadecryptedBuffer, 0, datacryptedSize);
XteaDecrypt((unsigned long*)datadecryptedBuffer, (unsigned long*)(epkBuffer + dwFileOffset + 16), DataXTEA, datacryptedSize);
if(*(unsigned long*)datadecryptedBuffer != FourCC)
{
printf("There was an error decrypting the data for the %s file. It will be skipped.\n", filename);
delete [] datadecryptedBuffer;
continue;
}
unsigned char* datauncompressedBuffer = new unsigned char[datadecompressedSize];
memset(datauncompressedBuffer, 0, datadecompressedSize);
unsigned long finalSize = 0;
if(lzo_decompress(datadecryptedBuffer + 4, datacompressedSize, datauncompressedBuffer, &finalSize) == LZO_E_OK && finalSize == datadecompressedSize)
{
std::stringstream dirPath;
std::vector<std::string> pathTokens;
size_t p0 = 0, p1 = std::string::npos;
while(p0 != std::string::npos)
{
p1 = ((const std::string&)filename).find_first_of("\\/", p0);
if(p1 != p0)
{
std::string token = ((const std::string&)filename).substr(p0, p1 - p0);
pathTokens.push_back(token);
}
p0 = ((const std::string&)filename).find_first_not_of("\\/", p1);
}
dirPath << outfolder;
mkfolder(dirPath.str().c_str());
dirPath << "\\";
size_t index = 0;
for(index = 0; index < pathTokens.size() - 1; ++index)
{
if(pathTokens[index].find_first_of(":") != std::string::npos)
continue;
dirPath << pathTokens[index];
mkfolder(dirPath.str().c_str());
dirPath << "\\";
}
dirPath << pathTokens[index];
outfilename = dirPath.str();
FILE * of = fopen(outfilename.c_str(), "wb");
if(!of)
{
std::string buff = outfolder + "\\crashfile" + (char)crashi;
++crashi;
of = fopen(buff.c_str(), "wb");
printf("Crash file %s saved as: %s\n", outfilename.c_str(), buff.c_str());
outfilename = buff;
}
if(of)
{
fwrite(datauncompressedBuffer, 1, datadecompressedSize, of);
fclose(of);
}
else
{
printf("Could not save the file %s\n", outfilename.c_str());
}
}
else
{
printf("There was an error when decompressing %s file.\n", filename);
}
delete [] datadecryptedBuffer;
delete [] datauncompressedBuffer;
}
else
{
printf("Unsupported type: %i (%s).\n", packedType, filename);
continue;
}
fprintf(of, "\t%s|%s|%i\n", filename, outfilename.c_str(), packedType);
}
fclose(of);
printf("Done!\n");
}
else printf("dat file error!\n");
if(!myfile.good()) break;
}
printf("All done!\n");
myfile.close();
}
else printf("%s file not found!\n", argv[1]);
pause();
return 0;
}