#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void PasswordChecker(void);
void sub_BB4F(unsigned char* Password);//subroutine $BB4F and so on...
void sub_BB21(void);
void sub_BBE0(void);
void sub_BBEA(void);
void SEC_SBC_6502(unsigned char operand);
void ADC_6502_simplified(unsigned char operand);
unsigned char Password[8];//$0766 to $076D in RAM, when a player enters it
unsigned char Invalidity=0;//$0764 in RAM
unsigned char Level;//$$0070 in RAM
unsigned char TimeTens;//$04c5 in RAM
unsigned char TimeOnes;//$04c6 in RAM
unsigned char Byte4BF, Byte17, Byte18;
unsigned char a, x;
unsigned char c=0;//carry flag
//former char Byte76A is Password[4] now, former char Byte76C is Password[6] now

void PasswordGenerator(void);
void BuildORTable(void);
unsigned char* BuildParticularLevelsArray(unsigned char DesiredLevel);//will think of it later...
void SimplifiedLevelGenerator(unsigned char* PassToFill,unsigned char Level);//finds just one 2nd,3rd,6th,8th digit combo

int main()
{
	int Choice;
	printf("Enter g if you'd like to generate a new password.\nEnter a to analyze an existing password.\n");
	Choice=fgetc(stdin);
	flushall();
	if (Choice=='a')
	PasswordChecker();
	if (Choice=='g')
	PasswordGenerator();
	if (Choice=='s')//'level function' is basic when generating a pass
	BuildORTable();//so here a bit of 'hidden' investigation, which will be useful
	//if I ever decide to rewrite this prog to output all passes possible, not just one
	printf("Press any key to quit.\n");
	getch();
	return 0;
}

void PasswordChecker(void)
{
	char InputString[9];//one extra byte needed due to fgets
	int i;
	printf("Please enter your password to test:\n");
	fgets(InputString,9,stdin);
	for(i=0;i<8;i++)
	{
		if ((InputString[i]>57)||(InputString[i]<48))
		{
			printf("This string contains non-digits.\n");
			return;
		}
		else
			Password[i]=InputString[i]-48;//ascii to digit
	}
	sub_BB4F(Password);
	if (Invalidity==1)
	{
		printf("This password is invalid.\n");
		return;
	}
	printf("%s%d","Level: ",Level);
	printf("%s%d%d\n"," Time: ",TimeTens,TimeOnes);
	if (Level==15)
	printf("Level 15 doesn't exist. So-called level 15 passwords are programming mistakes and cause system hang.\n");
	if (Level==16)
	printf("Level 16 doesn't exist. So-called level 16 passwords are programming mistakes and lead you to a buggy screen where Prince can't move.\n");
	return;
}

void sub_BB4F(unsigned char* Password)//$BB4F
{
	a=0;
	x=0;
	while (x<8)
	{
		a=a+Password[x];
		x++;
	}
	if(a==0)
	{
		Invalidity=1;//$BBC0
		return;
	}
	Byte17=Password[4];//$BB63
	Byte18=Password[6];
	Password[4]=0;
	Password[6]=0;
	sub_BB21();//$BB72,calculates and writes 1st checksum to Password[4], 2nd checksum to Password[6]
	if (Password[4]!=Byte17)
	{
		Invalidity=1;
		return;
	}
	if (Password[6]!=Byte18)//$BB7C
	{
		Invalidity=1;
		return;
	}
	Invalidity=0;//$BB85
	a=Password[7];
	sub_BBEA();
	a=a&3;//$BB8E
	a=a*4;
	Password[7]=a;
	a=Password[1];
	sub_BBE0();//$BB98
	a=a|Password[7];
	Level=a+1;//+1 is my insertion
	//if (Level!=1)//I chose to omit this $BBA2-$BBA4 code b/c it's unknown what byte at $06EE means
	a=Password[0];
	sub_BBE0();//$BBAA
	TimeTens=a;
	a=Password[3];
	sub_BBEA();
	TimeOnes=a;
	return;//$BBBF
}

void SEC_SBC_6502(unsigned char operand)
{
	c=1;
	if ((a-operand)>=0)
		a=a-operand;
	else
	{
		a=a-operand+256;
		c=0;
	};
}

void ADC_6502_simplified(unsigned char operand)
{
	if ((a+operand)<256)
	a=a+operand;
	else a=a+operand-256;
}

void sub_BB21(void)
{
	x=0;
BB23:	a=Password[4];
	a=a+Password[x];
	if(a<10)
	{
BB46:	Password[4]=a;//$BB46
		x++;
		if (x!=8)
		goto BB23;
		else return;//$BB4E
	}
	else //$BB2E
	{
		Byte4BF=a;
		a=Password[6];
		a++;//we came here b/c c=1
		if (a<10)
		goto BB3D;
		else
		SEC_SBC_6502(10);//can we get here? I doubt...
BB3D:	Password[6]=a;
		a=Byte4BF;
		SEC_SBC_6502(10);//$BB44, no danger of negative result
		goto BB46;
	}
}

void sub_BBE0(void)
{
	SEC_SBC_6502(Password[2]);
	if (c==1)
	return;
	ADC_6502_simplified(10);
	return;
}

void sub_BBEA(void)
{
	SEC_SBC_6502(Password[5]);
	if (c==1)
	return;
	ADC_6502_simplified(10);
	return;
}

void PasswordGenerator(void)
{
	unsigned char DesiredLevel, DesiredTimeTens, DesiredTimeOnes;
	unsigned char GeneratedPass[8];
	char InputLevel[3];//one extra char needed b/c of fgets
    char InputTime[3];
	int i;
	printf("Enter a desired level: ");
	fgets(InputLevel,3,stdin);
	printf("Enter remaining time: ");
	flushall();
	fgets(InputTime,3,stdin);
	if((InputLevel[0]==32)||(InputLevel[0]==10))//our defence against user's folly comes first
	InputLevel[0]=48;
	if((InputTime[0]==32)||(InputTime[0]==10))
	InputTime[0]=48;
	if((InputLevel[1]==32)||(InputLevel[1]==10))
	{
		InputLevel[1]=InputLevel[0];
		InputLevel[0]=48;
	}
	if((InputTime[1]==32)||(InputTime[1]==10))
	{
		InputTime[1]=InputTime[0];
		InputTime[0]=48;
	}
	for(i=0;i<2;i++)//then comes a real check
	{
		if ((InputLevel[i]>57)||(InputLevel[i]<48)||(InputTime[i]>57)||(InputTime[i]<48))
		{
			printf("Your data contains non-digits.\n");
			return;
		}
	};
	if((atoi(InputLevel)>0)&&(atoi(InputLevel)<15))
	DesiredLevel=(unsigned char)atoi(InputLevel);
	else
	{
		printf("Your level is out of 1-14 range.\n");
		return;
	};
	DesiredTimeTens=InputTime[0]-48;//0 mins is also possible:11111112
	DesiredTimeOnes=InputTime[1]-48;//99 mins is also possible:99097030
	SimplifiedLevelGenerator(GeneratedPass, DesiredLevel);
	GeneratedPass[0]=DesiredTimeTens;
	GeneratedPass[3]=DesiredTimeOnes;//now 6 digits are filled
	for (i=0;i<8;i++)
	Password[i]=GeneratedPass[i];
	Password[4]=0;
	Password[6]=0;
	sub_BB21();//calculates checksums for us
	GeneratedPass[4]=Password[4];
	GeneratedPass[6]=Password[6];//now all 8 digits are stored
	for (i=0;i<8;i++)//let's check our password
	Password[i]=GeneratedPass[i];
	sub_BB4F(Password);
	if (Invalidity==1)
	{
		printf("This passgen miserably failed due to bugs.\n");
		return;
	}
	printf("Your password is generated and confirmed to be correct: \n");
	for(i=0;i<8;i++)
	{
		printf("%d",GeneratedPass[i]);
	}
	printf("\n");
	return;
}

void BuildORTable(void)
{//our goal's to find all n2res/n8res combos for the given time and level
	unsigned char x, y, current_result;
	unsigned char n2result[10]={0,1,2,3,4,5,6,7,8,9};
	unsigned char n8result[4]={0,4,8,12};
	for(x=0;x<10;x++)
	{
		for(y=0;y<4;y++)
		{
			current_result=n2result[x]|n8result[y];
			if(current_result<14)
			printf("%d: %d %d\n",current_result+1,n2result[x],n8result[y]);
		}
	}
	printf("Now smaller results: \n");
	for(x=0;x<10;x++)//seek what sBC(N8-N6) should amount
	{
		for(y=0;y<4;y++)
		{
			current_result=(x&3)*4;
			if(current_result==n8result[y])
			printf("%d: %d\n",n8result[y],x);
		}
	}
}

unsigned char* BuildParticularLevelsArray(unsigned char DesiredLevel)
{
}

void SimplifiedLevelGenerator(unsigned char* PassToFill,unsigned char Level)//finds just one 2nd,3rd,6th,8th digit combo
{
	unsigned char x,y,n2result,n8result,current_result;
	unsigned char n2results[10]={0,1,2,3,4,5,6,7,8,9};//SBC(N2-N3)
	unsigned char n8results[4]={0,4,8,12};
	unsigned char n8minorresult;//SBC(N8-N6)
	for(x=0;x<10;x++)
	{
		for(y=0;y<4;y++)
		{
			current_result=n2results[x]|n8results[y];
			if(current_result==(Level-1))//level x is internally stored in x-1 presentation
			{
				n2result=n2results[x];
				n8result=n8results[y];
				break;
			};
		}
	}
	for(x=0;x<10;x++)
	{
		if ((x&3)*4==n8result)
		{
			n8minorresult=x;
			break;
		}
	}
	PassToFill[2]=0;
	PassToFill[1]=n2result;
	PassToFill[5]=0;
	PassToFill[7]=n8minorresult;
}
