/* @ NosTale Text File Extractor @ */

//--INCLUDES--
#include <iostream>
#include <sstream>
//--INCLUDES--

//--Decrypt text file--
int decryptnosfile(unsigned char *cData, unsigned int f_buffer, unsigned char *cOut, unsigned int &nOut)
{
	static unsigned char table[] = { 0, 0x20,'-','.','0','1','2','3','4','5','6','7','8','9', 0x0d };
	unsigned int i, offset, len;
	unsigned char size, c;
	len = f_buffer;
	unsigned char *cBuffer;
	cBuffer = (unsigned char*)malloc(f_buffer + 1);
	memcpy(cBuffer, cData, f_buffer);
	offset = nOut = 0;
	while(offset < len)
	{
		if(cBuffer[offset] == 0xFFu)
		{
			offset++;
			*(cOut + nOut++) = 0x0d;
			continue;
		}
		size = cBuffer[offset++];
		i = 0;
		if ((size & 0x80U) == 0)
		{
			while ((i++ < size) && (offset < len))
			{
				*(cOut + nOut++) = (cBuffer[offset++] ^ 0x33U);
			}
		}
		else
		{
			size &= 0x7FU;
			while ((i < size) && (offset < len))
			{
				c = cBuffer[offset++];
				*(cOut + nOut++) = (table[(c & 0xF0U) >> 4]);
				if (table[c & 0x0FU] != 0)
					*(cOut + nOut++) = table[c & 0x0FU];
				i += 2;
			}
		}
	}
	free(cBuffer);
	return offset;
}
//--Decrypt text file--

//--MAIN--
void main()
{
	std::string infile_name;
	unsigned int file_num, file_count, file_name_size, file_crypto_mode, file_size;
	FILE *inFile, *outFile;
	std::cout 
		<< " NTExtractor" << std::endl
		<< " Write file name: ";
	std::cin >> infile_name;
	inFile = fopen(infile_name.c_str(),"rb");
	if(inFile == NULL) 
		return; 
	fread(&file_num, 1, 4, inFile);
	std::cout << file_num << " files found" << std::endl;
	for(auto i = 0; i < file_num; i++)
	{
		fread(&file_count, 1, 4, inFile);
		fread(&file_name_size, 1, 4, inFile);
		char *file_name = (char*)malloc(file_name_size+1);
		fread(file_name, 1, file_name_size, inFile);
		file_name[file_name_size] = 0;
		fread(&file_crypto_mode, 1, 4, inFile);
		fread(&file_size, 1, 4, inFile);
		unsigned char *file = (unsigned char*)malloc(file_size+1);
		fread(file, 1, file_size, inFile);
		file[file_size] = 0;
		std::cout << " File [" << file_count << "] '"<< file_name <<"' size: " << file_size / 1024 << "KB" << std::endl;
		outFile = fopen(file_name,"wb");
		unsigned char *file_decrypted = (unsigned char*)malloc(2*file_size);
		unsigned int file_decrypted_lenght = 0;
		decryptnosfile(file, file_size, file_decrypted, file_decrypted_lenght);
		fwrite(file_decrypted,1, file_decrypted_lenght,outFile);
		std::cout << " The file are decrypted and saved!" << std::endl;
		fclose(outFile);
	}
	fclose(inFile);
	std::cout << " Files extracted correctly" << std::endl;
	_sleep(1000);
}
//--MAIN--