//
// TSM 3/4/5/5m unlock code algo
//
// indear
//

#include <stdio.h>
#include <string.h>

const static unsigned char tabla1[][16] = {
	{0x0C,0x2D,0x22,0x43,0x17,0x02,0x13,0x0A,0x0F,0x63,0x4C,0x2D,0x5B,0x03,0x37,0x3B},
	{0x05,0x17,0x43,0x4C,0x0C,0x16,0x4E,0x13,0x59,0x32,0x2B,0x38,0x56,0x0B,0x0F,0x63},
	{0x16,0x21,0x44,0x00,0x5F,0x51,0x16,0x02,0x12,0x1F,0x35,0x34,0x28,0x59,0x32,0x1C},
	{0x13,0x31,0x08,0x18,0x5F,0x3F,0x1A,0x37,0x19,0x2B,0x07,0x57,0x08,0x08,0x2A,0x08}
};

const static unsigned int tabla2[][4] = {
	{0x1E2D3E4F,0xF5E6F7C8,0x9E0D1E2F,0x3E4D5A6E},
	{0x7A8E9E0D,0xB1E2D3A4,0x5A6E7E8D,0x9E0F2E3D},
	{0x676DFCF4,0xC6AAB751,0x4BD0F1B1,0x791BE289},
	{0x3ADA1784,0xC50ECAD5,0x1E34312D,0xFA968262}
};

const static unsigned int tabla3[] = {0x9E3779B9,0x6F55A634,0x682CE8BD,0x7BF8B545};

//tipo:
//
//0 - TSM3/4/5 NCK
//1 - TSM3/4/5 SPCK
//2 - TSM5m NCK
//3 - TSM5m SPCK

static void calcula_codigo( char *imei, char tipo, char *codigo )
{
	unsigned int x, y, z;
	unsigned int destino[8];
	unsigned char IMEI[17];
	int i, j;

	y=0;
	z=0;

	strcpy(IMEI, imei);
	IMEI[14]='0';
	IMEI[15]='0';
	IMEI[16]=0;

	for(i=0; i<8; i++)
	{

		destino[i] = tabla1[tipo][i^0xf];
		destino[i] *= IMEI[0x10-i] - 0x30;
		destino[i] -= (IMEI[i] + IMEI[i^0xf]) % 9;
		destino[i] += 0x39;
	}

	for(i=0; i<0x10; i++)
	{
		y += IMEI[i];
		if ((tipo == 0) || (tipo == 2))
			y -= 0x30;
	}

	for(i=0; i<8; i++)
	{
		for(j=0; j<4; j++)
		{
			x = tabla1[tipo][(i^7) + j];
			destino[i^7] += ((x<<5) ^ (x<<4));
			destino[i^7] += tabla2[tipo][j^3];
		}
		destino[i^7] += (y + tabla3[tipo] * (i+1)) << 2;
	}

	for(i=0; i<8; i++)
	{
		y = destino[(i+y) % 6];
		codigo[i] = (char)(0x39 - (y%10));
		z += codigo[i];
	}

	if(codigo[0] == 0x30)
	{
		codigo[0] = (char)(0x39 - (z%9));
	}

	codigo[8] = 0;
}

void main()
{
	char imei[] = "123456789012347";
	char codigo[9];
	int i;

	for (i=0; i<4; i++)
	{
		calcula_codigo(imei, i, codigo);
		printf("%s\n", codigo);
	}
}
