Code:
using System;
using System.IO;
using System.Text;
namespace TDB
{
/// <summary>
/// Extractor for the TDB file package
/// </summary>
class Program
{
/// <summary>
/// Crypt table
/// </summary>
static readonly byte[] cryptTable = new byte[]
{
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x23, 0x23, 0x23, 0x23, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x6F,
0x75, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x73, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6C,
0x6F, 0x76, 0x65, 0x2E, 0x20, 0x46, 0x72, 0x6F, 0x6D, 0x20, 0x*** 0x34, 0x20, 0x44, 0x65, 0x63,
0x2C, 0x20, 0x31, 0x39, 0x39, 0x34, 0x2E, 0x20, 0x23, 0x23, 0x23, 0x23, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x4F, 0x6F, 0x6F, 0x70, 0x73, 0x2E, 0x20, 0x57, 0x68, 0x6F, 0x20, 0x61,
0x72, 0x65, 0x20, 0x79, 0x6F, 0x75, 0x3F, 0x20, 0x59, 0x6F, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20,
0x6E, 0x6F, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6F, 0x20,
0x72, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x2E, 0x20, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x63, 0x6C, 0x6F, 0x73, 0x65, 0x20,
0x74, 0x68, 0x69, 0x73, 0x2C, 0x20, 0x45, 0x6E, 0x6A, 0x6F, 0x79, 0x20, 0x6F, 0x75, 0x72, 0x20,
0x67, 0x61, 0x6D, 0x65, 0x20, 0x41, 0x33, 0x2C, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x61, 0x6C, 0x77,
0x61, 0x79, 0x73, 0x20, 0x62, 0x65, 0x20, 0x68, 0x61, 0x70, 0x70, 0x79, 0x7E, 0x21, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x20, 0x54, 0x68, 0x65, 0x20, 0x45, 0x78, 0x74,
0x72, 0x61, 0x2D, 0x54, 0x65, 0x72, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x61, 0x6C, 0x20, 0x2D,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
};
/// <summary>
/// File name of the file to extract
/// </summary>
const string FILE_NAME = @"C:\Program Files\A3 Game\Data\00.TDB";
/// <summary>
/// Folder to extract the files into
/// </summary>
const string OUTPUT_FOLDER = @"C:\Output\";
/// <summary>
/// Opens the TDB file and extracts all textures
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
BinaryReader fh = new BinaryReader(File.OpenRead(FILE_NAME));
byte[] version = fh.ReadBytes(32);
int fileCount = fh.ReadInt32();
for (int i = 0; i < fileCount; i++)
{
int fileSize = fh.ReadInt32();
byte[] fileNameBuffer = fh.ReadBytes(128);
fh.ReadInt64();
fh.ReadInt32();
sub_80DAF9(ref fileNameBuffer, 128);
string fileName = Encoding.Default.GetString(fileNameBuffer).Trim('\0');
byte[] fileBuffer = fh.ReadBytes(fileSize);
Console.WriteLine("File Name: {0}; File Size: {1}", fileName, fileSize);
sub_80DAF9(ref fileBuffer, 128);
sub_80DAF9(ref fileBuffer, 32);
File.WriteAllBytes(string.Format(@"{0}\{1}", OUTPUT_FOLDER, fileName), fileBuffer);
}
fh.Close();
Console.Read();
}
/// <summary>
/// Deobfuscates an integer
/// </summary>
/// <param name="value">Value</param>
/// <param name="key">Key</param>
/// <returns></returns>
static int sub_80D772(int value, int key)
{
return (int)(((key & 0xFFFF0000) >> 16) | (key << 16)) ^ value;
}
/// <summary>
/// Deobfuscates an integer
/// </summary>
/// <param name="value">Value</param>
/// <returns>Deobfuscated value</returns>
static int sub_80D939(int value)
{
value += ~(value << 15);
value ^= value >> 10;
value *= 9;
value ^= value >> 6;
value += ~(value << 11);
value ^= value >> 16;
return value;
}
/// <summary>
/// Absolutely no idea what this does generally
/// Used in the decryption process
/// </summary>
/// <param name="buffer">Buffer</param>
/// <param name="size">Size</param>
/// <returns>Some type of key?</returns>
static int sub_80D7FD(byte[] buffer, int size)
{
if (size == 0)
size = buffer.Length - 1;
int keyValue = 0;
for (int i = 0; i < size; i++)
keyValue = (keyValue << 16) + (keyValue << 6) + buffer[i] - keyValue;
return keyValue;
}
/// <summary>
/// Seems to be the main decrypter
/// </summary>
/// <param name="buffer">Buffer</param>
/// <param name="size">Size to decrypt</param>
static void sub_80DAF9(ref byte[] buffer, int size)
{
for (int i = 1, j = size - 1; i < size; i++, j--)
buffer[j] = (byte)(i ^ (size ^ (cryptTable[buffer[j - 1]] ^ buffer[j])));
}
}
}