#include "a51.h"
void convert();
void hexs();

void cleanexit(t)
char t[80];
{
	int x;
	LINK tl;
		tl=tag_list;
		x=0;
		hexsflag=0;
		while (tl!=(LINK) NULL)
		{
			if (x==0) fprintf(f_lst,"\n");
			else fprintf(f_lst,"\t");
			hexs(tl->value);
			fprintf(f_lst,"%s\t%s",tl->tag,hexstr);
			tl=tl->next;
		}
		fprintf(f_lst,"\n\n");
		fclose(f_lst);
	printf("****%d\t%s\n",line,buffer);
	printf("ERROR:%s\n",t);
	exit();
}

void warn(t)
char t[80];
{
	printf("++++%d\t%s\n",line,buffer);
	printf("WARNING:%s\n",t);
	return;
}

void strnullcpy(t,u,n)
char t[80];
char u[80];
int n;
{
	strncpy(t,u,n);
	t[n]='\0';
	return;
}

void hack(n)
int n;
{
	int x;
	for (x=0;x<=80;x++)
		s[x]=s[x+n];
	pos-=n;
	return;
}

char hexc(n)
int n;
{
	if ((n+=48)>57) n+=7;
	return((char) n);
}

void hexs(l)
long l;
{
	long m;
	char t[7];
	m=l;
	t[0]=hexc(m/1048576);
	m%=1048576;
	t[1]=hexc(m/65536);
	m%=65536;
	t[2]=hexc(m/4096);
	m%=4096;
	t[3]=hexc(m/256);
	m%=256;
	t[4]=hexc(m/16);
	m%=16;
	t[5]=hexc(m);
	t[6]='\0';
	if (l>65535) {strcpy(hexstr,t);return;}
	if ((l>255)||(hexsflag==1)) {strcpy(hexstr,&t[2]);return;}
	strcpy(hexstr,&t[4]);
	return;
}

void showcode()
{
	int x,y;
	int flag;
	char filename[80];
	char longstr[80];
	strcpy(filename,basename);
	f_hex=fopen(strcat(filename,".hex"),"w");
	if (f_hex==(FILE *) NULL)
		{
		printf("Could not open file.hex for write.");
		return;
		}
	for (x=0;x<32767-16;x+=16)
	{
		flag=0;
		for (y=0;y<=15;y++)
			if (mem[x+y]!=0) flag=1;
		if (flag==1)
		{
			hexsflag=1;
			hexs(x);
			hexsflag=0;
			strcpy(longstr,hexstr);
			strcat(longstr,":    ");
			for (y=0;y<=15;y++)
			{
				hexs(mem[x+y]);
				strcat(longstr,hexstr);
				strcat(longstr," ");
				if (y==7) strcat(longstr," ");
			}
			fprintf(f_hex,"%s\n",longstr);
		}
	}
	fclose(f_hex);
	return;
}	

void codeit(t)
char t[80];
{
	char sht[3];
	char tdup[80];
	char buf[80];
	char tdup2[80];
	int ad,x,y;
	strcpy(tdup,t);	
	if (pass==1) return;
	hexsflag=1;
	hexs(addr);
	hexsflag=0;
	sht[2]='\0';
	strcpy(buf,buffer);
	if (strlen(buffer)>50) strnullcpy(buf,buffer,50);
	strcpy(tdup2,tdup);
	if (strlen(tdup)>6) strnullcpy(tdup2,tdup,6);
	fprintf(f_lst,"%5d %4s  %6s   %s\n",line,hexstr,tdup2,buf);
	
	if (tdup[0]!=' ')
	{
		ad=addr;
		for (x=0;x<strlen(tdup);x+=2)
		{
			y=tdup[x]-48;
			if (y>9) y-=7;
			value=y*16;
			y=tdup[x+1]-48;
			if (y>9) y-=7;
			value+=y;	
			mem[ad++]=value;
		}
	}
	return;
}

int tag_defined(t)
char t[80];
{
	LINK	list;
	list=tag_list;
	while (list!=(LINK) NULL)
	{
		if (strcmp(t,list->tag)==0)
			return(1);
		list=list->next;
	}
	return(0);
} 
	
void add_tag(val) 
int val;
{
	LINK	list;
	list=tag_list;
	if (list!=(LINK) NULL)
		while (list->next!=(LINK) NULL)
			list=list->next;
	if (list==(LINK) NULL)
	{
		tag_list=(LINK) malloc(sizeof(ELEM));
		strcpy(tag_list->tag,name);
		tag_list->value=val;
		tag_list->next=(LINK) NULL;
	}
	else
	{
		list->next=(LINK) malloc(sizeof(ELEM));
		strcpy(list->next->tag,name);
		list->next->value=val;
		list->next->next=(LINK) NULL;
	}
	return;
} 

int validtag(t)
char t[80];
{
	int x;
	for (x=0;x<strlen(t);x++)
	{
		if ((
		((s[x]>='A')&&(s[x]<='Z'))||
		((s[x]>='0')&&(s[x]<='9'))||
		(s[x]=='_')
		)==0)
			return(0);
	}
	return(1);
}
		
void gettag(x)
int x;
{
	strnullcpy(name,s,x);
	if (validtag(name)==0)
		cleanexit("Tag contains extranneous characters.");
	if (pass==1)
	{
		if (tag_defined(name)) cleanexit("Tag already defined.");
		add_tag(addr);
	}
	hack(x+1);
	return;
}

int testbase(b,c)
int b;
char c;
{
	int n;
	n=((int) c)-48;
 if (n<0) return(-1);
	if ((n>9)&&(n<17)) return(-1);
	if (n>9) n-=7;
	if (n>(b-1)) return(-1);
	return(n);
}

void convert(base)
int base;
{
	int x;
	value=0;
	while ((x=testbase(base,s[0]))>=0)
	{
		hack(1);
		value*=base;
		value+=x;
	}
	return;
}
 
int lookup()
{
	LINK	list;
	list=tag_list;
	while (list!=(LINK) NULL)
	{
		if (strcmp(list->tag,name)==0) return(list->value);
		list=list->next;
	}
	cleanexit("Lookup on identifier failed.");
}

int regist(t)
char t[80];
{
	if (strcmp(t,"AB")==0) return(18);
	if (strcmp(t,"A")==0) return(1);
	if (strcmp(t,"DPTR")==0) return(4);
	if (t[0]=='R')
		if (((t[1]>='0')&&(t[1]<='7'))&&(t[2]=='\0'))
			return( ((int) t[1]) -38);
	if (strcmp(t,"C")==0) return(3);
	if (strcmp(t,"@DPTR")==0) return(5);
	if (strcmp(t,"@R0")==0) return(8);
	if (strcmp(t,"@R1")==0) return(9);
	return(0);
}

int getexp()
{
	int flag,x;
	value=0;
	flag=0;
	if (s[0]=='#')
	{
		hack(1);
		flag=1;
	}
	if (strncmp(s,"H'",2)==0)
	{
		hack(2);
		convert(16,s);
		return(7-flag);
	}
	if (strncmp(s,"B'",2)==0)
	{
		hack(2);
		convert(2,s);
		return(7-flag);
	}
	x=0;
	if (testbase(10,s[0])>=0)
	{
		while(testbase(16,s[x])>=0) x++;
		if (s[x]=='H') {convert(16,s);hack(1);return(7-flag);}
		if (s[x-1]=='B') {convert(2,s);hack(1); return(7-flag);}
		convert(10,s); return(7-flag);
	}
	if (s[0]=='\'')
	{
		hack(1);
		if (s[1]!='\'') cleanexit("Need another single quote.");
		value=(int) s[0];
		hack(2);
		if (flag==0)
		{
			warn("Character constants not advisable here.");
			return(7);
		}
		return(6);
	}
	x=0;
	while (
	(s[0]!=',')&&
	(s[0]!='\0')&&
	(s[0]!='+')&&
	(s[0]!='*')&&
	(s[0]!='-')&&
	(s[0]!=';')&&
	(s[0]!=' ')
	)
	{
		name[x++]=s[0];
		hack(1);
	}
	name[x]='\0';
	while (s[0]==' ') hack(1);
	x=regist(name);
	if (x>0) return(x);
	if (tag_defined(name)==0)
	{
		if (pass==1) {value=0;return(7-flag);}
		cleanexit("Need to define this expression.");
	}
	value=lookup();
	return(7-flag);
}
		
int getbyte()
{
	int v,x,firstx;
	char c;
	x=getexp();	
	v=value;
	firstx=x;
	while ((s[0]=='+')||(s[0]=='-')||(s[0]=='*'))
	{
		c=s[0];
		hack(1);
		x=getexp();
		if (x!=firstx) cleanexit("Expression types must match.");
		switch(c) {
			case '+':
				v+=value;
				break;
			case '-':
				v-=value;
				break;
			case '*':
				v*=value;
				break;
			default:
				break;
			}
	}
	realvalue=v;
	value=v;
	if (value<-65536) cleanexit("Value out of range.");
	if (value<-128) value+=65536;
	if (value<0) value+=256;
	if (value>65535) cleanexit("Value out of range.");
	return(x);
}

void equate()
{
	char left[80];
	int x;
	hack(5);
	x=0;
	while ((s[x]!=',')&&(s[x]!='\0')) x++;
	if (s[x]!=',') cleanexit("Equate needs a comma.");
	strnullcpy(left,s,x);
	if (regist(left)>0) cleanexit("Cannot use registers in equate.");
	hack(x+1);
	codeit("  ->");
	if (pass==2)
	{
		x=getbyte();
		return;
	}
	if (tag_defined(left)==1)
		cleanexit("Identifier already defined.");
	if (getbyte()!=7) cleanexit("Value must be a byte/word.");
	strcpy(name,left);
	add_tag(value);
	return;
}

void origin()
{
	hack(5);
	if (getbyte()!=7) cleanexit("Must be byte/word.");
	if (pass==2) codeit("  ->");
	addr=value;
	return;
}

void defbyte()
{
	hack(4);
	if (getbyte()!=7) cleanexit("Must be byte.");
	if (value>255) cleanexit("Byte value out of range.");
	if (pass==2)
	{
		hexs(value);
		codeit(hexstr);
	}
	addr+=1;
	return;
}

void defword()
{
	hack(4);
	if (getbyte()!=7) cleanexit("Must be word.");
	if (pass==2)
	{
		hexsflag=1;
		hexs(value);
		hexsflag=0;
		codeit(hexstr);
	}
	addr+=2;
	return;
}

void defmsg()
{
	char t[80];
	int x;
	hack(4);
	if (s[0]!='\'')
		cleanexit("Must start with single quote.");
	hack(1);
	t[0]='\0';
	for (x=0;x<=pos;x++)
	{
		if (s[x]=='\'')
		{
			if (pass==2) codeit(t);
			addr+=x;
			hack(x+1);
			return;
		}
		if (pass==2)
		{
			hexs(s[x]);
			strcat(t,hexstr);
		}
	}
	cleanexit("Must end with single quote.");
}

void reserve()
{
	hack(4);
	if (getbyte()!=7) cleanexit("Must be byte/word.");
	if (pass==2) codeit("  ->");
	addr+=value;
	return;
}

void endassm()
{
	hack(4);
	return;
}

void getdirec()
{
	if (strncmp(s,".EQU",4)==0) {equate();return;}
	if (strncmp(s,".ORG",4)==0) {origin();return;}
	if (strncmp(s,".DB",3)==0) {defbyte();return;}
	if (strncmp(s,".DW",3)==0) {defword();return;}
	if (strncmp(s,".DM",3)==0) {defmsg();return;}
	if (strncmp(s,".RS",3)==0) {reserve();return;}
	if (strncmp(s,".END",3)==0) {endassm();return;}
	cleanexit("Compiler directive not understood.");
}

void get2()
{
	mi=1;
	lop=getbyte();
	lval=value;
	if ((lop==6)||(lop==7)) mi++;
	if (lval>255) cleanexit("Left operator value > 255.");
	if (s[0]!=',')
		cleanexit("This statement needs two operands.");
	hack(1);
	rop=getbyte();
	rval=value;
	if ((rop==6)||(rop==7)) mi++;
	if (rval>255) cleanexit("Right operator value > 255.");
	return;
}

void get1()
{
	mi=1;
	lop=getbyte();
	lval=value;
	if ((lop==6)||(lop==7)) mi++;
	if (lval>255) cleanexit("Operator value > 255.");
	return;
}

void addr11()
{
	lop=getbyte();
	if (lop!=7) cleanexit("Operand must be an address.");
	if (pass==1) {value=0;return;}
	if ((value&63488)!=(addr&63488))
		cleanexit("11 bit address out of range.");
	value&=2047;
	return;
}

void addr16()
{
	lop=getbyte();
	if (lop!=7) cleanexit("Operand must be an address.");
	return;
}

void data16()
{
	lop=getbyte();
	if (lop!=6) cleanexit("Operand must be data.");
	return;
}

int getrel()
{
	int x,r;
	x=getbyte();
	if (x!=7) cleanexit("Operand must be an address.");
	if (pass==1) {return(0);} 
	r=realvalue-(addr+mi);
	if (r<-128) cleanexit("Relative offset < -128.");
	if (r>127) cleanexit("Relative offset > 127.");
	if (r<0) r+=256;
	return(r);
}


void ljmp()
{
	hack(5);
	addr16();
	hexs(02*65536+value);
	codeit(hexstr);
	addr+=3;
}

void form0(n)
int n;
{
	mi=2;
	hexs(n*256+getrel());
	codeit(hexstr);
	addr+=mi;
}

void sjmp()
{
	hack(5);
	form0(128);
}

jc()
{
	hack(3);
	form0(64);
}

jnc()
{
	hack(4);
	form0(80);
}

void form1(n)
int n;
{
	get1();
	mi++;
	if (lop!=7) cleanexit("Left operand must be bit address.");
	if (s[0]!=',') cleanexit("This command needs two operands.");
	hack(1);
	hexs(n*65536+lval*256+getrel());
	codeit(hexstr);
	addr+=mi;
}

void jb()
{
	hack(3);
	form1(32);
}

void jnb()
{
	hack(4);
	form1(48);
}

void jbc()
{
	hack(4);
	form1(16);
}
	
void form2(n)
int n;
{
	int x,y;
	addr11();
	x=(value/256)<<5;
	x+=n;
	y=(value%256);
	hexs(x*256+y);
	codeit(hexstr);
	addr+=2;
}

void ajmp()
{
	hack(5);
	form2(1);
	}

void acall()
{
	hack(6);
	form2(17);
}

void lcall()
{
	hack(6);
	addr16();
	hexs(18*65536+value);
	codeit(hexstr);
	addr+=3;
}

void jz()
{
	hack(3);
	form0(96);
}

void jnz()
{
	hack(4);
	form0(112);
}

void djnz()
{
	hack(5);
	get1();
	if (s[0]!=',') cleanexit("This statement needs two operands.");
	hack(1);
	mi++;
	if (lop==7)
	{
		hexs(213*65536+lval*256+getrel());
		codeit(hexstr);
		addr+=mi;
		return;
	}
	if ((lop>=10)&&(lop<=17))
	{
		hexs((216-10+lop)*256+getrel());
		codeit(hexstr);
		addr+=mi;
		return;
	}
	cleanexit("Left operand must be a direct addr or Rn.");
}

void cjne()
{
	hack(5);
	get2();
	if (s[0]!=',') cleanexit("This statement needs 3 operands.");
	hack(1);
	mi++;
	if (lop==1)
	{
		if (rop==6)
		{
			hexs(180*65536+rval*256+getrel());
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==7)
		{
			hexs(181*65536+rval*256+getrel());
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Middle operand must be # or $.");
	}
	if ((lop>=8)&&(lop<=17))
	{
		if (rop!=6) cleanexit("Middle operand must be #.");
		hexs((182-8+lop)*65536+rval*256+getrel());
		codeit(hexstr);
		addr+=mi;
		return;
	}
	cleanexit("Left operand must be A,@Ri, or Rn.");
}

void movdptr()
{
	hack(8);
	if (s[0]!=',') cleanexit("Comma needed.");
	hack(1);
	data16();
	hexs(144*65536+value);
	codeit(hexstr);
	addr+=3;
	return;
}

void form4(n)
int n;
{
	get2();
	if (lop!=1) cleanexit("Left operand must be A.");
	if ((rop>=6)&&(rop<=17))
	{
		hexs(n-6+rop);
		if ((rop==6)||(rop==7))
		{
			hexs((n-6+rop)*256+rval);
		}
		codeit(hexstr);
		addr+=mi;
		return;
	}
	cleanexit("Right operand must be #,$,@Ri, or Rn.");
}

void addc()
{
	hack(5);
	form4(52);
}

void add()
{
	hack(4);
	form4(36);
}

void subb()
{
	hack(5);
	form4(148);
}

void inc()
{
	hack(4);
	get1();
	if (lop==1) lop=6;
	if ((lop>=6)&&(lop<=17))
	{
		hexs(4-6+lop);
		if (lop==7)
			hexs((4-6+lop)*256+lval);
		codeit(hexstr);
		addr+=mi;
		return;
	}
	if (lop==4)
	{
		hexs(163);
		codeit(hexstr);
		addr+=mi;
		return;
	}
	cleanexit("Operand must be A,$,@Ri, Rn, or DPTR.");
}

void dec()
{
	hack(4);
	get1();
	if (lop==1) lop=6;
	if ((lop>=6)&&(lop<=17))
	{
		hexs(20-6+lop);
		if (lop==7)
			hexs((20-6+lop)*256+lval);
		codeit(hexstr);
		addr+=mi;
		return;
	}
	cleanexit("Operand must be A,$,@Ri, or Rn.");
}

void mul()
{
	hack(4);
	get1();
	if (lop!=18) cleanexit("Operand must be AB.");
	hexs(164);
	codeit(hexstr);
	addr++;
}

void div()
{
	hack(4);
	get1();
	if (lop!=18) cleanexit("Operand must be AB.");
	hexs(132);
	codeit(hexstr);
	addr++;
}

void da()
{
	hack(3);
	get1();
	if (lop!=1) cleanexit("Operand must be A.");
	hexs(212);
	codeit(hexstr);
	addr++;
}

void form5(n,m,o,p)
int n;
int m;
int o;
int p;
{
	get2();
	if (lop==1)
	{
		if ((rop>=6)&&(rop<=17))
		{
			hexs(n-8+rop);
			if ((rop==6)||(rop==7))
				hexs((m-6+rop)*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Right OP must be #,$,@Ri, or Rn.");
	}
	if (lop==7)
	{
		if (rop==1)
		{
			hexs(o*256+lval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==6)
		{
			hexs((o+1)*65536+lval*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Right operand must be A or #.");
	}
	if (lop==3)
	{
		if (rop==7)
		{
			hexs(p*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Right operand must be bit address.");
	}
	cleanexit("Left operand must be A, C, or $.");
}

void orl()
{
	hack(4);
	form5(70,68,66,114);
}

void anl()
{
	hack(4);
	form5(86,84,82,130);
}

void xrl()
{
	hack(4);
	get2();
	if (lop==1)
	{
		if ((rop>=6)&&(rop<=17))
		{
			hexs(100-6+rop);
			if ((rop==6)||(rop==7))
				hexs((100-6+rop)*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Right OP must be #,$,@Ri, or Rn.");
	}
	if (lop==7)
	{
		if (rop==1)
		{
			hexs(98*256+lval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==6)
		{
			hexs(99*65536+lval*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Right operand must be A or #.");
	}
	cleanexit("Left operand must be A or $.");
}

void form6(n,m,o)
int m,n,o;
{
	get1();
	if (lop==1)
	{
		hexs(n);
		codeit(hexstr);
		addr++;
		return;
	}
	if (lop==3)
	{
		hexs(m);
		codeit(hexstr);
		addr++;
		return;
	}
	if (lop==7)
	{
		hexs(o*256+lval);
		codeit(hexstr);
		addr+=2;
		return;
	}
	cleanexit("Operand must be A, C, or $.");
}

void clr()
{
	hack(4);
	form6(228,195,194);
}

void cpl()
{
	hack(4);
	form6(244,179,178);
}

void setb()
{
	hack(5);
	get1();
	if (lop==3)
	{
		hexs(211);
		codeit(hexstr);
		addr++;
		return;
	}
	if (lop==7)
	{
		hexs(210*256+lval);
		codeit(hexstr);
		addr+=2;
		return;
	}
	cleanexit("Operand must be C or $.");
}

void form7(n)
int n;
{
	get1();
	if (lop!=1) cleanexit("Operand must be A.");
	hexs(n);
	codeit(hexstr);
	addr++;
}

void rl()
{
	hack(3);
	form7(35);
}

void rlc()
{
	hack(4);
	form7(51);
}

void rr()
{
	hack(3);
	form7(3);
}

void rrc()
{
	hack(4);
	form7(19);
}

void swap()
{
	hack(5);
	form7(196);
}

void mov()
{
	hack(4);
	get2();
	if (lop==1)
	{
		if ((rop>=7)&&(rop<=17))
		{
			hexs(229-7+rop);
			if (rop==7)
				hexs(229*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==6)
		{
			hexs(116*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Right operand must be #,$,@Ri, or Rn.");
	}
	if ((lop>=8)&&(lop<=17))
	{
		if (rop==1)
		{
			hexs(245-8+lop);
			if (lop==7)
				hexs((245-8+lop)*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==7)
		{
			hexs((166-8+lop)*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==6)
		{
			hexs((118-8+lop)*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Right operand must be A,#, or $.");
	}
	if (lop==7)
	{
		if ((rop>=7)&&(rop<=17))
		{
			hexs((133-7+rop)*256+lval);
			if (rop==7)
				hexs(133*65536+lval*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==6)
		{
			hexs(117*65536+lval*256+rval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==3)
		{
			hexs(146*256+lval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		if (rop==1)
		{
			hexs(245*256+lval);
			codeit(hexstr);
			addr+=mi;
			return;
		}
		cleanexit("Right operand must be #,$, @Ri, or Rn.");
	}
	if (lop==3)
	{
		if (rop!=7) cleanexit("Right operand must be bit addr.");
		hexs(162*256+rval);
		codeit(hexstr);
		addr+=mi;
		return;
	}
	cleanexit("Left operand must be A,$, or C.");
}

void movx()
{
	hack(5);
	get2();
	if (lop==1)
	{
		if (rop==5)
		{
			hexs(224);
			codeit(hexstr);
			addr++;
			return;
		}
		if (rop==8)
		{
			hexs(226);
			codeit(hexstr);
			addr++;
			return;
		}
		if (rop==9)
		{
			hexs(227);
			codeit(hexstr);
			addr++;
			return;
		}
		cleanexit("Right operand must be @Ri, or @DPTR.");
	}
	if (lop==5)
	{
		if (rop!=1) cleanexit("Right OP must be A.");
		hexs(240);
		codeit(hexstr);
		addr++;
		return;
	}
	if (lop==8)
	{
		if (rop!=1) cleanexit("Right OP must be A.");
		hexs(242);
		codeit(hexstr);
		addr++;
		return;
	}
	if (lop==9)
	{
		if (rop!=1) cleanexit("Right OP must be A.");
		hexs(243);
		codeit(hexstr);
		addr++;
		return;
	}
	cleanexit("Left operand must be A,@Ri, or @DPTR.");
}

void pop()
{
	hack(4);
	get1();
	if (lop!=7) cleanexit("Operand must be direct byte.");
	hexs(208*256+lval);
	codeit(hexstr);
	addr+=mi;
}

void push()
{
	hack(5);
	get1();
	if (lop!=7) cleanexit("Operand must be direct byte.");
	hexs(192*256+lval);
	codeit(hexstr);
	addr+=mi;
}

void form8(n)
int n;
{
	hexs(n);
	codeit(hexstr);
	addr++;
	return;
}

void ret()
{
	hack(3);
	form8(34);
}

void reti()
{
	hack(4);
	form8(50);
}

void nop()
{
	hack(3);
	form8(0);
}

void xch()
{
	hack(4);
	get2();
	if (lop!=1) cleanexit("Left operand must be A.");
	if ((rop>=7)&&(rop<=17))
	{
		hexs(197-7+rop);
		if (rop==7) hexs((197-7+rop)*256+rval);
		codeit(hexstr);
		addr+=mi;
		return;
	}
	cleanexit("Right operand must be $,@Ri, or Rn.");
}

void xchd()
{
	hack(5);
	get2();
	if (lop!=1) cleanexit("Left operand must be A.");
	if ((rop>=8)&&(rop<=17))
	{
		hexs(214-8+rop);
		codeit(hexstr);
		addr++;
		return;
	}
	cleanexit("Right operand must be @Ri.");
}

void movcadptr()
{
	hack(14);
	hexs(147);
	codeit(hexstr);
	addr++;
}

void movcapc()
{
	hack(12);
	hexs(131);
	codeit(hexstr);
	addr++;
}

void jmpadptr()
{
	hack(11);
	hexs(115);
	codeit(hexstr);
	addr++;
}

void opcode()
{
	if (strncmp(s,"ADDC ",5)==0) {addc();return;}
	if (strncmp(s,"ADD ",4)==0) {add();return;}
	if (strncmp(s,"SUBB ",5)==0) {subb();return;}
	if (strncmp(s,"INC ",4)==0) {inc();return;}
	if (strncmp(s,"DEC ",4)==0) {dec();return;}
	if (strncmp(s,"MUL ",4)==0) {mul();return;}
	if (strncmp(s,"DIV ",4)==0) {div();return;}
	if (strncmp(s,"DA ",3)==0) {da();return;}
	if (strncmp(s,"ANL ",4)==0) {anl();return;}
	if (strncmp(s,"ORL ",4)==0) {orl();return;}
	if (strncmp(s,"XRL ",4)==0) {xrl();return;}
	if (strncmp(s,"CPL ",4)==0) {cpl();return;}
	if (strncmp(s,"RLC ",4)==0) {rlc();return;}
	if (strncmp(s,"RR ",3)==0) {rr();return;}
	if (strncmp(s,"RRC ",4)==0) {rrc();return;}
	if (strncmp(s,"RL ",3)==0) {rl();return;}
	if (strncmp(s,"SWAP ",5)==0) {swap();return;}
	if (strncmp(s,"MOVX ",5)==0) {movx();return;}
	if (strncmp(s,"MOV DPTR",8)==0) {movdptr();return;}
	if (strncmp(s,"MOVC A,@A+DPTR",14)==0) {movcadptr();return;}
	if (strncmp(s,"MOVC A,@A+PC",12)==0) {movcapc();return;}
	if (strncmp(s,"JMP @A+DPTR",11)==0) {jmpadptr();return;}
	if (strncmp(s,"MOV ",4)==0) {mov();return;}
	if (strncmp(s,"PUSH ",5)==0) {push();return;}
	if (strncmp(s,"POP ",4)==0) {pop();return;}
	if (strncmp(s,"XCHD ",5)==0) {xchd();return;}
	if (strncmp(s,"XCH ",4)==0) {xch();return;}
	if (strncmp(s,"CLR ",4)==0) {clr();return;}
	if (strncmp(s,"SETB ",5)==0) {setb();return;}
	if (strncmp(s,"JC ",3)==0) {jc();return;}
	if (strncmp(s,"JNC ",4)==0) {jnc();return;}
	if (strncmp(s,"JNB ",4)==0) {jnb();return;}
	if (strncmp(s,"JBC ",4)==0) {jbc();return;}
	if (strncmp(s,"JB ",3)==0) {jb();return;}
	if (strncmp(s,"ACALL ",6)==0) {acall();return;}
	if (strncmp(s,"LCALL ",6)==0) {lcall();return;}
	if (strncmp(s,"RETI",4)==0) {reti();return;}
	if (strncmp(s,"RET",3)==0) {ret();return;}
	if (strncmp(s,"SJMP ",5)==0) {sjmp();return;}
	if (strncmp(s,"LJMP ",5)==0) {ljmp();return;}
	if (strncmp(s,"AJMP ",5)==0) {ajmp();return;}
	if (strncmp(s,"JZ ",3)==0) {jz();return;}
	if (strncmp(s,"JNZ ",4)==0) {jnz();return;}
	if (strncmp(s,"CJNE ",5)==0) {cjne();return;}
	if (strncmp(s,"DJNZ ",5)==0) {djnz();return;}
	if (strncmp(s,"NOP",3)==0) {nop();return;}
	if ((s[0]>32)&&(s[0]<127)) 
		warn("Syntax Error.");
	return;
}

void assemble()
{
	int x,y;
	while (s[0]==' ') hack(1);
	if (s[0]==';') {codeit("  **"); return;}
	y=(-1); x=0;
	do
	{
		if (s[x]==';')		
			y=x;
		x++;
	} while ((x<=pos)&&(y<0));
	if (y>=0)
	{
		s[y]='\0';
		pos=y;
	}

	while (s[0]==':')
	{
	warn (": at beginning of line.");
	hack(1);
	}
	
	for (x=0;x<=pos;x++)
		if (s[x]==':')
		{
			if (pass==1) gettag(x);
			else hack(x+1);
			while (s[0]==' ') hack(1);
			if (s[0]=='\0') codeit(" --]");
		}
	while (s[0]==' ') hack(1);	
	if (s[0]=='.') {getdirec();return;}
	opcode();
	return;
}

int getline()
{
	int x;
	x=0;
	while ((c=fgetc(f))<32)
	{
		if (c=='\n')
			 {strcpy(buffer,"    ");line++;codeit("     ");}
		if (c==EOF) return(-1);
	}
	buffer[x++]=c;
	while ((c=fgetc(f))!='\n')
		buffer[x++]=c;
	buffer[x]='\0';
	return(x);
}

void main(argc,argv)
int argc;
char *argv[];
{
	int n,x,y,last,white;
	char filename[80];
	LINK tl;
	tag_list=(LINK) NULL;
	printf("8051 assembler by Eric Rudolph, 1991. Version 1.\n");
	strcpy(basename,argv[1]);
	strcpy(filename,basename);
	f=fopen("a51.equ","r");
	if (f==(FILE *) NULL)
		printf("Could not find asm.equ file.\n");
	else
		do
		{
			fscanf(f,"%s",name);
			fscanf(f,"%d",&value);
			if (value>0) add_tag(value);
		} while (value>0);
	for (x=0;x<32767;x++)
		mem[x]=0;
	
	f=fopen(filename,"r");
	hexsflag=0;
	if (f!=(FILE *) NULL)
	{
		printf("PASS1\n");
		addr=0;pass=1;line=0;
		do
		{
			n=getline();
			if (n>0)
			{
				line++;
				y=0;
				last=1;
				for (x=0;x<=n;x++)
				{
					white=0;
if ((buffer[x]==' ')||(buffer[x]=='\t'))
	white=1;
if ((white==1)&&(last==0))
	s[y++]=' ';
if (white==0)
{
	s[y]=buffer[x];
	if ((buffer[x]>='a')&&(buffer[x]<='z')) s[y]-=32;
	y++;
}
					last=white;
				}
				pos=strlen(s);
				if (s[pos-1]==' ') {s[pos-1]='\0';pos--;}
				assemble();
			}
		} while (n>=1);
		fclose(f);
		printf("PASS2\n");
		f=fopen(filename,"r");
		strcat(filename,".lst");
		f_lst=fopen(filename,"w");
		if (f_lst==(FILE *) NULL) cleanexit("Can't open .lst for write.");
		addr=0;pass=2;line=0;
		do
		{
			n=getline();
			if (n>0)
				{
				line++;
				y=0;
				last=1;
				for (x=0;x<=n;x++)
				{
					white=0;
if ((buffer[x]==' ')||(buffer[x]=='\t'))
	white=1;
if ((white==1)&&(last==0))
	s[y++]=' ';
if (white==0)
{
	s[y]=buffer[x];
	if ((buffer[x]>='a')&&(buffer[x]<='z')) s[y]-=32;
	y++;
}
					last=white;
				}
				pos=strlen(s);
				if (s[pos-1]==' ') {s[pos-1]='\0';pos--;}
				assemble();
			}
		} while (n>=1);
		fprintf(f_lst,"=============================\n");
		tl=tag_list;
		x=0;
		hexsflag=0;
		while (tl!=(LINK) NULL)
		{
			if (x==0) fprintf(f_lst,"\n");
			else fprintf(f_lst,"\t");
			hexs(tl->value);
			fprintf(f_lst,"%s\t%s",tl->tag,hexstr);
			tl=tl->next;
		}
		fprintf(f_lst,"\n\n");
		fclose(f_lst);
		showcode();
		printf("END OF ASSEMBLY.\n");
	}
	else 
		printf("No such file.\n");
	
}

@\Rogue\Monster\
else
  echo "shar: Will not over write a51.c"
fi
if `test ! -s a51.doc`
then
echo "x - a51.doc"
cat > a51.doc << '@\Rogue\Monster\'
This is an 8031/8051 assembler.

This assembler is a simple one, I think. It includes little error checking
but it does work on programs that are correctly written. It will bomb out
of assembling on any error. Usually when compling programs anyhow, the
rest of the errors are useless anyhow. It is not "case sensative".

This assembler has several directives:

	.org exp	;start address at exp.
	.equ exp,exp	;equate left expression to right one.
	.db exp		;define byte of expression
	.dw exp		;define word.
	.rs exp		;reserve exp bytes of space
	.dm exp		;define message. Put in single quotes.
	.end exp	;end assembly. Start address=exp

"exp" is either a string constant or a number, or a math function of both.
Either way, the resulting expression must be a constant. I.e. No registers.
Is that clear? (I am not good at documentation!) 

string names, called "tags" can be up to 80 characters in length, but each
line can ONLY be 80 characters long, so it's probably best to make them a
little shorter than 80.

This compiler supports addition, subtraction, and multiplication of 
constants. Plus, any character within single quotes will be treated as the
ASCII decimal equivalent. I.e. 'A'=65.

numerical constants can be specified in one of three ways, not including the
character constant. Decimal, Hexidecimal, and Binary are all supported.
Both H'xxx and 0xxxH and B'xxx and 0xxxB are supported. My favorite is 0xxxH.
If the trailing H is used in hexidecimal format, like most compilers, if the
first number is a alphabet character (A-F) it must be preceded with a 0.

The full 8051 instruction set it translated in this assembler EXCEPT for
1. ANL c,/bit and 2. ORL c,/bit. Oh well!

To use this assembler, first compile it with "cc a51.c -o a51"
The compiler must be able to handle arrays of 32k long. With this capability,
you can have programs with an ADDRESS SPACE OF 0-8000 HEX! Addresses
farther than this will cause the program to BOMB. If your compiler can
handle it, change the array bounds in a51.h to 64k and all limiting
references to 32k in the program to 64k. I can't imagine a 32k program on
the 8051 myself...

To use the program, type "a51 filename" The assembler will generate two
files, a filename.lst file and a filename.hex file. 
	The .lst file will contain a listing of your program with the code
beside it followed by a table of tags that were defined.
	The .hex file will contain all the object code that is in your program
but no checksums, since I don't know how to do that. (any ideas?)

To make life easy, the assembler comes with an additional file, "a51.equ"
that has predefined tags with thier values. This file must end with a negative
number as a delimiter. Feel free to add your own equates if you want. It will
work the same.

Negative numbers are treated as two's complement. Always. If the number is
negative and greater than -256, it is treated as a byte.
If the number is negative and less than -255 (like -256) it is treated as
a word. Remember this! It's probably best not even to use negative 
constants. Figure them out yourself and compliment them. Just to make sure,
check the code listing and see if it's right.

rem statements are preceded by semicolons. 

Example programs foo and foo2 are included to show a couple of the features.

Questions? Complaints? Bugs?

rudolpe@jacobs.cs.orst.edu (503-745-7466)

@\Rogue\Monster\
else
  echo "shar: Will not over write a51.doc"
fi
if `test ! -s a51.equ`
then
echo "x - a51.equ"
cat > a51.equ << '@\Rogue\Monster\'
ACC
224
ACC.0
224
ACC.1
225
ACC.2
226
ACC.3
227
ACC.4
228
ACC.5
229
ACC.6
230
ACC.7
231
B
240
B.0
240
B.1
241
B.2
242
B.3
243
B.4
244
B.5
245
B.6
246
B.7
247
PSW
208
PSW.0
208
PSW.1
209
PSW.2
210
PSW.3
211
PSW.4
212
PSW.5
213
PSW.6
214
PSW.7
215
P0
128
P0.0
128
P0.1
129
P0.2
130
P0.3
131
P0.4
132
P0.5
133
P0.6
134
P0.7
135
TCON
136
TCON.0
136
TCON.1
137
TCON.2
138
TCON.3
139
TCON.4
140
TCON.5
141
TCON.6
142
TCON.7
143
P1
144
P1.0
144
P1.1
145
P1.2
146
P1.3
147
P1.4
148
P1.5
149
P1.6
150
P1.7
151
SCON
152
SCON.0
152
SCON.1
153
SCON.2
154
SCON.3
155
SCON.4
156
SCON.5
157
SCON.6
158
SCON.7
159
P2
160
P2.0
160
P2.1
161
P2.2
162
P2.3
163
P2.4
164
P2.5
165
P2.6
166
P2.7
167
IE
168
IE.0
168
IE.1
169
IE.2
170
IE.3
171
IE.4
172
IE.5
173
IE.6
174
IE.7
175
P3
176
P3.0
176
P3.1
177
P3.2
178
P3.3
179
P3.4
180
P3.5
181
P3.6
182
P3.7
183
SBUF
153
TMOD
137
TL0
138
TL1
139
TH0
140
TH1
141
SP
129
DPL
130
DPH
131
PCON
135
P
208
OV
210
RS0
211
RS1
212
F0
213
AC
214
CY
215
EA
175
ES
172
ET1
171
EX1
170
ET0
169
EX0
168
PS
188
PT1
187
PX1
186
PT0
185
PX0
184
TF1
143
TR1
142
TF0
141
TR0
140
IE1
139
IT1
138
IE0
137
IT0
136
SM0
159
SM1
158
SM2
157
REN
156
TB8
155
RB8
154
TI
153
RI
152
INT0
178
INT1
179
IP
184
IP.0
184
IP.1
185
IP.2
186
IP.3
187
IP.4
188
IP.5
189
RXD
176
TXD
177
END
-1

@\Rogue\Monster\
else
  echo "shar: Will not over write a51.equ"
fi
if `test ! -s a51.h`
then
echo "x - a51.h"
cat > a51.h << '@\Rogue\Monster\'
#include <stdio.h>
#include <string.h>

short		mem[32768];
char		s[80];
char		buffer[80];
char		hexstr[7];
char		name[80];
char		left[80];
char		basename[80];
char		c;
int		addr,line,lval,mi,pass,pos,rval,realvalue,value;
int		lop,rel,rop,ln,hexsflag;
FILE 		*f,*f_lst,*f_hex;
struct		taglist {
	char	tag[80];
	int	value;
	struct	taglist *next;
	};
struct taglist	*tag_list;
typedef	struct taglist ELEM;
typedef	ELEM *LINK;

@\Rogue\Monster\
else
  echo "shar: Will not over write a51.h"
fi
if `test ! -s foo`
then
echo "x - foo"
cat > foo << '@\Rogue\Monster\'
nop
ajmp 100h
ljmp 100h
rr a
inc a
inc 40h
inc r0
inc r1
inc r2
inc r3
inc r4
inc r5
inc r6
inc r7
jbc 20h,77h
acall 0
lcall 4220h
rrc a
dec a
dec 40h
dec @r0
dec @r1
dec r0
dec r1
dec r2
dec r3
dec r4
dec r5
dec r6
dec r7
jb 10h,77h
ret
rl a
add a,#1
add a,20h
add a,@r0
add a,@r1
add a,r0
add a,r1
add a,r2
add a,r3
add a,r4
add a,r5
add a,r6
add a,r7
jnb 10h,77h
reti
rlc a
addc a,#1
addc a,20h
addc a,@r0
addc a,@r1
addc a,r0
addc a,r1
addc a,r2
addc a,r3
addc a,r4
addc a,r5
addc a,r6
addc a,r7
jc 77h
orl 20h,a
orl 20h,#1
orl a,#1
orl a,20h
orl a,@r0
orl a,@r1
orl a,r0
orl a,r1
orl a,r2
orl a,r3
orl a,r4
orl a,r5
orl a,r6
orl a,r7
jnc 77h
anl 20h,a
anl 20h,#1
anl a,#1
anl a,20h
anl a,@r0
anl a,@r1
anl a,r0
anl a,r1
anl a,r2
anl a,r3
anl a,r4
anl a,r5
anl a,r6
anl a,r7
jz 77h
xrl 20h,a
xrl 20h,#1
xrl a,#1
xrl a,20h
xrl a,@r0
xrl a,@r1
xrl a,r0
xrl a,r1
xrl a,r2
xrl a,r3
xrl a,r4
xrl a,r5
xrl a,r6
xrl a,r7
jnz 77h
orl c,10h
jmp @a+dptr
mov a,#1
mov 20h,#1
mov @r0,#1
mov @r1,#1
mov r0,#1
mov r1,#1
mov r2,#1
mov r3,#1
mov r4,#1
mov r5,#1
mov r6,#1
mov r7,#1
sjmp 77h
anl c,77h
movc a,@a+pc
div ab
mov 20h,21h
mov 20h,@r0
mov 20h,@r1
mov 20h,r0
mov 20h,r1
mov 20h,r2
mov 20h,r3
mov 20h,r4
mov 20h,r5
mov 20h,r6
mov 20h,r7
mov dptr,#2123h
mov 77h,c
movc a,@a+dptr
subb a,#1
subb a,20h
subb a,@r0
subb a,@r1
subb a,r0
subb a,r1
subb a,r2
subb a,r3
subb a,r4
subb a,r5
subb a,r6
subb a,r7
mov c,77h
inc dptr
mul ab
mov @r0,20h
mov @r1,20h
mov r0,20h
mov r1,20h
mov r2,20h
mov r3,20h
mov r4,20h
mov r5,20h
mov r6,20h
mov r7,20h
cpl 77h
cpl c
cjne a,#1,loo
cjne a,20h,loo
cjne @r0,#1,loo
cjne @r1,#1,loo
cjne r0,#1,loo
cjne r1,#1,loo 
cjne r2,#1,loo 
cjne r3,#1,loo 
cjne r4,#1,loo 
cjne r5,#1,loo 
cjne r6,#1,loo 
cjne r7,#1,loo 
loo:
push 40h
clr 77h
clr c
swap a
xch a,20h
xch a,@r0
xch a,@r1
xch a,r0
xch a,r1
xch a,r2
xch a,r3
xch a,r4
xch a,r5
xch a,r6
xch a,r7
pop 40h
setb 77h
setb c
da a
djnz 40h,loo 
xchd a,@r0
xchd a,@r1
loop:
djnz r0,loop
djnz r1,loop
djnz r2,loop
djnz r3,loop
djnz r4,loop
djnz r5,loop
djnz r6,loop
djnz r7,loop
movx a,@dptr
movx a,@r0
movx a,@r1
clr a
mov a,20h
mov a,@r0
mov a,@r1
mov a,r0
mov a,r1
mov a,r2
mov a,r3
mov a,r4
mov a,r5
mov a,r6
mov a,r7
movx @dptr,a
movx @r0,a
movx @r1,a
cpl a
mov @r0,a
mov @r1,a
mov r0,a
mov r1,a
mov r2,a
mov r3,a
mov r4,a
mov r5,a
mov r6,a
mov r7,a




@\Rogue\Monster\
else
  echo "shar: Will not over write foo"
fi
if `test ! -s foo2`
then
echo "x - foo2"
cat > foo2 << '@\Rogue\Monster\'
mov a,#'A'
.dw 2000h


.db 24h+111b+'a'
.db 1111b
.dm 'hello'
.equ apple_soft,45h
.db apple_soft
.end

@\Rogue\Monster\
else
  echo "shar: Will not over write foo2"
fi
if `test ! -s key.asm`
then
echo "x - key.asm"
cat > key.asm << '@\Rogue\Monster\'
;* these port equates are explained below. Relocate them to any of
;* Port1, pins 0-7 or Port3, pins 0-7, except Port3, pins2 and 3
;* because these are the external interrupts.
;* it doesn't matter as long as you equate the right pin to the right
;* signal.

        .equ    Kclk,p1.0
        .equ    Kdat,p1.1
        .equ    Aclk,p1.3
        .equ    Adat,p1.4
        .equ    Areset,p1.5
        .equ    Kswitch,p1.7

        .org    0000h
init:   ljmp    start
        .org    0003h
        ljmp    resetint
        .org    001bh
        ljmp    timer1int

;**************************************************
;*
;*
;* Equates Descriptions:
;* 
;*      Aclk is the line to the Amiga keyboard clock in. (P1.3)
;*      Adat is the line to the Amiga keyboard data in. (P1.4)
;*      Areset is the Amiga Reset line (P1.5) (for the A500)
;*      Kclk is the line to the Keyboard clock out (P1.0)
;*      Kdat is the line to the Keyboard data out (P1.1)
;*      Kstyle is bit defining whether or not the keyboard
;*        is AT or XT. if AT, Kstyle=1
;*
;*      Oldchar is the last character typed to go to the Amiga.
;* This is used to tell if the Capslock was Pressed and 
;* Released without pressing any other keys. If this was done, 
;* then it is a "Caps Lock" otherwise, the Caps key functions
;* as the Control Key because of the keyboard remapping.
;*
;*      Capbit is the flag which tells whether the Caps Lock
;* should be down or up.
;*      Capdown is the flag which tells whether the Caps Lock 
;* KEY is presently down or up. The difference between Capdown 
;* and Capbit is that Capdown relates to the KEY. Capbit toggles 
;* once for every "press and release" of the Cap Lock Key. 
;* Press and release Cap Lock Key, and Capbit goes low.....
;* Press and release it again, and Capbit goes high....
;*      Cntldown is the flag which is set and reset when you 
;* press Cap Lock and then another key. Then, Cap Lock Key 
;* functions as the Control Key.
;* LAMIGA,RAMIGA,and CONTROL are all flags that tell if those 
;* keys are being held down. When all three are, the computer
;* will reset.
;*
;* ATparity is the 10th bit that the AT keyboard transmits. It 
;* is SET if the number of DATA bits set is EVEN. Otherwise, its
;* CLEARED.
;*
;**************************************************

        ;bit memory locations:

        .equ    Capbit,42h
        .equ    Capdown,43h
        .equ    Ctrldown,44h
        .equ    CONTROL,45h
        .equ    LAMIGA,46h
        .equ    RAMIGA,47h
        .equ    ATparity,48h
        .equ    Make,49h
        .equ    XT7bit,4ah
        .equ    Kstyle,4bh

        ;byte memory locations:

        .equ    Charbad,50h
        .equ    Oldchar,51h
        .equ    Amigachar,52h

        .org    0200h

start:  mov     tmod,#11h       ;two 16 bit timers
        mov     tcon,#05h	;edge triggered interrupt.
        mov     ie,#00h         ;clear all interrupts
        setb    ea
        setb    et1             ;enable timer 1
        setb    ex0             ;enable external 0
        setb    int0            ;make sure it's high
        setb    pt0		;timer 0 has high priority
        mov     sp,#30h         ;stack somewhere safe.

; set the ports for input
        mov     p1,#255         ;set port1 for read
        clr     tr1             ;make sure timers are in
        clr     tf1             ;reset state.
        clr     tr0
        clr     tf0

; clear out the miscellaneous flags.
        clr     Capdown         ;Caps is up...
        clr     Ctrldown        ;Control is up
        clr     Capbit          ;Caps light is off.
        setb    CONTROL         ;all reset keys are UP
        setb    LAMIGA
        setb    RAMIGA

;**** sync the controller with the Amiga. clock out
;**** ones until we receive a handshake...
sync:
        mov     tl1,#0          ;set up timer for 143ms
        mov     th1,#0
        mov     r1,#2
        setb     tr1
sync2:
        jb      Adat,sync2      ;wait for handshake
sync3:
        jnb     Adat,sync3      ;wait for end of handshake
        clr     tr1

;**** transmit power up key stream and end key stream.
        mov     a,#0FDh
        acall   actualtransmit
        mov     a,#0FEh
        acall   actualtransmit

;**** test for XT keyboard, if Kswitch is low, automatically
;**** jump to XT mode.
;**** otherwise, test to see if Kdat is low and stays there.
;**** If so, it's in XT mode.                                

        jnb     Kswitch,XTPowerup 
        jb      Kdat,ATPowerup
        mov     th0,#0
        mov     tl0,#0
        clr     tf0
        setb    tr0
XTtest: jb      tf0,XTPowerup   ;timer ran out. XT mode.
        jnb     Kdat,XTtest     ;data is low, but for how long?
        clr     tr0
        clr     tf0
        sjmp    ATPowerup
XTPowerup:
        clr     Kstyle          ;XT flag.
        clr     tf0
        clr     Kclk            ;Clock low=Reset for the XT.
XTreset:
        jnb     tf0,XTreset
        setb    Kclk
        clr     tr0
        clr     tf0
ll:     acall   XTgetkey        ;(Should be AA)
        ljmp    XTstyle

;**** sync up the AT and go with it!

ATPowerup:
        setb    Kstyle
        mov     a,#0ffh         ;RESET
        acall   SendtoAT
        mov     a,#0f6h         ;DEFAULT
        acall   SendtoAT
        mov     a,#0edh         ;NEXT DATA is FOR LIGHTS
        acall   SendtoAT
        mov     a,#2            ;NUMLOCK ON?
        acall   SendtoAT
        mov     a,#0f4h         ;CLEAR BUFFER
        acall   SendtoAT
        ljmp    ATstyle         ;go and parse AT keyboard

;***********************************************
;* ATgetkey
;* ATgetkey
;* ATgetkey
;*
;* ATgetkey looks at the keyboard and waits for a key to be
;* pressed. ATinkey is the actual routine that watched the logic
;* levels of Kdat and Kclk. IF the character's parity is not 
;* what it is supposed to be, then the routine will attempt to
;* tell the keyboard to resend.
;*
;* When exiting from this routine, Kclock is pulled low to hold 
;* off any more transmissions. You must restore it to 5 volts to
;* receive any more characters later.
;*
;*

ATgetkey:
        mov     r0,#11          ;number of bits
        setb    Kclk
ATwaitC0:         
        jb      Kclk,ATwaitC0   ;wait for a clock pulse
        dec     r0              ;decrement clock bit counter
        cjne    r0,#10,ATnstart ;test for startbit
        sjmp    ATwait  
ATnstart:
        cjne    r0,#0,ATnstop   ;check for stopbit      
ATwaitC1:
        jnb     Kclk,ATwaitC1   ;wait for clock to go high                     
        clr     Kclk            ;hold off more data
        mov     r0,#20          ;small delay
pause:  djnz    r0,pause
;**** now we check to see if the parity between
;**** Bit register P (which is set if Parity of Acc is odd)
;**** is compared to the received Parity Bit.
        jb      p,parityodd     ;test if parity of DATA is odd
parityeven:
        jnb     ATparity,ATerror
        ret                     ;Okay to return. A=valid
parityodd:
        jb      ATparity,ATerror
        ret                     ;Okay to return. A=valid
ATerror:
        mov     a,#0feh         ;RESEND character
        acall   SendtoAT
        sjmp    ATgetkey        ;now return to caller
ATnstop:
        cjne    r0,#1,ATdatab   ;check for paritybit
        mov     c,Kdat          ;error checking! (AT only)
        mov     ATparity,c
        sjmp    ATwait          ;
ATdatab: 
        mov     c,Kdat          ;get data bit
        rrc     a               ;shift it into accumulator
ATwait: jnb     Kclk,ATwait     ;wait for clock line to go low
        sjmp    ATwaitC0        ;get another bit


;**************************************************
;* AT-STYLE
;*
;*     This waits for a keycode or two from the IBM and then calls
;* the appropriate transmit subroutine. The IBM keyboard sends 
;* out special codes in front of and behind some scancodes. This
;* routine will chop them out before doing a lookup on the 
;* code to see what to send to the AMIGA. The scancodes between 
;* the IBM and the AMIGA are of course, not the same!
;*
;**************************************************

ATstyle:
        acall   ATgetkey          ;get one scancode.
        cjne    a,#0e1h,ATnE1
        acall   ATgetkey          ;(should be 14)
        acall   ATgetkey          ;(should be 77)
        acall   ATgetkey          ;(should be E1)
        acall   ATgetkey          ;(should be F0)
        acall   ATgetkey          ;(should be 14)
        acall   ATgetkey          ;(should be F0)
        acall   ATgetkey          ;(should be 77)
        sjmp    ATstyle
;PAUSE was pressed. Just ignore it.
ATnE1:
        mov     dptr,#ATtb1
        cjne    a,#0e0h,ATnE0
        mov     dptr,#ATtb2
        acall   ATgetkey
        cjne    a,#0f0h,ATnE0F0
        acall   ATgetkey
        cjne    a,#12h,ATnEF12
        ljmp    ATstyle         ;(E0F012....ignore it)
ATnEF12:
        cjne    a,#59h,ATup     ;(E0F0mk)
        ljmp    ATstyle         ;(E0F059....ignore it)
ATnE0F0:
        cjne    a,#12h,ATnE012
        ljmp    ATstyle         ;(E012....ignore it)
ATnE012:
        cjne    a,#59h,ATdown   ;(E0mk)
        ljmp    ATstyle         ;(E059....ignore it)
ATnE0:
        cjne    a,#0f0h,ATdown  ;(mk)
        acall   ATgetkey
        sjmp    ATup            ;(F0mk....normal key break)

;**************************************************
;* ATdown and the rest here call a lookup table to change
;* the AT scancodes into AMIGA scancodes. In the "down"
;* routine, the "make" bit is asserted. In the "up" routine
;* it is de-asserted.
;**************************************************
ATdown:
        movc    a,@a+dptr       ;indexed into table
        clr     acc.7           ;clear make/break bit
        acall   transmit        ;transmit it
        ljmp    ATstyle
ATup:
        movc    a,@a+dptr
        setb    acc.7           ;set make/break bit
        acall   transmit        ;transmit it
        ljmp    ATstyle

;**************************************************
;* SendtoAT is the subroutine that sends special codes
;* to the keyboard from the controller. Codes include
;* the command to reset (FF) or the command to change
;* the lights (ED). It is advisable to keep the timing
;* very close to how I have it done in this routine.
;**************************************************

SendtoAT:
        setb    Kclk
        clr     Kdat
        mov     r0,#8
Send4:  jb      Kclk,Send4      ;data bit
        mov     c,acc.0
        mov     Kdat,c
        rr      a 
Send5:  jnb     Kclk,Send5      ;data bit
        dec     r0
        cjne    r0,#0,Send4
        mov     c,p
        cpl     c
Send6:  jb      Kclk,Send6      ;parity bit
        mov     Kdat,c
Send7:  jnb     Kclk,Send7      ;parity bit
Send77: jb      Kclk,Send77     ;stop bit
        setb    Kdat
Send78: jnb     Kclk,Send78     ;stop bit
Send79: jb      Kclk,Send79
Send7a: jnb     Kclk,Send7a
        mov     r0,#8           ;small delay
Send8:  djnz    r0,Send8
        clr     Kclk            ;drive clock low
        mov     r0,#20          ;long delay
Send9:  djnz    r0,Send9
        setb    Kclk
        acall   ATgetkey        ;should check if response isbad.
        ret                     ;who cares if it is? not me!

XTgetkey:
        setb    Kdat            ;let data flow!
        mov     r0,#8
XTw1:   jb      Kclk,XTw1       ;start bit1
XTw2:   jnb     Kclk,XTw2       ;start bit1
XTw3:   jb      Kclk,XTw3       ;start bit2
XTw4:   jnb     Kclk,XTw4       ;start bit2
XTw5:   jb      Kclk,XTw5       ;data bit
        mov     c,Kdat
        rrc     a
XTw6:   jnb     Kclk,XTw6       ;data bit
        djnz    r0,XTw5
        clr     Kdat            ;hold off data
        ret

XTstyle:
        acall   XTgetkey
        cjne    a,#0e1h,XTnE1
        acall   XTgetkey        ;(should be 1d)
        acall   XTgetkey        ;(should be 45)
        acall   XTgetkey        ;(should be e1)
        acall   XTgetkey        ;(should be 9d)
        acall   XTgetkey        ;(should be c5)
        sjmp    XTstyle
XTnE1:
        cjne    a,#0e0h,XTnE0
        acall   XTgetkey
        cjne    a,#0aah,XTnAA
        sjmp    XTstyle
XTnAA:
        cjne    a,#2ah,XTn2A
        sjmp    XTstyle
XTn2A:
        cjne    a,#0b6h,XTnB6
        sjmp    XTstyle
XTnB6:
        cjne    a,#36h,XTn36
        sjmp    XTstyle
XTn36:
        mov     dptr,#XTtb2
XTlookup:
        mov     c,acc.7         ;(1=break)
        mov     XT7bit,c
        clr     acc.7
        movc    a,@a+dptr
        mov     c,XT7bit
        mov     acc.7,c
        acall   transmit
        ljmp    XTstyle
XTnE0:
        mov     dptr,#XTtb1
        sjmp    XTlookup

;**************************************************
;*
;* TRANSMIT first does some checking to take out repeating
;* keys and does the conversion on the Caps Lock Key and
;* then calls Actualtransmit.
;*
;**************************************************

dontrans:                       ;jumps back if key is already
        pop     acc             ;held down.
        ret
transmit:
        cjne    a,Oldchar,transok
        ret
transok:
        cjne    a,#62h,transok2 ;jump if not CapsLock=down
        mov     Oldchar,a
        setb    Capdown         ;set the flags for later
        ret
transok2:                       
        cjne    a,#0e2h,transok3;jump if not CapsLock=up
        mov     a,Oldchar       ;see if Caps was just down
        jnb     Kstyle,XTcap    ;if XT, skip control feature.
        cjne    a,#62h,transok4 ;if not, then it was a control
XTcap:
        clr     Capdown         ;clear flag
        cpl     Capbit          ;toggle down/up-ness of Caplock
        mov     a,#62h
        mov     c,Capbit
        cpl     c
        mov     acc.7,c
        acall   actualtransmit  ;(Caps to Amiga!)
        jnb     Kstyle,skiplights ;(don't do lights if XT)
        mov     a,#0edh         ;set lights on next byte.
        acall   SendtoAT
        mov     a,#2            ;numlock on
        mov     c,Capbit
        mov     acc.2,c
        acall   SendtoAT        ;maybe capslock light
skiplights: 
        ret           
transok4:
        clr     CtrlDown        ;This sends out a Control Up.
        clr     Capdown         ;Caps lock is done functioning as Ctl
        mov     a,#63h          ;Control Key
        setb    acc.7           ;break bit set.
        acall   actualtransmit  ;send to Amiga.
        ret
transok3:
        mov     Oldchar,a
        jnb     Kstyle,noControl
        jnb     Capdown,noControl
        jb      CtrlDown,noControl
        setb    CtrlDown        ;Caps lock is beginning to function
        mov     a,#63h          ;as the Control Key.
        acall   actualtransmit  ;send Control Down to Amiga
        mov     a,Oldchar       ;now send the actual key

noControl:                      ;its not a controlled key
        mov     c,acc.7         ;c=make/break bit
        mov     Make,c          ;will be set if key up
        clr     acc.7           ;test for key only. NO make/break
        cjne    a,#0eh,noMup    ;special key mouse up
        jnb     Make,kmupdown
kmupup:
        mov     a,#0cch         ;cursor up break
        acall   actualtransmit
        acall   Smalldelay
        mov     a,#0e7h         ;right amiga break
        acall   actualtransmit
        ret
kmupdown:
        mov     a,#67h          ;amiga make
        acall   actualtransmit
        acall   Smalldelay
        mov     a,#4ch          ;cursor up make
        acall   actualtransmit
        ret
noMup:
        cjne    a,#1ch,noMdown  ;special key mouse down
        jnb     Make,kmdowndown
kmdownup:
        mov     a,#0cdh         ;cursor down break
        acall   actualtransmit
        mov     a,#0e7h         ;amiga break
        acall   Smalldelay
        acall   actualtransmit
        ret
kmdowndown:
        mov     a,#67h          ;amiga make
        acall   actualtransmit
        acall   Smalldelay      ;cursor down make
        mov     a,#4dh
        acall   actualtransmit
        ret
noMdown:
        cjne    a,#2ch,noMleft  ;special key mouse left
        jnb     Make,kmleftdown
kmleftup:
        mov     a,#0cfh         ;cursor left break
        acall   actualtransmit
        acall   Smalldelay      ;amiga break
        mov     a,#0e7h
        acall   actualtransmit
        ret
kmleftdown:
        mov     a,#67h          ;amiga make
        acall   actualtransmit
        acall   Smalldelay
        mov     a,#4fh          ;cursor left make
        acall   actualtransmit
        ret
noMleft:                        ;special key mouse right
        cjne    a,#47h,notspecial
        jnb     Make,kmrhtdown
kmrhtup:
        mov     a,#0ceh         ;cursor right break
        acall   actualtransmit
        acall   Smalldelay
        mov     a,#0e7h         ;amiga break
        acall   actualtransmit
        ret
kmrhtdown:
        mov     a,#67h          ;amiga make
        acall   actualtransmit
        acall   Smalldelay
        mov     a,#04eh         ;cursor right make
        acall   actualtransmit
        ret
Smalldelay:
        mov     th0,#0
        mov     tl0,#0
        clr     tf0
        setb    tr0
small1: jnb     tf0,small1
        clr     tf0
        clr     tr0
        ret
notspecial:
        mov     a,Oldchar
        acall   actualtransmit  ;transmit the keycode
        mov     a,Oldchar       ;get back same keycode, in A.
        mov     c,acc.7         ;put make/break bit in Make
        mov     Make,c
        clr     acc.7           ;start testing for reset keys
        cjne    a,#63h,nrset1   ;held down
        mov     c,Make
        mov     CONTROL,c
        sjmp    trset
nrset1: cjne    a,#66h,nrset2
        mov     c,Make
        mov     LAMIGA,c
        sjmp    trset
nrset2: cjne    a,#67h,trset
        mov     c,Make
        mov     RAMIGA,c
trset:  jnb     CONTROL,maybefree       ;if bit set, this key is up
        jb      CtrlDown,maybefree      ;if bit set, this key is down
        sjmp    free
maybefree:
        jb      LAMIGA,free     ;ditto
        jb      RAMIGA,free     ;ditto
        sjmp    resetwarn       ;OOPS! They are all down!
free:   ret
dummy:
        reti
resetint:
        acall   dummy
resetwarn:
        clr     tf0             
        mov     a,78h
        mov     r1,#2           ;set up timer 0 watchdog
        mov     tl0,#0
        mov     th0,#0
        cpl     a               ;invert, don't know why.
        mov     r0,#8
wr1:
        rl      a
        mov     c,acc.7
        mov     Adat,c
        mov     b,#8
wr2:
        djnz    b,wr2             ; transmit it.
        clr     Aclk
        mov     b,#8
wr3:
        djnz    b,wr3
        setb    Aclk
        mov     b,#10
wr4:
        djnz    b,wr4
        djnz    r0,wr1
        setb    Adat
        setb    tr0             ;start watchdog
wr5:
        jnb     Adat,caught1
        jnb     tf0,wr5
        clr     tf0
        djnz    r1,wr5
        sjmp    Hardreset
caught1:
        clr     tr0
        clr     tf0
        mov     a,78h
        mov     r1,#4
        mov     tl0,#0
        mov     th0,#0
        cpl     a    
        mov     r0,#8
wr11:
        rl      a
        mov     c,acc.7
        mov     Adat,c
        mov     b,#8
wr22:
        djnz    b,wr22   
        clr     Aclk
        mov     b,#8
wr33:
        djnz    b,wr33
        setb    Aclk
        mov     b,#10
wr44:
        djnz    b,wr44
        djnz    r0,wr11
        setb    Adat
        setb    tr0             ;start watchdog
wr55:
        jnb     Adat,caught2
        jnb     tf0,wr55
        clr     tf0
        djnz    r1,wr55
        sjmp    Hardreset
caught2:
hold:   jnb     Adat,hold
Hardreset:
        clr     tr0
        clr     tf0
        clr     Areset
        clr     Aclk            ;clear both lines for A500/A1000
        mov     r1,#15          ;clock should go low for over 500ms
        mov     th0,#0          ;timer 1 will overflow repeatedly
        mov     tl0,#0
        setb    tr0
hsloop:
        jnb     tf0,hsloop      ;wait for overflow flag
        clr     tf0             ;clear it again
        djnz    r1,hsloop
        clr     tf0
        clr     tr0             ;stop the timer
        ljmp    start
 
;**************************************************
;* 
;* ActualTransmit sends the character out to the Amiga and waits
;* for an acknowledge handshake. If it does not receive one in
;* 143 ms, then it clocks out 1's on the data line until it 
;* receives the acknowledge. If the Amiga is not connected up, 
;* then it will hang here. The handshake is that the AMIGA 
;* drives the clock line low.
;*
;*      The loops with register B are for timing delays. 
;* There should be about 20usec between when the Data line is 
;* set, the Clock line is driven low, and the Clock line
;* is driven high.
;*
;**************************************************

actualtransmit:
        mov     Amigachar,a     ;set the character to transmit

        mov     r0,#05          ;do a small delay
dly:
        mov     b,#0
delay:  djnz    b,delay
        djnz    r0,dly

actual2:
        mov     a,Amigachar     ;restore it
        clr     Charbad         ;character is not bad yet
        mov     r1,#2           ;set up timer 0 watchdog
        mov     tl1,#0
        mov     th1,#0
        cpl     a               ;invert, don't know why.
        mov     r0,#8
f:      rl      a
        mov     c,acc.7
        mov     Adat,c
        mov     b,#8
g:      djnz    b,g             ; transmit it.
        clr     Aclk
        mov     b,#8
h:      djnz    b,h
        setb    Aclk
        mov     b,#10
i:      djnz    b,i
        djnz    r0,f
        setb    Adat
        setb    tr1             ;start watchdog
waitshake:
        jb      Adat,waitshake
        clr     tr1             ;stop watchdog
gotit:  jnb     Adat,gotit
        ret

timer1int:
        djnz    r1,t3           ;we wait for 143 ms.
        mov     r1,#2           
        setb    Charbad         ;flag to resend the character
        clr     Adat            ;1 on the data line
        mov     b,#8
tt1:    djnz    b,tt1           ;wait for it
        clr     Aclk            ;clock asserted
        mov     b,#8            ;sync up the controller to the
tt2:    djnz    b,tt2           ;amiga
        setb    Aclk
        mov     b,#10
tt3:    djnz    b,tt3
        setb    Adat
t3:     reti                    ;return and send again.

ATtb1: 
        .db     0               
        .db     58h             ;F9
        .db     0               
        .db     54h             ;F5
        .db     52h             ;F3
        .db     50h             ;F1
        .db     51h             ;F2
        .db     5bh             ;F12=right parenthesis
        .db     0
        .db     59h             ;F10
        .db     57h             ;F8
        .db     55h             ;F6
        .db     53h             ;F4
        .db     42h             ;TAB
        .db     00h             ;~
        .db     0

        .db     0
        .db     64h             ;Left ALT
        .db     60h             ;Left SHIFT
        .db     0
        .db     66h             ;Left Ctrl=Left AMIGA
        .db     10h             ;Q
        .db     01h             ;1
        .db     0
        .db     0
        .db     0
        .db     31h             ;Z
        .db     21h             ;S
        .db     20h             ;A
        .db     11h             ;W
        .db     02h             ;2
        .db     0

        .db     0
        .db     33h             ;C
        .db     32h             ;X
        .db     22h             ;D
        .db     12h             ;E
        .db     04h             ;4
        .db     03h             ;3
        .db     0
        .db     0
        .db     40h             ;SPACE
        .db     34h             ;V
        .db     23h             ;F
        .db     14h             ;T
        .db     13h             ;R
        .db     05h             ;5
        .db     0

        .db     0
        .db     36h             ;N
        .db     35h             ;B
        .db     25h             ;H
        .db     24h             ;G
        .db     15h             ;Y
        .db     06h             ;6
        .db     0
        .db     0
        .db     0
        .db     37h             ;M
        .db     26h             ;J
        .db     16h             ;U
        .db     07h             ;7
        .db     08h             ;8
        .db     0

        .db     0
        .db     38h             ;<
        .db     27h             ;K
        .db     17h             ;I
        .db     18h             ;O
        .db     0Ah             ;0
        .db     09h             ;9
        .db     0
        .db     0
        .db     39h             ;>
        .db     3ah             ;/
        .db     28h             ;L
        .db     29h             ; ';'
        .db     19h             ;P
        .db     0bh             ;-
        .db     0

        .db     0
        .db     0
        .db     2ah             ;'
        .db     0
        .db     1ah             ;[
        .db     0ch             ;=
        .db     0
        .db     0
        .db     62h             ;CAPS LOCK?
        .db     61h             ;Right SHIFT
        .db     44h             ;RETURN
        .db     1bh             ;]
        .db     0
        .db     0dh             ;\
        .db     0
        .db     0

        .rs     6
        .db     41h             ;Back SPACE
        .db     0
        .db     0
        .db     1dh             ;1 keypad
        .db     0
        .db     2dh             ;4 keypad
        .db     3dh             ;7 keypad
        .db     0
        .db     0
        .db     0

        .db     0fh             ;0 keypad
        .db     3ch             ;dot keypad
        .db     1eh             ;2 keypad
        .db     2eh             ;5 keypad
        .db     2fh             ;6 keypad
        .db     3eh             ;8 keypad
        .db     45h             ;ESCAPE!
        .db     63h             ;Number Lock=CTRL
        .db     5ah             ;F11=( keypad
        .db     5eh             ;+ keypad
        .db     1fh             ;3 keypad
        .db     4ah             ;- keypad
        .db     5dh             ;* keypad
        .db     3fh             ;9 keypad
        .db     67h             ;scroll Lock=Right AMIGA
        .db     0
ATtb2:
        .rs     3
        .db     56h             ;F7
        .db     66h             ;print screen=Left Amiga
        .rs     11

        .db     0
        .db     65h             ;Right ALT
        .db     0
        .db     0
        .db     67h             ;Right CTL=RIGHT AMIGA
        .rs     11

        .rs     10h
        
        .rs     10h

        .rs     10
        .db     5ch             ;/key, supposedly
        .rs     5

        .rs     10
        .db     43h             ;Numeric Enter
        .rs     5

        .rs     9
        .db     1ch             ;End=Mouse down
        .db     0
        .db     4fh             ;Cursor Left
        .db     0eh             ;Home=Mouse up
        .db     0
        .db     0
        .db     63h             ;MACRO key=control

        .db     2ch             ;Insert=Mouse Left
        .db     46h             ;Delete
        .db     4dh             ;Cursor Down
        .db     0
        .db     4eh             ;Cursor Right
        .db     4ch             ;Cursor Up
        .rs     4
        .db     5fh             ;Page Down=Help
        .db     0
        .db     66h             ;print screen=LEFT AMIGA
        .db     47h             ;Page up=mouse right
        .db     40h             ;Break=Space?
        .db     0
XTtb1:
        .db     0
        .db     45h             ;esc
        .db     01h             ;1
        .db     02h             ;2
        .db     03h             ;3
        .db     04h             ;4
        .db     05h             ;5
        .db     06h             ;6
        .db     07h             ;7
        .db     08h             ;8
        .db     09h             ;9
        .db     0ah             ;0
        .db     0bh             ;-
        .db     0ch             ;=
        .db     41h             ;Backspace
        .db     42h             ;Tab

        .db     10h             ;Q
        .db     11h             ;W
        .db     12h             ;E
        .db     13h             ;R
        .db     14h             ;T
        .db     15h             ;Y
        .db     16h             ;U
        .db     17h             ;I
        .db     18h             ;O
        .db     19h             ;P
        .db     1Ah             ;[
        .db     1Bh             ;]
        .db     44h             ;ENTER
        .db     66h             ;L.CTL=LEFT AMIGA
        .db     20h             ;A
        .db     21h             ;S

        .db     22h             ;D
        .db     23h             ;F
        .db     24h             ;G
        .db     25h             ;H
        .db     26h             ;J
        .db     27h             ;K
        .db     28h             ;L
        .db     29h             ;';'
        .db     2Ah             ;'
        .db     00h             ;~
        .db     60h             ;Left Shift
        .db     0dh             ;\
        .db     31h             ;Z
        .db     32h             ;X
        .db     33h             ;C
        .db     34h             ;V

        .db     35h             ;B
        .db     36h             ;N
        .db     37h             ;M
        .db     38h             ;<
        .db     39h             ;>
        .db     3Ah             ;/
        .db     61h             ;Right Shift
        .db     5dh             ;Numeric *
        .db     64h             ;Left Alt
        .db     40h             ;space
        .db     62h             ;CapsLock
        .db     50h             ;F1
        .db     51h             ;F2
        .db     52h             ;F3
        .db     53h             ;F4
        .db     54h             ;F5

        .db     55h             ;F6
        .db     56h             ;F7
        .db     57h             ;F8
        .db     58h             ;F9
        .db     59h             ;F10
        .db     63h             ;Number Lock=Control
        .db     67h             ;Scroll Lock=Right Amiga
        .db     3dh             ;Numeric 7
        .db     3eh             ;* 8
        .db     3fh             ;* 9
        .db     4ah             ;* -
        .db     2dh             ;* 4
        .db     2eh             ;* 5
        .db     2fh             ;* 6
        .db     5eh             ;* +
        .db     1dh             ;* 1

        .db     1eh             ;* 2
        .db     1fh             ;* 3
        .db     0fh             ;* 0
        .db     3ch             ;* .
        .db     63h             ;print screen=CONTROL
        .db     0
        .db     0
        .db     5ah             ;F11=Numeric (
        .db     5bh             ;F12=Numeric )
        .rs     7

        .rs     10h

        .rs     10h
XTtb2:
        .rs     10h

        .rs     12
        .db     43h             ;Numeric Enter
        .db     67h             ;Right Control=RIGHT AMIGA
        .rs     2

        .rs     10h
        
        .rs     5
        .db     5ch             ;Numeric /key
        .db     0
        .db     66h             ;Print Screeen=Left Amiga
        .db     65h             ;Right Alt
        .rs     7

        .rs     6
        .db     5fh             ;BREAK=HELP!
        .db     0eh             ;Home=MOUSE UP
        .db     4ch             ;cursor up
        .db     47h             ;pageup=mouse right
        .db     0
        .db     4fh             ;cursor left
        .db     0
        .db     4eh             ;cursor right
        .db     0
        .db     1ch             ;End=mouse down

        .db     4dh             ;cursor down
        .db     5fh             ;page down=HELP!
        .db     2ch             ;insert=mouse left
        .db     46h             ;delete
        .rs     12
       
        .rs     15
        .db     63h             ;Macro=control

        .rs     10h

        .end    0

@\Rogue\Monster\
else
  echo "shar: Will not over write key.asm"
fi
if `test ! -s key.asm.hex`
then
echo "x - key.asm.hex"
cat > key.asm.hex << '@\Rogue\Monster\'
0000:    02 02 00 02 04 D0 00 00  00 00 00 00 00 00 00 00 
0010:    00 00 00 00 00 00 00 00  00 00 00 02 05 B4 00 00 
0200:    75 89 11 75 88 05 75 A8  00 D2 AF D2 AB D2 A8 D2 
0210:    B2 D2 B9 75 81 30 75 90  FF C2 8E C2 8F C2 8C C2 
0220:    8D C2 43 C2 44 C2 42 D2  45 D2 46 D2 47 75 8B 00 
0230:    75 8D 00 79 02 D2 8E 20  94 FD 30 94 FD C2 8E 74 
0240:    FD B1 6F 74 FE B1 6F 30  97 19 20 91 2A 75 8C 00 
0250:    75 8A 00 C2 8D D2 8C 20  8D 09 30 91 FA C2 8C C2 
0260:    8D 80 14 C2 4B C2 8D C2  90 30 8D FD D2 90 C2 8C 
0270:    C2 8D 71 5C 02 03 7A D2  4B 74 FF 71 1F 74 F6 71 
0280:    1F 74 ED 71 1F 74 02 71  1F 74 F4 71 1F 02 02 CB 
0290:    78 0B D2 90 20 90 FD 18  B8 0A 02 80 29 B8 00 1A 
02A0:    30 90 FD C2 90 78 14 D8  FE 20 D0 04 30 48 05 22 
02B0:    20 48 01 22 74 FE 71 1F  80 D6 B8 01 06 A2 91 92 
02C0:    48 80 03 A2 91 13 30 90  FD 80 C9 51 90 B4 E1 10 
02D0:    51 90 51 90 51 90 51 90  51 90 51 90 51 90 80 EB 
02E0:    90 05 D5 B4 E0 22 90 06  55 51 90 B4 F0 0E 51 90 
02F0:    B4 12 03 02 02 CB B4 59  1E 02 02 CB B4 12 03 02 
0300:    02 CB B4 59 0A 02 02 CB  B4 F0 04 51 90 80 08 93 
0310:    C2 E7 71 BF 02 02 CB 93  D2 E7 71 BF 02 02 CB D2 
0320:    90 C2 91 78 08 20 90 FD  A2 E0 92 91 03 30 90 FD 
0330:    18 B8 00 F1 A2 D0 B3 20  90 FD 92 91 30 90 FD 20 
0340:    90 FD D2 91 30 90 FD 20  90 FD 30 90 FD 78 08 D8 
0350:    FE C2 90 78 14 D8 FE D2  90 51 90 22 D2 91 78 08 
0360:    20 90 FD 30 90 FD 20 90  FD 30 90 FD 20 90 FD A2 
0370:    91 13 30 90 FD D8 F5 C2  91 22 71 5C B4 E1 0C 71 
0380:    5C 71 5C 71 5C 71 5C 71  5C 80 EF B4 E0 29 71 5C 
0390:    B4 AA 02 80 E5 B4 2A 02  80 E0 B4 B6 02 80 DB B4 
03A0:    36 02 80 D6 90 07 55 A2  E7 92 4A C2 E7 93 A2 4A 
03B0:    92 E7 71 BF 02 03 7A 90  06 D5 80 EB D0 E0 22 B5 
03C0:    51 01 22 B4 62 05 F5 51  D2 43 22 B4 E2 30 E5 51 
03D0:    30 4B 03 B4 62 1D C2 43  B2 42 74 62 A2 42 B3 92 
03E0:    E7 B1 6F 30 4B 0C 74 ED  71 1F 74 02 A2 42 92 E2 
03F0:    71 1F 22 C2 44 C2 43 74  63 D2 E7 B1 6F 22 F5 51 
0400:    30 4B 0E 30 43 0B 20 44  08 D2 44 74 63 B1 6F E5 
0410:    51 A2 E7 92 49 C2 E7 B4  0E 19 30 49 0B 74 CC B1 
0420:    6F 91 87 74 E7 B1 6F 22  74 67 B1 6F 91 87 74 4C 
0430:    B1 6F 22 B4 1C 19 30 49  0B 74 CD B1 6F 74 E7 91 
0440:    87 B1 6F 22 74 67 B1 6F  91 87 74 4D B1 6F 22 B4 
0450:    2C 19 30 49 0B 74 CF B1  6F 91 87 74 E7 B1 6F 22 
0460:    74 67 B1 6F 91 87 74 4F  B1 6F 22 B4 47 2B 30 49 
0470:    0B 74 CE B1 6F 91 87 74  E7 B1 6F 22 74 67 B1 6F 
0480:    91 87 74 4E B1 6F 22 75  8C 00 75 8A 00 C2 8D D2 
0490:    8C 30 8D FD C2 8D C2 8C  22 E5 51 B1 6F E5 51 A2 
04A0:    E7 92 49 C2 E7 B4 63 06  A2 49 92 45 80 10 B4 66 
04B0:    06 A2 49 92 46 80 07 B4  67 04 A2 49 92 47 30 45 
04C0:    05 20 44 02 80 08 20 46  05 20 47 02 80 04 22 32 
04D0:    91 CF C2 8D E5 78 79 02  75 8A 00 75 8C 00 F4 78 
04E0:    08 23 A2 E7 92 94 75 F0  08 D5 F0 FD C2 93 75 F0 
04F0:    08 D5 F0 FD D2 93 75 F0  0A D5 F0 FD D8 E3 D2 94 
0500:    D2 8C 30 94 09 30 8D FA  C2 8D D9 F6 80 41 C2 8C 
0510:    C2 8D E5 78 79 04 75 8A  00 75 8C 00 F4 78 08 23 
0520:    A2 E7 92 94 75 F0 08 D5  F0 FD C2 93 75 F0 08 D5 
0530:    F0 FD D2 93 75 F0 0A D5  F0 FD D8 E3 D2 94 D2 8C 
0540:    30 94 09 30 8D FA C2 8D  D9 F6 80 03 30 94 FD C2 
0550:    8C C2 8D C2 95 C2 93 79  0F 75 8C 00 75 8A 00 D2 
0560:    8C 30 8D FD C2 8D D9 F9  C2 8D C2 8C 02 02 00 F5 
0570:    52 78 05 75 F0 00 D5 F0  FD D8 F8 E5 52 C2 50 79 
0580:    02 75 8B 00 75 8D 00 F4  78 08 23 A2 E7 92 94 75 
0590:    F0 08 D5 F0 FD C2 93 75  F0 08 D5 F0 FD D2 93 75 
05A0:    F0 0A D5 F0 FD D8 E3 D2  94 D2 8E 20 94 FD C2 8E 
05B0:    30 94 FD 22 D9 1E 79 02  D2 50 C2 94 75 F0 08 D5 
05C0:    F0 FD C2 93 75 F0 08 D5  F0 FD D2 93 75 F0 0A D5 
05D0:    F0 FD D2 94 32 00 58 00  54 52 50 51 5B 00 59 57 
05E0:    55 53 42 00 00 00 64 60  00 66 10 01 00 00 00 31 
05F0:    21 20 11 02 00 00 33 32  22 12 04 03 00 00 40 34 
0600:    23 14 13 05 00 00 36 35  25 24 15 06 00 00 00 37 
0610:    26 16 07 08 00 00 38 27  17 18 0A 09 00 00 39 3A 
0620:    28 29 19 0B 00 00 00 2A  00 1A 0C 00 00 62 61 44 
0630:    1B 00 0D 00 00 00 00 00  00 00 00 41 00 00 1D 00 
0640:    2D 3D 00 00 00 0F 3C 1E  2E 2F 3E 45 63 5A 5E 1F 
0650:    4A 5D 3F 67 00 00 00 00  56 66 00 00 00 00 00 00 
0660:    00 00 00 00 00 00 65 00  00 67 00 00 00 00 00 00 
0690:    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 5C 
06A0:    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 43 
06B0:    00 00 00 00 00 00 00 00  00 00 00 00 00 00 1C 00 
06C0:    4F 0E 00 00 63 2C 46 4D  00 4E 4C 00 00 00 00 5F 
06D0:    00 66 47 40 00 00 45 01  02 03 04 05 06 07 08 09 
06E0:    0A 0B 0C 41 42 10 11 12  13 14 15 16 17 18 19 1A 
06F0:    1B 44 66 20 21 22 23 24  25 26 27 28 29 2A 00 60 
0700:    0D 31 32 33 34 35 36 37  38 39 3A 61 5D 64 40 62 
0710:    50 51 52 53 54 55 56 57  58 59 63 67 3D 3E 3F 4A 
0720:    2D 2E 2F 5E 1D 1E 1F 0F  3C 63 00 00 5A 5B 00 00 
0770:    00 43 67 00 00 00 00 00  00 00 00 00 00 00 00 00 
0780:    00 00 00 00 00 00 00 00  00 00 5C 00 66 65 00 00 
0790:    00 00 00 00 00 00 00 00  00 00 00 5F 0E 4C 47 00 
07A0:    4F 00 4E 00 1C 4D 5F 2C  46 00 00 00 00 00 00 00 
07C0:    00 00 00 00 63 00 00 00  00 00 00 00 00 00 00 00 
@\Rogue\Monster\
else
  echo "shar: Will not over write key.asm.hex"
fi
if `test ! -s key.list`
then
echo "x - key.list"
cat > key.list << '@\Rogue\Monster\'
000001 0000                  ;* these equates are explained below. Relocate them to any of
000002 0000                  ;* Port1, pins 0-7 or Port3, pins 0-7, except Port3, pins2 and 3
000003 0000                  ;* because these are the external interrupts.
000004 0000                  
000005 0090                          .equ    Kclk,p1.0
000006 0091                          .equ    Kdat,p1.1
000007 0092                          .equ    Kreset,p1.2 
000008 0093                          .equ    Aclk,p1.3
000009 0094                          .equ    Adat,p1.4
000010 0095                          .equ    Areset,p1.5
000011 0097                          .equ    Kswitch,p1.7
000012 0000                  
000013 0000                          .org    0000h
000014 0000 020200           init:   ljmp    start
000015 0003                          .org    0003h
000016 0003 0204D0                   ljmp    resetint
000017 001B                          .org    001bh
000018 001B 0205B4                   ljmp    timer1int
000019 001E                  
000020 001E                  ;**************************************************
000021 001E                  ;*
000022 001E                  ;*
000023 001E                  ;* Equates Descriptions:
000024 001E                  ;* 
000025 001E                  ;*    Watch1 is a flag which tells the IBM keycode parser that
000026 001E                  ;* some extranneous codes are to come across the lines. In 
000027 001E                  ;* particular, these codes will be either E0 4A or E0 59. The 
000028 001E                  ;* parser should ignore them.
000029 001E                  ;*      Watch2 is also the same type of flag as Watch1. It
000030 001E                  ;* tells the parser that E0 12 59 will follow and to ignore it.
000031 001E                  ;*
000032 001E                  ;*      Aclk is the line to the Amiga keyboard clock in. (P1.3)
000033 001E                  ;*      Adat is the line to the Amiga keyboard data in. (P1.4)
000034 001E                  ;*      Areset is the Amiga Reset line (P1.5)
000035 001E                  ;*      Kclk is the line to the Keyboard clock out (P1.0)
000036 001E                  ;*      Kdat is the line to the Keyboard data out (P1.1)
000037 001E                  ;*      Kreset is the Keyboard Reset line (P1.2)
000038 001E                  ;*      Kstyle is bit defining whether or not the keyboard
000039 001E                  ;*        is AT or XT. if AT, Kstyle=1
000040 001E                  ;*
000041 001E                  ;*      Oldchar is the last character typed to go to the Amiga.
000042 001E                  ;* This is used to tell if the Capslock was Pressed and 
000043 001E                  ;* Released without pressing any other keys. If this was done, 
000044 001E                  ;* then it is a "Caps Lock" otherwise, the Caps key functions
000045 001E                  ;* as the Control Key because of the keyboard remapping.
000046 001E                  ;*
000047 001E                  ;*      Capbit is the flag which tells whether the Caps Lock
000048 001E                  ;* should be down or up.
000049 001E                  ;*      Capdown is the flag which tells whether the Caps Lock 
000050 001E                  ;* KEY is presently down or up. The difference between Capdown 
000051 001E                  ;* and Capbit is that Capdown relates to the KEY. Capbit toggles 
000052 001E                  ;* once for every "press and release" of the Cap Lock Key. 
000053 001E                  ;* Press and release Cap Lock Key, and Capbit goes low.....
000054 001E                  ;* Press and release it again, and Capbit goes high....
000055 001E                  ;*      Cntldown is the flag which is set and reset when you 
000056 001E                  ;* press Cap Lock and then another key. Then, Cap Lock Key 
000057 001E                  ;* functions as the Control Key.
000058 001E                  ;* LAMIGA,RAMIGA,and CONTROL are all flags that tell if those 
000059 001E                  ;* keys are being held down. When all three are, the computer
000060 001E                  ;* will reset.
000061 001E                  ;*
000062 001E                  ;* ATparity is the 10th bit that the AT keyboard transmits. It 
000063 001E                  ;* is SET if the number of DATA bits set is EVEN. Otherwise, its
000064 001E                  ;* CLEARED.
000065 001E                  ;*
000066 001E                  ;**************************************************
000067 001E                  
000068 001E                          ;bit memory locations:
000069 001E                  
000070 0042                          .equ    Capbit,42h
000071 0043                          .equ    Capdown,43h
000072 0044                          .equ    Ctrldown,44h
000073 0045                          .equ    CONTROL,45h
000074 0046                          .equ    LAMIGA,46h
000075 0047                          .equ    RAMIGA,47h
000076 0048                          .equ    ATparity,48h
000077 0049                          .equ    Make,49h
000078 004A                          .equ    XT7bit,4ah
000079 004B                          .equ    Kstyle,4bh
000080 001E                  
000081 001E                          ;byte memory locations:
000082 001E                  
000083 0050                          .equ    Charbad,50h
000084 0051                          .equ    Oldchar,51h
000085 0052                          .equ    Amigachar,52h
000086 001E                  
000087 0200                          .org    0200h
000088 0200                  
000089 0200 758911           start:  mov     tmod,#11h       ;two 16 bit timers
000090 0203 758805                   mov     tcon,#05h
000091 0206 75A800                   mov     ie,#00h         ;clear all interrupts
000092 0209 D2AF                     setb    ea
000093 020B D2AB                     setb    et1             ;enable timer 1
000094 020D D2A8                     setb    ex0             ;enable external 0
000095 020F D2B2                     setb    int0            ;make sure it's high
000096 0211 D2B9                     setb    pt0
000097 0213 758130                   mov     sp,#30h         ;stack somewhere safe.
000098 0216                  
000099 0216                  ; set the ports for input
000100 0216 7590FF                   mov     p1,#255         ;set port1 for read
000101 0219 C28E                     clr     tr1             ;make sure timers are in
000102 021B C28F                     clr     tf1             ;reset state.
000103 021D C28C                     clr     tr0
000104 021F C28D                     clr     tf0
000105 0221                  
000106 0221                  ; clear out the miscellaneous flags.
000107 0221 C243                     clr     Capdown         ;Caps is up...
000108 0223 C244                     clr     Ctrldown        ;Control is up
000109 0225 C242                     clr     Capbit          ;Caps light is off.
000110 0227 D245                     setb    CONTROL         ;all reset keys are UP
000111 0229 D246                     setb    LAMIGA
000112 022B D247                     setb    RAMIGA
000113 022D                  
000114 022D                  ;**** sync the controller with the Amiga. clock out
000115 022D                  ;**** ones until we receive a handshake...
000116 022D                  sync:
000117 022D 758B00                   mov     tl1,#0          ;set up timer for 143ms
000118 0230 758D00                   mov     th1,#0
000119 0233 7902                     mov     r1,#2
000120 0235 D28E                     setb     tr1
000121 0237                  sync2:
000122 0237 2094FD                   jb      Adat,sync2      ;wait for handshake
000123 023A                  sync3:
000124 023A 3094FD                   jnb     Adat,sync3      ;wait for end of handshake
000125 023D C28E                     clr     tr1
000126 023F                  
000127 023F                  ;**** transmit power up key stream and end key stream.
000128 023F 74FD                     mov     a,#0FDh
000129 0241 B16F                     acall   actualtransmit
000130 0243 74FE                     mov     a,#0FEh
000131 0245 B16F                     acall   actualtransmit
000132 0247                  
000133 0247                  ;**** test for XT keyboard, if Kswitch is low, automatically
000134 0247                  ;**** jump to XT mode.
000135 0247                  ;**** otherwise, test to see if Kdat is low and stays there.
000136 0247                  ;**** If so, it's in XT mode.                                
000137 0247 309719                   jnb     Kswitch,XTPowerup 
000138 024A 20912A                   jb      Kdat,ATPowerup
000139 024D 758C00                   mov     th0,#0
000140 0250 758A00                   mov     tl0,#0
000141 0253 C28D                     clr     tf0
000142 0255 D28C                     setb    tr0
000143 0257 208D09           XTtest: jb      tf0,XTPowerup   ;timer ran out. XT mode.
000144 025A 3091FA                   jnb     Kdat,XTtest     ;data is low, but for how long?
000145 025D C28C                     clr     tr0
000146 025F C28D                     clr     tf0
000147 0261 8014                     sjmp    ATPowerup
000148 0263                  XTPowerup:
000149 0263 C24B                     clr     Kstyle          ;XT flag.
000150 0265 C28D                     clr     tf0
000151 0267 C290                     clr     Kclk            ;Clock low=Reset for the XT.
000152 0269                  XTreset:
000153 0269 308DFD                   jnb     tf0,XTreset
000154 026C D290                     setb    Kclk
000155 026E C28C                     clr     tr0
000156 0270 C28D                     clr     tf0
000157 0272 715C             ll:     acall   XTgetkey        ;(Should be AA)
000158 0274 02037A                   ljmp    XTstyle
000159 0277                  
000160 0277                  ;**** sync up the AT and go with it!
000161 0277                  
000162 0277                  ATPowerup:
000163 0277 D24B                     setb    Kstyle
000164 0279 74FF                     mov     a,#0ffh         ;RESET
000165 027B 711F                     acall   SendtoAT
000166 027D 74F6                     mov     a,#0f6h         ;DEFAULT
000167 027F 711F                     acall   SendtoAT
000168 0281 74ED                     mov     a,#0edh         ;NEXT DATA is FOR LIGHTS
000169 0283 711F                     acall   SendtoAT
000170 0285 7402                     mov     a,#2            ;NUMLOCK ON?
000171 0287 711F                     acall   SendtoAT
000172 0289 74F4                     mov     a,#0f4h         ;CLEAR BUFFER
000173 028B 711F                     acall   SendtoAT
000174 028D 0202CB                   ljmp    ATstyle         ;go and parse AT keyboard
000175 0290                  
000176 0290                  ;***********************************************
000177 0290                  ;* ATgetkey
000178 0290                  ;* ATgetkey
000179 0290                  ;* ATgetkey
000180 0290                  ;*
000181 0290                  ;* ATgetkey looks at the keyboard and waits for a key to be
000182 0290                  ;* pressed. ATinkey is the actual routine that watched the logic
000183 0290                  ;* levels of Kdat and Kclk. IF the character's parity is not 
000184 0290                  ;* what it is supposed to be, then the routine will attempt to
000185 0290                  ;* tell the keyboard to resend.
000186 0290                  ;*
000187 0290                  ;* When exiting from this routine, Kclock is pulled low to hold 
000188 0290                  ;* off any more transmissions. You must restore it to 5 volts to
000189 0290                  ;* receive any more characters later.
000190 0290                  ;*
000191 0290                  ;*
000192 0290                  
000193 0290                  ATgetkey:
000194 0290 780B                     mov     r0,#11          ;number of bits
000195 0292 D290                     setb    Kclk
000196 0294                  ATwaitC0:         
000197 0294 2090FD                   jb      Kclk,ATwaitC0   ;wait for a clock pulse
000198 0297 18                       dec     r0              ;decrement clock bit counter
000199 0298 B80A02                   cjne    r0,#10,ATnstart ;test for startbit
000200 029B 8029                     sjmp    ATwait  
000201 029D                  ATnstart:
000202 029D B8001A                   cjne    r0,#0,ATnstop   ;check for stopbit      
000203 02A0                  ATwaitC1:
000204 02A0 3090FD                   jnb     Kclk,ATwaitC1   ;wait for clock to go high                     
000205 02A3 C290                     clr     Kclk            ;hold off more data
000206 02A5 7814                     mov     r0,#20          ;small delay
000207 02A7 D8FE             pause:  djnz    r0,pause
000208 02A9                  ;**** now we check to see if the parity between
000209 02A9                  ;**** Bit register P (which is set if Parity of Acc is odd)
000210 02A9                  ;**** is compared to the received Parity Bit.
000211 02A9 20D004                   jb      p,parityodd     ;test if parity of DATA is odd
000212 02AC                  parityeven:
000213 02AC 304805                   jnb     ATparity,ATerror
000214 02AF 22                       ret                     ;Okay to return. A=valid
000215 02B0                  parityodd:
000216 02B0 204801                   jb      ATparity,ATerror
000217 02B3 22                       ret                     ;Okay to return. A=valid
000218 02B4                  ATerror:
000219 02B4 74FE                     mov     a,#0feh         ;RESEND character
000220 02B6 711F                     acall   SendtoAT
000221 02B8 80D6                     sjmp    ATgetkey        ;now return to caller
000222 02BA                  ATnstop:
000223 02BA B80106                   cjne    r0,#1,ATdatab   ;check for paritybit
000224 02BD A291                     mov     c,Kdat          ;error checking! (AT only)
000225 02BF 9248                     mov     ATparity,c
000226 02C1 8003                     sjmp    ATwait          ;
000227 02C3                  ATdatab: 
000228 02C3 A291                     mov     c,Kdat          ;get data bit
000229 02C5 13                       rrc     a               ;shift it into accumulator
000230 02C6 3090FD           ATwait: jnb     Kclk,ATwait     ;wait for clock line to go low
000231 02C9 80C9                     sjmp    ATwaitC0        ;get another bit
000232 02CB                  
000233 02CB                  
000234 02CB                  ;**************************************************
000235 02CB                  ;* AT-STYLE
000236 02CB                  ;*
000237 02CB                  ;*     This waits for a keycode or two from the IBM and then calls
000238 02CB                  ;* the appropriate transmit subroutine. The IBM keyboard sends 
000239 02CB                  ;* out special codes in front of and behind some scancodes. This
000240 02CB                  ;* routine will chop them out before doing a lookup on the 
000241 02CB                  ;* code to see what to send to the AMIGA. The scancodes between 
000242 02CB                  ;* the IBM and the AMIGA are of course, not the same!
000243 02CB                  ;*
000244 02CB                  ;**************************************************
000245 02CB                  
000246 02CB                  ATstyle:
000247 02CB 5190                     acall   ATgetkey          ;get one scancode.
000248 02CD B4E110                   cjne    a,#0e1h,ATnE1
000249 02D0 5190                     acall   ATgetkey          ;(should be 14)
000250 02D2 5190                     acall   ATgetkey          ;(should be 77)
000251 02D4 5190                     acall   ATgetkey          ;(should be E1)
000252 02D6 5190                     acall   ATgetkey          ;(should be F0)
000253 02D8 5190                     acall   ATgetkey          ;(should be 14)
000254 02DA 5190                     acall   ATgetkey          ;(should be F0)
000255 02DC 5190                     acall   ATgetkey          ;(should be 77)
000256 02DE 80EB                     sjmp    ATstyle
000257 02E0                  ;PAUSE was pressed. Just ignore it.
000258 02E0                  ATnE1:
000259 02E0 9005D5                   mov     dptr,#ATtb1
000260 02E3 B4E022                   cjne    a,#0e0h,ATnE0
000261 02E6 900655                   mov     dptr,#ATtb2
000262 02E9 5190                     acall   ATgetkey
000263 02EB B4F00E                   cjne    a,#0f0h,ATnE0F0
000264 02EE 5190                     acall   ATgetkey
000265 02F0 B41203                   cjne    a,#12h,ATnEF12
000266 02F3 0202CB                   ljmp    ATstyle         ;(E0F012....ignore it)
000267 02F6                  ATnEF12:
000268 02F6 B4591E                   cjne    a,#59h,ATup     ;(E0F0mk)
000269 02F9 0202CB                   ljmp    ATstyle         ;(E0F059....ignore it)
000270 02FC                  ATnE0F0:
000271 02FC B41203                   cjne    a,#12h,ATnE012
000272 02FF 0202CB                   ljmp    ATstyle         ;(E012....ignore it)
000273 0302                  ATnE012:
000274 0302 B4590A                   cjne    a,#59h,ATdown   ;(E0mk)
000275 0305 0202CB                   ljmp    ATstyle         ;(E059....ignore it)
000276 0308                  ATnE0:
000277 0308 B4F004                   cjne    a,#0f0h,ATdown  ;(mk)
000278 030B 5190                     acall   ATgetkey
000279 030D 8008                     sjmp    ATup            ;(F0mk....normal key break)
000280 030F                  
000281 030F                  ;**************************************************
000282 030F                  ;* ATdown and the rest here call a lookup table to change
000283 030F                  ;* the AT scancodes into AMIGA scancodes. In the "down"
000284 030F                  ;* routine, the "make" bit is asserted. In the "up" routine
000285 030F                  ;* it is de-asserted.
000286 030F                  ;**************************************************
000287 030F                  ATdown:
000288 030F 93                       movc    a,@a+dptr       ;indexed into table
000289 0310 C2E7                     clr     acc.7           ;clear make/break bit
000290 0312 71BF                     acall   transmit        ;transmit it
000291 0314 0202CB                   ljmp    ATstyle
000292 0317                  ATup:
000293 0317 93                       movc    a,@a+dptr
000294 0318 D2E7                     setb    acc.7           ;set make/break bit
000295 031A 71BF                     acall   transmit        ;transmit it
000296 031C 0202CB                   ljmp    ATstyle
000297 031F                  
000298 031F                  ;**************************************************
000299 031F                  ;* SendtoAT is the subroutine that sends special codes
000300 031F                  ;* to the keyboard from the controller. Codes include
000301 031F                  ;* the command to reset (FF) or the command to change
000302 031F                  ;* the lights (ED). It is advisable to keep the timing
000303 031F                  ;* very close to how I have it done in this routine.
000304 031F                  ;**************************************************
000305 031F                  
000306 031F                  SendtoAT:
000307 031F D290                     setb    Kclk
000308 0321 C291                     clr     Kdat
000309 0323 7808                     mov     r0,#8
000310 0325 2090FD           Send4:  jb      Kclk,Send4      ;data bit
000311 0328 A2E0                     mov     c,acc.0
000312 032A 9291                     mov     Kdat,c
000313 032C 03                       rr      a 
000314 032D 3090FD           Send5:  jnb     Kclk,Send5      ;data bit
000315 0330 18                       dec     r0
000316 0331 B800F1                   cjne    r0,#0,Send4
000317 0334 A2D0                     mov     c,p
000318 0336 B3                       cpl     c
000319 0337 2090FD           Send6:  jb      Kclk,Send6      ;parity bit
000320 033A 9291                     mov     Kdat,c
000321 033C 3090FD           Send7:  jnb     Kclk,Send7      ;parity bit
000322 033F 2090FD           Send77: jb      Kclk,Send77     ;stop bit
000323 0342 D291                     setb    Kdat
000324 0344 3090FD           Send78: jnb     Kclk,Send78     ;stop bit
000325 0347 2090FD           Send79: jb      Kclk,Send79
000326 034A 3090FD           Send7a: jnb     Kclk,Send7a
000327 034D 7808                     mov     r0,#8           ;small delay
000328 034F D8FE             Send8:  djnz    r0,Send8
000329 0351 C290                     clr     Kclk            ;drive clock low
000330 0353 7814                     mov     r0,#20          ;long delay
000331 0355 D8FE             Send9:  djnz    r0,Send9
000332 0357 D290                     setb    Kclk
000333 0359 5190                     acall   ATgetkey        ;should check if response isbad.
000334 035B 22                       ret                     ;who cares if it is? not me!
000335 035C                  
000336 035C                  XTgetkey:
000337 035C D291                     setb    Kdat            ;let data flow!
000338 035E 7808                     mov     r0,#8
000339 0360 2090FD           XTw1:   jb      Kclk,XTw1       ;start bit1
000340 0363 3090FD           XTw2:   jnb     Kclk,XTw2       ;start bit1
000341 0366 2090FD           XTw3:   jb      Kclk,XTw3       ;start bit2
000342 0369 3090FD           XTw4:   jnb     Kclk,XTw4       ;start bit2
000343 036C 2090FD           XTw5:   jb      Kclk,XTw5       ;data bit
000344 036F A291                     mov     c,Kdat
000345 0371 13                       rrc     a
000346 0372 3090FD           XTw6:   jnb     Kclk,XTw6       ;data bit
000347 0375 D8F5                     djnz    r0,XTw5
000348 0377 C291                     clr     Kdat            ;hold off data
000349 0379 22                       ret
000350 037A                  
000351 037A                  XTstyle:
000352 037A 715C                     acall   XTgetkey
000353 037C B4E10C                   cjne    a,#0e1h,XTnE1
000354 037F 715C                     acall   XTgetkey        ;(should be 1d)
000355 0381 715C                     acall   XTgetkey        ;(should be 45)
000356 0383 715C                     acall   XTgetkey        ;(should be e1)
000357 0385 715C                     acall   XTgetkey        ;(should be 9d)
000358 0387 715C                     acall   XTgetkey        ;(should be c5)
000359 0389 80EF                     sjmp    XTstyle
000360 038B                  XTnE1:
000361 038B B4E029                   cjne    a,#0e0h,XTnE0
000362 038E 715C                     acall   XTgetkey
000363 0390 B4AA02                   cjne    a,#0aah,XTnAA
000364 0393 80E5                     sjmp    XTstyle
000365 0395                  XTnAA:
000366 0395 B42A02                   cjne    a,#2ah,XTn2A
000367 0398 80E0                     sjmp    XTstyle
000368 039A                  XTn2A:
000369 039A B4B602                   cjne    a,#0b6h,XTnB6
000370 039D 80DB                     sjmp    XTstyle
000371 039F                  XTnB6:
000372 039F B43602                   cjne    a,#36h,XTn36
000373 03A2 80D6                     sjmp    XTstyle
000374 03A4                  XTn36:
000375 03A4 900755                   mov     dptr,#XTtb2
000376 03A7                  XTlookup:
000377 03A7 A2E7                     mov     c,acc.7         ;(1=break)
000378 03A9 924A                     mov     XT7bit,c
000379 03AB C2E7                     clr     acc.7
000380 03AD 93                       movc    a,@a+dptr
000381 03AE A24A                     mov     c,XT7bit
000382 03B0 92E7                     mov     acc.7,c
000383 03B2 71BF                     acall   transmit
000384 03B4 02037A                   ljmp    XTstyle
000385 03B7                  XTnE0:
000386 03B7 9006D5                   mov     dptr,#XTtb1
000387 03BA 80EB                     sjmp    XTlookup
000388 03BC                  
000389 03BC                  ;**************************************************
000390 03BC                  ;*
000391 03BC                  ;* TRANSMIT first does some checking to take out repeating
000392 03BC                  ;* keys and does the conversion on the Caps Lock Key and
000393 03BC                  ;* then calls Actualtransmit.
000394 03BC                  ;*
000395 03BC                  ;**************************************************
000396 03BC                  
000397 03BC                  dontrans:                       ;jumps back if key is already
000398 03BC D0E0                     pop     acc             ;held down.
000399 03BE 22                       ret
000400 03BF                  transmit:
000401 03BF B55101                   cjne    a,Oldchar,transok
000402 03C2 22                       ret
000403 03C3                  transok:
000404 03C3 B46205                   cjne    a,#62h,transok2 ;jump if not CapsLock=down
000405 03C6 F551                     mov     Oldchar,a
000406 03C8 D243                     setb    Capdown         ;set the flags for later
000407 03CA 22                       ret
000408 03CB                  transok2:                       
000409 03CB B4E230                   cjne    a,#0e2h,transok3;jump if not CapsLock=up
000410 03CE E551                     mov     a,Oldchar       ;see if Caps was just down
000411 03D0 304B03                   jnb     Kstyle,XTcap    ;if XT, skip control feature.
000412 03D3 B4621D                   cjne    a,#62h,transok4 ;if not, then it was a control
000413 03D6                  XTcap:
000414 03D6 C243                     clr     Capdown         ;clear flag
000415 03D8 B242                     cpl     Capbit          ;toggle down/up-ness of Caplock
000416 03DA 7462                     mov     a,#62h
000417 03DC A242                     mov     c,Capbit
000418 03DE B3                       cpl     c
000419 03DF 92E7                     mov     acc.7,c
000420 03E1 B16F                     acall   actualtransmit  ;(Caps to Amiga!)
000421 03E3 304B0C                   jnb     Kstyle,skiplights ;(don't do lights if XT)
000422 03E6 74ED                     mov     a,#0edh         ;set lights on next byte.
000423 03E8 711F                     acall   SendtoAT
000424 03EA 7402                     mov     a,#2            ;numlock on
000425 03EC A242                     mov     c,Capbit
000426 03EE 92E2                     mov     acc.2,c
000427 03F0 711F                     acall   SendtoAT        ;maybe capslock light
000428 03F2                  skiplights: 
000429 03F2 22                       ret           
000430 03F3                  transok4:
000431 03F3 C244                     clr     CtrlDown        ;This sends out a Control Up.
000432 03F5 C243                     clr     Capdown         ;Caps lock is done functioning as Ctl
000433 03F7 7463                     mov     a,#63h          ;Control Key
000434 03F9 D2E7                     setb    acc.7           ;break bit set.
000435 03FB B16F                     acall   actualtransmit  ;send to Amiga.
000436 03FD 22                       ret
000437 03FE                  transok3:
000438 03FE F551                     mov     Oldchar,a
000439 0400 304B0E                   jnb     Kstyle,noControl
000440 0403 30430B                   jnb     Capdown,noControl
000441 0406 204408                   jb      CtrlDown,noControl
000442 0409 D244                     setb    CtrlDown        ;Caps lock is beginning to function
000443 040B 7463                     mov     a,#63h          ;as the Control Key.
000444 040D B16F                     acall   actualtransmit  ;send Control Down to Amiga
000445 040F E551                     mov     a,Oldchar       ;now send the actual key
000446 0411                  
000447 0411                  noControl:                      ;its not a controlled key
000448 0411 A2E7                     mov     c,acc.7         ;c=make/break bit
000449 0413 9249                     mov     Make,c          ;will be set if key up
000450 0415 C2E7                     clr     acc.7           ;test for key only. NO make/break
000451 0417 B40E19                   cjne    a,#0eh,noMup    ;special key mouse up
000452 041A 30490B                   jnb     Make,kmupdown
000453 041D                  kmupup:
000454 041D 74CC                     mov     a,#0cch         ;cursor up break
000455 041F B16F                     acall   actualtransmit
000456 0421 9187                     acall   Smalldelay
000457 0423 74E7                     mov     a,#0e7h         ;right amiga break
000458 0425 B16F                     acall   actualtransmit
000459 0427 22                       ret
000460 0428                  kmupdown:
000461 0428 7467                     mov     a,#67h          ;amiga make
000462 042A B16F                     acall   actualtransmit
000463 042C 9187                     acall   Smalldelay
000464 042E 744C                     mov     a,#4ch          ;cursor up make
000465 0430 B16F                     acall   actualtransmit
000466 0432 22                       ret
000467 0433                  noMup:
000468 0433 B41C19                   cjne    a,#1ch,noMdown  ;special key mouse down
000469 0436 30490B                   jnb     Make,kmdowndown
000470 0439                  kmdownup:
000471 0439 74CD                     mov     a,#0cdh         ;cursor down break
000472 043B B16F                     acall   actualtransmit
000473 043D 74E7                     mov     a,#0e7h         ;amiga break
000474 043F 9187                     acall   Smalldelay
000475 0441 B16F                     acall   actualtransmit
000476 0443 22                       ret
000477 0444                  kmdowndown:
000478 0444 7467                     mov     a,#67h          ;amiga make
000479 0446 B16F                     acall   actualtransmit
000480 0448 9187                     acall   Smalldelay      ;cursor down make
000481 044A 744D                     mov     a,#4dh
000482 044C B16F                     acall   actualtransmit
000483 044E 22                       ret
000484 044F                  noMdown:
000485 044F B42C19                   cjne    a,#2ch,noMleft  ;special key mouse left
000486 0452 30490B                   jnb     Make,kmleftdown
000487 0455                  kmleftup:
000488 0455 74CF                     mov     a,#0cfh         ;cursor left break
000489 0457 B16F                     acall   actualtransmit
000490 0459 9187                     acall   Smalldelay      ;amiga break
000491 045B 74E7                     mov     a,#0e7h
000492 045D B16F                     acall   actualtransmit
000493 045F 22                       ret
000494 0460                  kmleftdown:
000495 0460 7467                     mov     a,#67h          ;amiga make
000496 0462 B16F                     acall   actualtransmit
000497 0464 9187                     acall   Smalldelay
000498 0466 744F                     mov     a,#4fh          ;cursor left make
000499 0468 B16F                     acall   actualtransmit
000500 046A 22                       ret
000501 046B                  noMleft:                        ;special key mouse right
000502 046B B4472B                   cjne    a,#47h,notspecial
000503 046E 30490B                   jnb     Make,kmrhtdown
000504 0471                  kmrhtup:
000505 0471 74CE                     mov     a,#0ceh         ;cursor right break
000506 0473 B16F                     acall   actualtransmit
000507 0475 9187                     acall   Smalldelay
000508 0477 74E7                     mov     a,#0e7h         ;amiga break
000509 0479 B16F                     acall   actualtransmit
000510 047B 22                       ret
000511 047C                  kmrhtdown:
000512 047C 7467                     mov     a,#67h          ;amiga make
000513 047E B16F                     acall   actualtransmit
000514 0480 9187                     acall   Smalldelay
000515 0482 744E                     mov     a,#04eh         ;cursor right make
000516 0484 B16F                     acall   actualtransmit
000517 0486 22                       ret
000518 0487                  Smalldelay:
000519 0487 758C00                   mov     th0,#0
000520 048A 758A00                   mov     tl0,#0
000521 048D C28D                     clr     tf0
000522 048F D28C                     setb    tr0
000523 0491 308DFD           small1: jnb     tf0,small1
000524 0494 C28D                     clr     tf0
000525 0496 C28C                     clr     tr0
000526 0498 22                       ret
000527 0499                  notspecial:
000528 0499 E551                     mov     a,Oldchar
000529 049B B16F                     acall   actualtransmit  ;transmit the keycode
000530 049D E551                     mov     a,Oldchar       ;get back same keycode, in A.
000531 049F A2E7                     mov     c,acc.7         ;put make/break bit in Make
000532 04A1 9249                     mov     Make,c
000533 04A3 C2E7                     clr     acc.7           ;start testing for reset keys
000534 04A5 B46306                   cjne    a,#63h,nrset1   ;held down
000535 04A8 A249                     mov     c,Make
000536 04AA 9245                     mov     CONTROL,c
000537 04AC 8010                     sjmp    trset
000538 04AE B46606           nrset1: cjne    a,#66h,nrset2
000539 04B1 A249                     mov     c,Make
000540 04B3 9246                     mov     LAMIGA,c
000541 04B5 8007                     sjmp    trset
000542 04B7 B46704           nrset2: cjne    a,#67h,trset
000543 04BA A249                     mov     c,Make
000544 04BC 9247                     mov     RAMIGA,c
000545 04BE 304505           trset:  jnb     CONTROL,maybefree       ;if bit set, this key is up
000546 04C1 204402                   jb      CtrlDown,maybefree      ;if bit set, this key is down
000547 04C4 8008                     sjmp    free
000548 04C6                  maybefree:
000549 04C6 204605                   jb      LAMIGA,free     ;ditto
000550 04C9 204702                   jb      RAMIGA,free     ;ditto
000551 04CC 8004                     sjmp    resetwarn       ;OOPS! They are all down!
000552 04CE 22               free:   ret
000553 04CF                  dummy:
000554 04CF 32                       reti
000555 04D0                  resetint:
000556 04D0 91CF                     acall   dummy
000557 04D2                  resetwarn:
000558 04D2 C28D                     clr     tf0             
000559 04D4 E578                     mov     a,78h
000560 04D6 7902                     mov     r1,#2           ;set up timer 0 watchdog
000561 04D8 758A00                   mov     tl0,#0
000562 04DB 758C00                   mov     th0,#0
000563 04DE F4                       cpl     a               ;invert, don't know why.
000564 04DF 7808                     mov     r0,#8
000565 04E1                  wr1:
000566 04E1 23                       rl      a
000567 04E2 A2E7                     mov     c,acc.7
000568 04E4 9294                     mov     Adat,c
000569 04E6 75F008                   mov     b,#8
000570 04E9                  wr2:
000571 04E9 D5F0FD                   djnz    b,wr2             ; transmit it.
000572 04EC C293                     clr     Aclk
000573 04EE 75F008                   mov     b,#8
000574 04F1                  wr3:
000575 04F1 D5F0FD                   djnz    b,wr3
000576 04F4 D293                     setb    Aclk
000577 04F6 75F00A                   mov     b,#10
000578 04F9                  wr4:
000579 04F9 D5F0FD                   djnz    b,wr4
000580 04FC D8E3                     djnz    r0,wr1
000581 04FE D294                     setb    Adat
000582 0500 D28C                     setb    tr0             ;start watchdog
000583 0502                  wr5:
000584 0502 309409                   jnb     Adat,caught1
000585 0505 308DFA                   jnb     tf0,wr5
000586 0508 C28D                     clr     tf0
000587 050A D9F6                     djnz    r1,wr5
000588 050C 8041                     sjmp    Hardreset
000589 050E                  caught1:
000590 050E C28C                     clr     tr0
000591 0510 C28D                     clr     tf0
000592 0512 E578                     mov     a,78h
000593 0514 7904                     mov     r1,#4
000594 0516 758A00                   mov     tl0,#0
000595 0519 758C00                   mov     th0,#0
000596 051C F4                       cpl     a    
000597 051D 7808                     mov     r0,#8
000598 051F                  wr11:
000599 051F 23                       rl      a
000600 0520 A2E7                     mov     c,acc.7
000601 0522 9294                     mov     Adat,c
000602 0524 75F008                   mov     b,#8
000603 0527                  wr22:
000604 0527 D5F0FD                   djnz    b,wr22   
000605 052A C293                     clr     Aclk
000606 052C 75F008                   mov     b,#8
000607 052F                  wr33:
000608 052F D5F0FD                   djnz    b,wr33
000609 0532 D293                     setb    Aclk
000610 0534 75F00A                   mov     b,#10
000611 0537                  wr44:
000612 0537 D5F0FD                   djnz    b,wr44
000613 053A D8E3                     djnz    r0,wr11
000614 053C D294                     setb    Adat
000615 053E D28C                     setb    tr0             ;start watchdog
000616 0540                  wr55:
000617 0540 309409                   jnb     Adat,caught2
000618 0543 308DFA                   jnb     tf0,wr55
000619 0546 C28D                     clr     tf0
000620 0548 D9F6                     djnz    r1,wr55
000621 054A 8003                     sjmp    Hardreset
000622 054C                  caught2:
000623 054C 3094FD           hold:   jnb     Adat,hold
000624 054F                  Hardreset:
000625 054F C28C                     clr     tr0
000626 0551 C28D                     clr     tf0
000627 0553 C295                     clr     Areset
000628 0555 C293                     clr     Aclk            ;clear both lines for A500/A1000
000629 0557 790F                     mov     r1,#15          ;clock should go low for over 500ms
000630 0559 758C00                   mov     th0,#0          ;timer 1 will overflow repeatedly
000631 055C 758A00                   mov     tl0,#0
000632 055F D28C                     setb    tr0
000633 0561                  hsloop:
000634 0561 308DFD                   jnb     tf0,hsloop      ;wait for overflow flag
000635 0564 C28D                     clr     tf0             ;clear it again
000636 0566 D9F9                     djnz    r1,hsloop
000637 0568 C28D                     clr     tf0
000638 056A C28C                     clr     tr0             ;stop the timer
000639 056C 020200                   ljmp    start
000640 056F                   
000641 056F                  ;**************************************************
000642 056F                  ;* 
000643 056F                  ;* ActualTransmit sends the character out to the Amiga and waits
000644 056F                  ;* for an acknowledge handshake. If it does not receive one in
000645 056F                  ;* 143 ms, then it clocks out 1's on the data line until it 
000646 056F                  ;* receives the acknowledge. If the Amiga is not connected up, 
000647 056F                  ;* then it will hang here. The handshake is that the AMIGA 
000648 056F                  ;* drives the clock line low.
000649 056F                  ;*
000650 056F                  ;*      The loops with register B are for timing delays. 
000651 056F                  ;* There should be about 20usec between when the Data line is 
000652 056F                  ;* set, the Clock line is driven low, and the Clock line
000653 056F                  ;* is driven high.
000654 056F                  ;*
000655 056F                  ;**************************************************
000656 056F                  
000657 056F                  actualtransmit:
000658 056F F552                     mov     Amigachar,a     ;set the character to transmit
000659 0571                  
000660 0571 7805                     mov     r0,#05          ;do a small delay
000661 0573                  dly:
000662 0573 75F000                   mov     b,#0
000663 0576 D5F0FD           delay:  djnz    b,delay
000664 0579 D8F8                     djnz    r0,dly
000665 057B                  
000666 057B                  actual2:
000667 057B E552                     mov     a,Amigachar     ;restore it
000668 057D C250                     clr     Charbad         ;character is not bad yet
000669 057F 7902                     mov     r1,#2           ;set up timer 0 watchdog
000670 0581 758B00                   mov     tl1,#0
000671 0584 758D00                   mov     th1,#0
000672 0587 F4                       cpl     a               ;invert, don't know why.
000673 0588 7808                     mov     r0,#8
000674 058A 23               f:      rl      a
000675 058B A2E7                     mov     c,acc.7
000676 058D 9294                     mov     Adat,c
000677 058F 75F008                   mov     b,#8
000678 0592 D5F0FD           g:      djnz    b,g             ; transmit it.
000679 0595 C293                     clr     Aclk
000680 0597 75F008                   mov     b,#8
000681 059A D5F0FD           h:      djnz    b,h
000682 059D D293                     setb    Aclk
000683 059F 75F00A                   mov     b,#10
000684 05A2 D5F0FD           i:      djnz    b,i
000685 05A5 D8E3                     djnz    r0,f
000686 05A7 D294                     setb    Adat
000687 05A9 D28E                     setb    tr1             ;start watchdog
000688 05AB                  waitshake:
000689 05AB 2094FD                   jb      Adat,waitshake
000690 05AE C28E                     clr     tr1             ;stop watchdog
000691 05B0 3094FD           gotit:  jnb     Adat,gotit
000692 05B3 22                       ret
000693 05B4                  
000694 05B4                  timer1int:
000695 05B4 D91E                     djnz    r1,t3           ;we wait for 143 ms.
000696 05B6 7902                     mov     r1,#2           
000697 05B8 D250                     setb    Charbad         ;flag to resend the character
000698 05BA C294                     clr     Adat            ;1 on the data line
000699 05BC 75F008                   mov     b,#8
000700 05BF D5F0FD           tt1:    djnz    b,tt1           ;wait for it
000701 05C2 C293                     clr     Aclk            ;clock asserted
000702 05C4 75F008                   mov     b,#8            ;sync up the controller to the
000703 05C7 D5F0FD           tt2:    djnz    b,tt2           ;amiga
000704 05CA D293                     setb    Aclk
000705 05CC 75F00A                   mov     b,#10
000706 05CF D5F0FD           tt3:    djnz    b,tt3
000707 05D2 D294                     setb    Adat
000708 05D4 32               t3:     reti                    ;return and send again.
000709 05D5                  
000710 05D5                  ATtb1: 
000711 05D5 00                       .db     0               
000712 05D6 58                       .db     58h             ;F9
000713 05D7 00                       .db     0               
000714 05D8 54                       .db     54h             ;F5
000715 05D9 52                       .db     52h             ;F3
000716 05DA 50                       .db     50h             ;F1
000717 05DB 51                       .db     51h             ;F2
000718 05DC 5B                       .db     5bh             ;F12=right parenthesis
000719 05DD 00                       .db     0
000720 05DE 59                       .db     59h             ;F10
000721 05DF 57                       .db     57h             ;F8
000722 05E0 55                       .db     55h             ;F6
000723 05E1 53                       .db     53h             ;F4
000724 05E2 42                       .db     42h             ;TAB
000725 05E3 00                       .db     00h             ;~
000726 05E4 00                       .db     0
000727 05E5                  
000728 05E5 00                       .db     0
000729 05E6 64                       .db     64h             ;Left ALT
000730 05E7 60                       .db     60h             ;Left SHIFT
000731 05E8 00                       .db     0
000732 05E9 66                       .db     66h             ;Left Ctrl=Left AMIGA
000733 05EA 10                       .db     10h             ;Q
000734 05EB 01                       .db     01h             ;1
000735 05EC 00                       .db     0
000736 05ED 00                       .db     0
000737 05EE 00                       .db     0
000738 05EF 31                       .db     31h             ;Z
000739 05F0 21                       .db     21h             ;S
000740 05F1 20                       .db     20h             ;A
000741 05F2 11                       .db     11h             ;W
000742 05F3 02                       .db     02h             ;2
000743 05F4 00                       .db     0
000744 05F5                  
000745 05F5 00                       .db     0
000746 05F6 33                       .db     33h             ;C
000747 05F7 32                       .db     32h             ;X
000748 05F8 22                       .db     22h             ;D
000749 05F9 12                       .db     12h             ;E
000750 05FA 04                       .db     04h             ;4
000751 05FB 03                       .db     03h             ;3
000752 05FC 00                       .db     0
000753 05FD 00                       .db     0
000754 05FE 40                       .db     40h             ;SPACE
000755 05FF 34                       .db     34h             ;V
000756 0600 23                       .db     23h             ;F
000757 0601 14                       .db     14h             ;T
000758 0602 13                       .db     13h             ;R
000759 0603 05                       .db     05h             ;5
000760 0604 00                       .db     0
000761 0605                  
000762 0605 00                       .db     0
000763 0606 36                       .db     36h             ;N
000764 0607 35                       .db     35h             ;B
000765 0608 25                       .db     25h             ;H
000766 0609 24                       .db     24h             ;G
000767 060A 15                       .db     15h             ;Y
000768 060B 06                       .db     06h             ;6
000769 060C 00                       .db     0
000770 060D 00                       .db     0
000771 060E 00                       .db     0
000772 060F 37                       .db     37h             ;M
000773 0610 26                       .db     26h             ;J
000774 0611 16                       .db     16h             ;U
000775 0612 07                       .db     07h             ;7
000776 0613 08                       .db     08h             ;8
000777 0614 00                       .db     0
000778 0615                  
000779 0615 00                       .db     0
000780 0616 38                       .db     38h             ;<
000781 0617 27                       .db     27h             ;K
000782 0618 17                       .db     17h             ;I
000783 0619 18                       .db     18h             ;O
000784 061A 0A                       .db     0Ah             ;0
000785 061B 09                       .db     09h             ;9
000786 061C 00                       .db     0
000787 061D 00                       .db     0
000788 061E 39                       .db     39h             ;>
000789 061F 3A                       .db     3ah             ;/
000790 0620 28                       .db     28h             ;L
000791 0621 29                       .db     29h             ; ';'
000792 0622 19                       .db     19h             ;P
000793 0623 0B                       .db     0bh             ;-
000794 0624 00                       .db     0
000795 0625                  
000796 0625 00                       .db     0
000797 0626 00                       .db     0
000798 0627 2A                       .db     2ah             ;'
000799 0628 00                       .db     0
000800 0629 1A                       .db     1ah             ;[
000801 062A 0C                       .db     0ch             ;=
000802 062B 00                       .db     0
000803 062C 00                       .db     0
000804 062D 62                       .db     62h             ;CAPS LOCK?
000805 062E 61                       .db     61h             ;Right SHIFT
000806 062F 44                       .db     44h             ;RETURN
000807 0630 1B                       .db     1bh             ;]
000808 0631 00                       .db     0
000809 0632 0D                       .db     0dh             ;\
000810 0633 00                       .db     0
000811 0634 00                       .db     0
000812 0635                  
000813 0635                          .rs     6
000814 063B 41                       .db     41h             ;Back SPACE
000815 063C 00                       .db     0
000816 063D 00                       .db     0
000817 063E 1D                       .db     1dh             ;1 keypad
000818 063F 00                       .db     0
000819 0640 2D                       .db     2dh             ;4 keypad
000820 0641 3D                       .db     3dh             ;7 keypad
000821 0642 00                       .db     0
000822 0643 00                       .db     0
000823 0644 00                       .db     0
000824 0645                  
000825 0645 0F                       .db     0fh             ;0 keypad
000826 0646 3C                       .db     3ch             ;dot keypad
000827 0647 1E                       .db     1eh             ;2 keypad
000828 0648 2E                       .db     2eh             ;5 keypad
000829 0649 2F                       .db     2fh             ;6 keypad
000830 064A 3E                       .db     3eh             ;8 keypad
000831 064B 45                       .db     45h             ;ESCAPE!
000832 064C 63                       .db     63h             ;Number Lock=CTRL
000833 064D 5A                       .db     5ah             ;F11=( keypad
000834 064E 5E                       .db     5eh             ;+ keypad
000835 064F 1F                       .db     1fh             ;3 keypad
000836 0650 4A                       .db     4ah             ;- keypad
000837 0651 5D                       .db     5dh             ;* keypad
000838 0652 3F                       .db     3fh             ;9 keypad
000839 0653 67                       .db     67h             ;scroll Lock=Right AMIGA
000840 0654 00                       .db     0
000841 0655                  ATtb2:
000842 0655                          .rs     3
000843 0658 56                       .db     56h             ;F7
000844 0659 66                       .db     66h             ;print screen=Left Amiga
000845 065A                          .rs     11
000846 0665                  
000847 0665 00                       .db     0
000848 0666 65                       .db     65h             ;Right ALT
000849 0667 00                       .db     0
000850 0668 00                       .db     0
000851 0669 67                       .db     67h             ;Right CTL=RIGHT AMIGA
000852 066A                          .rs     11
000853 0675                  
000854 0675                          .rs     10h
000855 0685                          
000856 0685                          .rs     10h
000857 0695                  
000858 0695                          .rs     10
000859 069F 5C                       .db     5ch             ;/key, supposedly
000860 06A0                          .rs     5
000861 06A5                  
000862 06A5                          .rs     10
000863 06AF 43                       .db     43h             ;Numeric Enter
000864 06B0                          .rs     5
000865 06B5                  
000866 06B5                          .rs     9
000867 06BE 1C                       .db     1ch             ;End=Mouse down
000868 06BF 00                       .db     0
000869 06C0 4F                       .db     4fh             ;Cursor Left
000870 06C1 0E                       .db     0eh             ;Home=Mouse up
000871 06C2 00                       .db     0
000872 06C3 00                       .db     0
000873 06C4 63                       .db     63h             ;MACRO key=control
000874 06C5                  
000875 06C5 2C                       .db     2ch             ;Insert=Mouse Left
000876 06C6 46                       .db     46h             ;Delete
000877 06C7 4D                       .db     4dh             ;Cursor Down
000878 06C8 00                       .db     0
000879 06C9 4E                       .db     4eh             ;Cursor Right
000880 06CA 4C                       .db     4ch             ;Cursor Up
000881 06CB                          .rs     4
000882 06CF 5F                       .db     5fh             ;Page Down=Help
000883 06D0 00                       .db     0
000884 06D1 66                       .db     66h             ;print screen=LEFT AMIGA
000885 06D2 47                       .db     47h             ;Page up=mouse right
000886 06D3 40                       .db     40h             ;Break=Space?
000887 06D4 00                       .db     0
000888 06D5                  XTtb1:
000889 06D5 00                       .db     0
000890 06D6 45                       .db     45h             ;esc
000891 06D7 01                       .db     01h             ;1
000892 06D8 02                       .db     02h             ;2
000893 06D9 03                       .db     03h             ;3
000894 06DA 04                       .db     04h             ;4
000895 06DB 05                       .db     05h             ;5
000896 06DC 06                       .db     06h             ;6
000897 06DD 07                       .db     07h             ;7
000898 06DE 08                       .db     08h             ;8
000899 06DF 09                       .db     09h             ;9
000900 06E0 0A                       .db     0ah             ;0
000901 06E1 0B                       .db     0bh             ;-
000902 06E2 0C                       .db     0ch             ;=
000903 06E3 41                       .db     41h             ;Backspace
000904 06E4 42                       .db     42h             ;Tab
000905 06E5                  
000906 06E5 10                       .db     10h             ;Q
000907 06E6 11                       .db     11h             ;W
000908 06E7 12                       .db     12h             ;E
000909 06E8 13                       .db     13h             ;R
000910 06E9 14                       .db     14h             ;T
000911 06EA 15                       .db     15h             ;Y
000912 06EB 16                       .db     16h             ;U
000913 06EC 17                       .db     17h             ;I
000914 06ED 18                       .db     18h             ;O
000915 06EE 19                       .db     19h             ;P
000916 06EF 1A                       .db     1Ah             ;[
000917 06F0 1B                       .db     1Bh             ;]
000918 06F1 44                       .db     44h             ;ENTER
000919 06F2 66                       .db     66h             ;L.CTL=LEFT AMIGA
000920 06F3 20                       .db     20h             ;A
000921 06F4 21                       .db     21h             ;S
000922 06F5                  
000923 06F5 22                       .db     22h             ;D
000924 06F6 23                       .db     23h             ;F
000925 06F7 24                       .db     24h             ;G
000926 06F8 25                       .db     25h             ;H
000927 06F9 26                       .db     26h             ;J
000928 06FA 27                       .db     27h             ;K
000929 06FB 28                       .db     28h             ;L
000930 06FC 29                       .db     29h             ;';'
000931 06FD 2A                       .db     2Ah             ;'
000932 06FE 00                       .db     00h             ;~
000933 06FF 60                       .db     60h             ;Left Shift
000934 0700 0D                       .db     0dh             ;\
000935 0701 31                       .db     31h             ;Z
000936 0702 32                       .db     32h             ;X
000937 0703 33                       .db     33h             ;C
000938 0704 34                       .db     34h             ;V
000939 0705                  
000940 0705 35                       .db     35h             ;B
000941 0706 36                       .db     36h             ;N
000942 0707 37                       .db     37h             ;M
000943 0708 38                       .db     38h             ;<
000944 0709 39                       .db     39h             ;>
000945 070A 3A                       .db     3Ah             ;/
000946 070B 61                       .db     61h             ;Right Shift
000947 070C 5D                       .db     5dh             ;Numeric *
000948 070D 64                       .db     64h             ;Left Alt
000949 070E 40                       .db     40h             ;space
000950 070F 62                       .db     62h             ;CapsLock
000951 0710 50                       .db     50h             ;F1
000952 0711 51                       .db     51h             ;F2
000953 0712 52                       .db     52h             ;F3
000954 0713 53                       .db     53h             ;F4
000955 0714 54                       .db     54h             ;F5
000956 0715                  
000957 0715 55                       .db     55h             ;F6
000958 0716 56                       .db     56h             ;F7
000959 0717 57                       .db     57h             ;F8
000960 0718 58                       .db     58h             ;F9
000961 0719 59                       .db     59h             ;F10
000962 071A 63                       .db     63h             ;Number Lock=Control
000963 071B 67                       .db     67h             ;Scroll Lock=Right Amiga
000964 071C 3D                       .db     3dh             ;Numeric 7
000965 071D 3E                       .db     3eh             ;* 8
000966 071E 3F                       .db     3fh             ;* 9
000967 071F 4A                       .db     4ah             ;* -
000968 0720 2D                       .db     2dh             ;* 4
000969 0721 2E                       .db     2eh             ;* 5
000970 0722 2F                       .db     2fh             ;* 6
000971 0723 5E                       .db     5eh             ;* +
000972 0724 1D                       .db     1dh             ;* 1
000973 0725                  
000974 0725 1E                       .db     1eh             ;* 2
000975 0726 1F                       .db     1fh             ;* 3
000976 0727 0F                       .db     0fh             ;* 0
000977 0728 3C                       .db     3ch             ;* .
000978 0729 63                       .db     63h             ;print screen=CONTROL
000979 072A 00                       .db     0
000980 072B 00                       .db     0
000981 072C 5A                       .db     5ah             ;F11=Numeric (
000982 072D 5B                       .db     5bh             ;F12=Numeric )
000983 072E                          .rs     7
000984 0735                  
000985 0735                          .rs     10h
000986 0745                  
000987 0745                          .rs     10h
000988 0755                  XTtb2:
000989 0755                          .rs     10h
000990 0765                  
000991 0765                          .rs     12
000992 0771 43                       .db     43h             ;Numeric Enter
000993 0772 67                       .db     67h             ;Right Control=RIGHT AMIGA
000994 0773                          .rs     2
000995 0775                  
000996 0775                          .rs     10h
000997 0785                          
000998 0785                          .rs     5
000999 078A 5C                       .db     5ch             ;Numeric /key
001000 078B 00                       .db     0
001001 078C 66                       .db     66h             ;Print Screeen=Left Amiga
001002 078D 65                       .db     65h             ;Right Alt
001003 078E                          .rs     7
001004 0795                  
001005 0795                          .rs     6
001006 079B 5F                       .db     5fh             ;BREAK=HELP!
001007 079C 0E                       .db     0eh             ;Home=MOUSE UP
001008 079D 4C                       .db     4ch             ;cursor up
001009 079E 47                       .db     47h             ;pageup=mouse right
001010 079F 00                       .db     0
001011 07A0 4F                       .db     4fh             ;cursor left
001012 07A1 00                       .db     0
001013 07A2 4E                       .db     4eh             ;cursor right
001014 07A3 00                       .db     0
001015 07A4 1C                       .db     1ch             ;End=mouse down
001016 07A5                  
001017 07A5 4D                       .db     4dh             ;cursor down
001018 07A6 5F                       .db     5fh             ;page down=HELP!
001019 07A7 2C                       .db     2ch             ;insert=mouse left
001020 07A8 46                       .db     46h             ;delete
001021 07A9                          .rs     12
001022 07B5                         
001023 07B5                          .rs     15
001024 07C4 63                       .db     63h             ;Macro=control
001025 07C5                  
001026 07C5                          .rs     10h
001027 07D5                  
001028 07D5                          .end    0

AC      =00D6  ET2     =00AD  P0.0    =0080  RXD     =00B0  TMOD    =0089  
ACC     =00E0  EX0     =00A8  P0.1    =0081  SBUF    =0099  TR0     =008C  
ACC.0   =00E0  EX1     =00AA  P0.2    =0082  SCON    =0098  TR1     =008E  
ACC.1   =00E1  EXEN2   =00CB  P0.3    =0083  SCON.0  =0098  TR2     =00CA  
ACC.2   =00E2  EXF2    =00CE  P0.4    =0084  SCON.1  =0099  TRANSMIT=03BF  
ACC.3   =00E3  F       =058A  P0.5    =0085  SCON.2  =009A  TRANSOK =03C3  
ACC.4   =00E4  F0      =00D5  P0.6    =0086  SCON.3  =009B  TRANSOK2=03CB  
ACC.5   =00E5  FREE    =04CE  P0.7    =0087  SCON.4  =009C  TRANSOK3=03FE  
ACC.6   =00E6  G       =0592  P1      =0090  SCON.5  =009D  TRANSOK4=03F3  
ACC.7   =00E7  GOTIT   =05B0  P1.0    =0090  SCON.6  =009E  TRSET   =04BE  
ACLK    =0093  H       =059A  P1.1    =0091  SCON.7  =009F  TT1     =05BF  
ACTUAL2 =057B  HARDRESE=054F  P1.2    =0092  SEND4   =0325  TT2     =05C7  
ACTUALTR=056F  HOLD    =054C  P1.3    =0093  SEND5   =032D  TT3     =05CF  
ADAT    =0094  HSLOOP  =0561  P1.4    =0094  SEND6   =0337  TXD     =00B1  
AMIGACHA=0052  I       =05A2  P1.5    =0095  SEND7   =033C  WAITSHAK=05AB  
ARESET  =0095  IE      =00A8  P1.6    =0096  SEND77  =033F  WR1     =04E1  
ATDATAB =02C3  IE.0    =00A8  P1.7    =0097  SEND78  =0344  WR11    =051F  
ATDOWN  =030F  IE.1    =00A9  P2      =00A0  SEND79  =0347  WR2     =04E9  
ATERROR =02B4  IE.2    =00AA  P2.0    =00A0  SEND7A  =034A  WR22    =0527  
ATGETKEY=0290  IE.3    =00AB  P2.1    =00A1  SEND8   =034F  WR3     =04F1  
ATNE0   =0308  IE.4    =00AC  P2.2    =00A2  SEND9   =0355  WR33    =052F  
ATNE012 =0302  IE.5    =00AD  P2.3    =00A3  SENDTOAT=031F  WR4     =04F9  
ATNE0F0 =02FC  IE.7    =00AF  P2.4    =00A4  SKIPLIGH=03F2  WR44    =0537  
ATNE1   =02E0  IE0     =0089  P2.5    =00A5  SM0     =009F  WR5     =0502  
ATNEF12 =02F6  IE1     =008B  P2.6    =00A6  SM1     =009E  WR55    =0540  
ATNSTART=029D  INIT    =0000  P2.7    =00A7  SM2     =009D  XT7BIT  =004A  
ATNSTOP =02BA  INT0    =00B2  P3      =00B0  SMALL1  =0491  XTCAP   =03D6  
ATPARITY=0048  INT1    =00B3  P3.0    =00B0  SMALLDEL=0487  XTGETKEY=035C  
ATPOWERU=0277  IP      =00B8  P3.1    =00B1  SP      =0081  XTLOOKUP=03A7  
ATSTYLE =02CB  IP.0    =00B8  P3.2    =00B2  START   =0200  XTN2A   =039A  
ATTB1   =05D5  IP.1    =00B9  P3.3    =00B3  SYNC    =022D  XTN36   =03A4  
ATTB2   =0655  IP.2    =00BA  P3.4    =00B4  SYNC2   =0237  XTNAA   =0395  
ATUP    =0317  IP.3    =00BB  P3.5    =00B5  SYNC3   =023A  XTNB6   =039F  
ATWAIT  =02C6  IP.4    =00BC  P3.6    =00B6  T2CON   =00C8  XTNE0   =03B7  
ATWAITC0=0294  IP.5    =00BD  P3.7    =00B7  T2CON.0 =00C8  XTNE1   =038B  
ATWAITC1=02A0  IT0     =0088  PARITYEV=02AC  T2CON.1 =00C9  XTPOWERU=0263  
B       =00F0  IT1     =008A  PARITYOD=02B0  T2CON.2 =00CA  XTRESET =0269  
B.0     =00F0  KCLK    =0090  PAUSE   =02A7  T2CON.3 =00CB  XTSTYLE =037A  
B.1     =00F1  KDAT    =0091  PCON    =0087  T2CON.4 =00CC  XTTB1   =06D5  
B.2     =00F2  KMDOWNDO=0444  PS      =00BC  T2CON.5 =00CD  XTTB2   =0755  
B.3     =00F3  KMDOWNUP=0439  PSW     =00D0  T2CON.6 =00CE  XTTEST  =0257  
B.4     =00F4  KMLEFTDO=0460  PSW.0   =00D0  T2CON.7 =00CF  XTW1    =0360  
B.5     =00F5  KMLEFTUP=0455  PSW.1   =00D1  T3      =05D4  XTW2    =0363  
B.6     =00F6  KMRHTDOW=047C  PSW.2   =00D2  TB8     =009B  XTW3    =0366  
B.7     =00F7  KMRHTUP =0471  PSW.3   =00D3  TCLK    =00CC  XTW4    =0369  
CAPBIT  =0042  KMUPDOWN=0428  PSW.4   =00D4  TCON    =0088  XTW5    =036C  
CAPDOWN =0043  KMUPUP  =041D  PSW.5   =00D5  TCON.0  =0088  XTW6    =0372  
CAUGHT1 =050E  KRESET  =0092  PSW.6   =00D6  TCON.1  =0089  
CAUGHT2 =054C  KSTYLE  =004B  PSW.7   =00D7  TCON.2  =008A  
CHARBAD =0050  KSWITCH =0097  PT0     =00B9  TCON.3  =008B  
CONTROL =0045  LAMIGA  =0046  PT1     =00BB  TCON.4  =008C  
CPRL2   =00C8  LL      =0272  PT2     =00BD  TCON.5  =008D  
CT2     =00C9  MAKE    =0049  PX0     =00B8  TCON.6  =008E  
CTRLDOWN=0044  MAYBEFRE=04C6  PX1     =00BA  TCON.7  =008F  
CY      =00D7  NOCONTRO=0411  RAMIGA  =0047  TF0     =008D  
DELAY   =0576  NOMDOWN =044F  RB8     =009A  TF1     =008F  
DLY     =0573  NOMLEFT =046B  RCAP2H  =00CB  TF2     =00CF  
DONTRANS=03BC  NOMUP   =0433  RCAP2L  =00CA  TH0     =008C  
DPH     =0083  NOTSPECI=0499  RCLK    =00CD  TH1     =008D  
DPL     =0082  NRSET1  =04AE  REN     =009C  TH2     =00CD  
DUMMY   =04CF  NRSET2  =04B7  RESETINT=04D0  TI      =0099  
EA      =00AF  OLDCHAR =0051  RESETWAR=04D2  TIMER1IN=05B4  
ES      =00AC  OV      =00D2  RI      =0098  TL0     =008A  
ET0     =00A9  P       =00D0  RS0     =00D3  TL1     =008B  
ET1     =00AB  P0      =0080  RS1     =00D4  TL2     =00CC  
@\Rogue\Monster\
else
  echo "shar: Will not over write key.list"
fi
if `test ! -s key.obj`
then
echo "x - key.obj"
cat > key.obj << '@\Rogue\Monster\'
:03000000020200F9
:030003000204D024
:03001B000205B427
:1002000075891175880575A800D2AFD2ABD2A8D276
:10021000B2D2B97581307590FFC28EC28FC28CC2C6
:100220008DC243C244C242D245D246D247758B00EA
:10023000758D007902D28E2094FD3094FDC28E74AB
:10024000FDB16F74FEB16F30971920912A758C0043
:10025000758A00C28DD28C208D093091FAC28CC271
:100260008D8014C24BC28DC290308DFDD290C28C55
:10027000C28D715C02037AD24B74FF711F74F671E8
:100280001F74ED711F7402711F74F4711F0202CB91
:10029000780BD2902090FD18B80A028029B8001A75
:1002A0003090FDC2907814D8FE20D004304805224A
:1002B0002048012274FE711F80D6B80106A29192D7
:1002C000488003A291133090FD80C95190B4E11091
:1002D000519051905190519051905190519080EB8C
:1002E0009005D5B4E0229006555190B4F00E51908F
:1002F000B412030202CBB4591E0202CBB4120302A1
:1003000002CBB4590A0202CBB4F004519080089396
:10031000C2E771BF0202CB93D2E771BF0202CBD218
:1003200090C29178082090FDA2E09291033090FD58
:1003300018B800F1A2D0B32090FD92913090FD202A
:1003400090FDD2913090FD2090FD3090FD7808D83E
:10035000FEC2907814D8FED290519022D2917808A3
:100360002090FD3090FD2090FD3090FD2090FDA26A
:1003700091133090FDD8F5C29122715CB4E10C71FB
:100380005C715C715C715C715C80EFB4E029715CE4
:10039000B4AA0280E5B42A0280E0B4B60280DBB4DD
:1003A000360280D6900755A2E7924AC2E793A24A46
:1003B00092E771BF02037A9006D580EBD0E022B5B8
:1003C000510122B46205F551D24322B4E230E55125
:1003D000304B03B4621DC243B2427462A242B39274
:1003E000E7B16F304B0C74ED711F7402A24292E2C0
:1003F000711F22C244C2437463D2E7B16F22F55128
:10040000304B0E30430B204408D2447463B16FE587
:1004100051A2E79249C2E7B40E1930490B74CCB12E
:100420006F918774E7B16F227467B16F9187744CD5
:10043000B16F22B41C1930490B74CDB16F74E791C0
:1004400087B16F227467B16F9187744DB16F22B419
:100450002C1930490B74CFB16F918774E7B16F22BB
:100460007467B16F9187744FB16F22B4472B3049D5
:100470000B74CEB16F918774E7B16F227467B16F5F
:100480009187744EB16F22758C00758A00C28DD22F
:100490008C308DFDC28DC28C22E551B16FE551A229
:1004A000E79249C2E7B46306A24992458010B46658
:1004B00006A24992468007B46704A2499247304594
:1004C000052044028008204605204702800422328D
:1004D00091CFC28DE5787902758A00758C00F47829
:1004E0000823A2E7929475F008D5F0FDC29375F049
:1004F00008D5F0FDD29375F00AD5F0FDD8E3D2947B
:10050000D28C309409308DFAC28DD9F68041C28CDC
:10051000C28DE5787904758A00758C00F47808231B
:10052000A2E7929475F008D5F0FDC29375F008D556
:10053000F0FDD29375F00AD5F0FDD8E3D294D28CB9
:10054000309409308DFAC28DD9F680033094FDC203
:100550008CC28DC295C293790F758C00758A00D2BA
:100560008C308DFDC28DD9F9C28DC28C020200F58E
:1005700052780575F000D5F0FDD8F8E552C25079F3
:1005800002758B00758D00F4780823A2E7929475AC
:10059000F008D5F0FDC29375F008D5F0FDD2937543
:1005A000F00AD5F0FDD8E3D294D28E2094FDC28E0D
:1005B0003094FD22D91E7902D250C29475F008D52C
:1005C000F0FDC29375F008D5F0FDD29375F00AD511
:1005D000F0FDD29432005800545250515B005957EC
:1005E00055534200000064600066100100000031B5
:1005F0002120110200003332221204030000403493
:100600002314130500003635252415060000003795
:10061000261607080000382717180A090000393A7B
:100620002829190B0000002A001A0C0000626144FE
:050630001B000D00009D
:10063B004100001D002D3D0000000F3C1E2E2F3EE3
:0A064B0045635A5E1F4A5D3F6700D9
:020658005666E4
:050665000065000067C4
:01069F005CFE
:0106AF004307
:0D06BE001C004F0E0000632C464D004E4CFA
:1006CF005F00664740000045010203040506070866
:1006DF00090A0B0C41421011121314151617181991
:1006EF001A1B4466202122232425262728292A0085
:1006FF00600D3132333435363738393A615D644005
:10070F00625051525354555657585963673D3E3FA7
:0F071F004A2D2E2F5E1D1E1F0F3C6300005A5BDC
:020771004367DC
:04078A005C00666544
:0E079B005F0E4C47004F004E001C4D5F2C4679
:0107C40063D1
:00000001FF
@\Rogue\Monster\
else
  echo "shar: Will not over write key.obj"
fi
if `test ! -s keydoc`
then
echo "x - keydoc"
cat > keydoc << '@\Rogue\Monster\'
IBM Keyboard Interfact Project, by ERic Rudolph, 1991.
No Copyright Whatsoever, but I would like credit where it's due.

This is documentation for the circuit I built which converts the information
put out by an XT or AT keyboard to that which can be recognized by an Amiga.

The circuit itself is a simple 8051 with an address latch and an Eprom.
It is inserted between the keyboard and the Amiga and sends data in both
directions to the Keyboard and the Amiga. 

Parts count could be reduced by using an 8751 which contains a 4k internal
Eprom. Seeing as how I don't know how to program them yet, I will stick to
the above design, but I am sure it's not hard to do. :-\

Full Parts List:
================
1) Intel 8031/8051, preferrably low power
2) 74373 address latch
3) 2732 Eprom
4) 11.059 MHZ crystal
5) 2 30pf caps
6) 1 10k resistor, 1/4 watt
7) 1 10uF electolytic cap
8) 2 momentary pushbutton switches. Neither is really needed.
10) connectors to the Amiga and the IBM

The total cost for these parts come to about $18.00 minus box and breadboard.
It certainly would be cheaper to use some used components. 

Wiring List:
============
INTEL 8031/8051:
Port1, pins 1-8 can be connected in any manner whatsoever,
so long as you change the source code. You can relocate
the lines to the Keyboard and the Amiga wherever suitable.
If you understand the 8051 or read the 8051 manual, it will make more
sense.
	pin	to
	===	==
	1(p1.0)	Keyboard Clock. Female 5-pin, pin #1
	2	Keyboard Data, Female 5-pin, pin #2
	3 	
	4	Amiga Clock
	5	Amiga Data
	6	Amiga Reset
	7
	8(p1.7)	XT/AT pin. Tie low to always convert an XT keyboard.
		For Auto detect, leave pin unconnected.
	9(reset) to - side of 10uF cap & 10k resistor & pushbutton switch
		only if you want a manual CIRCUIT reset switch.
	10(p3.0)
	11
	12(int0)  pushbutton switch2
	13-16
	17(p3.7)
	18	clock crystal & 30pf cap1
	19	clock crystal(other pin) & 30pf cap2
	20 	Ground
	21(a8)	Eprom Addr8, 2732 pin#23
	22 	Eprom Addr9, 2732 pin#22
	23 	Eprom Addr10, 2732 pin#19
	24(a11)	Eprom Addr11, 2732 pin#21
	25-28
	29	Eprom Read, 2732 pin#20
	30	373 Gate, pin# 11
	31 	Ground
	32(ad7)	373 D7, pin#13 & Eprom Data7, pin#17
	33	373 D6, pin#14 & Eprom Data6, pin#16
	34	373 D5, pin#8 & Eprom Data5, pin#15
	35	373 D4, pin#7 & Eprom Data4, pin#14
	36	373 D3, pin#4 & Eprom Data3, pin#13
	37	373 D2, pin#3 & Eprom Data2, pin#11
	38	373 D1, pin#17 & Eprom Data1, pin#10
	39(ad0)	373 D0, pin#18 & Eprom Data0, pin#9
	40	+5 Volts
74373:
	1	Ground
	2	Eprom Addr2, pin#6
	3	done
	4	done
	5	Eprom Addr3, pin#5
	6	Eprom Addr4, pin#4	
	7	done
	8	done
	9	Eprom Addr5, pin#3	
	10	Ground
	11	done
	12	Eprom Addr7, pin#1
	13	done
	14	done
	15	Eprom Addr6, pin#2
	16	Eprom Addr1, pin#7
	17	done
	18	done
	19	Eprom Addr0, pin#8
	20	+5 volts
2732 Prom:
	1-11	done
	12	Ground
	13-17	done
	18	Ground (chip enable. Doesn't save power very much)
	19-23	done
	24	+5 volts
crystal:
	connected between 8051 pins 18 and 19
30pf cap1:
	connected between a lead of cystal and ground
30pf cap2:
	connected between other lead of crystal and ground
10uF Electrolytic Cap:
	minus end to 8051 pin9, + end to +5 volts.
10k resistor:
	tied between ground and 8051 pin 9
VVV reset pushbutton switch. This is not absolutely necessary.
Pushbutton Switch1:
	tied between 8051 pin9 and +5 volts
VVV only use if you want a one-button hard reset.
Pushbutton Switch2: (amiga reset switch)
	tied between 8051 pin12 (int0) and ground
5-pin Female IBM connector:
	Connect plus voltage pin to +5 volts
	Connect ground pin to ground
	connect clock and data as in above
(pin1=clock, pin2=data, pin3=NC, pin4=ground, pin5=+5v)
(as you face the back of the 5-pin female din, with the notch pointing up,
the pin order from left to right is 1,4,2,5,3)

Amiga Connector: each of the amiga connectors for the 500/1000/2000 will 
	be different.
On the Amiga 1000, the keyboard connects by means of a telephone
	HANDSET connector with a regular phone handset cord. The pins
	from left to right on the back of the Amiga 1000 are +5,clock,data,GND.
	If you make this circuit yourself, I suggest purchasing a little jack
	from the local telephone repairman. They are fairly standard jacks
	I believe. Connect red on the jack to +5,white to clock,greeen to
	data, black to ground. (On the circuit board, that is...)
	Clock and Data are wherever you locate them in the source code.
	As it stands, Amiga Clock is on pin 3 of the 8051, and Data is
	on pin 4.

For the Amiga 500, there is a 8 pin straight line on the mother board.
These pins from left to right are
1. Data
2. Clock
3. Reset
4.+5
5 Not connected. (Key)
6.Ground
7. Status (not used)
8. Disk Light (not used)

Make yourself a special adaptor that connects your amiga to the circuit.
You WILL need to connect the reset line if you want to soft reset from
the keyboard. The A500 only resets by having the Reset line driven low.

It says in my hardware manual here that The connector TO the keyboard
goes as follows:
1: Clock
2: Data
3: Not connected.
4: Ground
5: +5 volts.
I imagine it's just like the AT connector, but it's a shame they don't use
the same data signals!



VERY IMPORTANT:!!!! The cord from the Amiga to the Converter must be
very very short and have very low resistance for this circuit to run on it's
own power. Do NOT use a long handset cord, it will load down the power lines.
IT's made of ribbon copper wound around some white stuff and it conducts poorly
on purpose. I used a hackup phone handset cord that is only about 3 inches
long. That works fine. You may need to get a phone repairman to make the
little cord special. He can do it, I know. It's a common thing. It shouldn't
be expensive. The one he made for me cost 1$.
 
That's it!
====================================================================
A little background on the IBM AT keyboard:
The keyboard I used for this circuit was a BTC 5339sx. It costs about $40
Lucky Computers, 1-800-348-5825. I have also tested the circuit on a 
standard PC keyboard, and an HP Vectra AT keyboard.

The AT keyboard DIN connector has 5 pins. Pin 3 is called Reset, but it's
reserved, so we can't use it. Forget it exists on the AT keyboard. They just
charge you money for it. (joke) Open collectors drive the clock and data pins,
so when they are not driven low, they float at 5 volts.

The keyboard transmits data by bits, each synchonous somehow with the clock
line. They keyboard when clocking in or out data, always runs the clock.
The controller can drive the clock line, but not with reference to data.
	When the Keyboard sends data, it first sets the data, then drives
clock low, then high, and then changes the data to the next value.
	The AT uses 11 bits for a transmission, 1 start bit (0), 8 data
bits, 1 parity bit-set if the number of 1's in the data bits is even, and
a stop bit (1). When the keyboard sends it's last bit, the stop bit, the
controller must drive clock line low as a handshake and to tell the 
keyboard not to send until clock goes high again.
	Theoretically, the controller could interrupt the sending of the
bits, but I consider this unnecessary, and don't bother with it.
When the computer needs to send a command to the keyboard, it sets clock
line high and the data line low. When the keyboard sees this, it will
start clocking pulsed on the data line. 
Then, the controller must look for the clock line going low, set the data
bit, wait for the clock to go high, then wait for the clock to go low
again, and then change the bit. Thus, it changes the data in the middle
of the clock low pulse. When the keyboard has received it's 10th bit,
it will drive the data line low while at the same time clocking out
an extra clock low pulse. Then, it expects a handshake of the clock line
low from the controller.
                    0       1       2   |   7       P     stop    extra
Clock:------------\___/---\___/---\___/---\___/---\___/---\___/---\___/end

Data:-------\_______00000001111111122222|6677777777PPPPPPPP1111xxxxxxxx_____

Notice there is NO start bit when the controller sends data to the Keyboard.

Special Commands the Keyboard can Send to the Controller:
-----------------------------------------------------------
00 	Keyboard buffer overflowed
AA 	Selftest passed
FA	The command sent was received correctly
FE	The command sent was received poorly. Please resend.

Special Commands the Controller can Send to the Keyboard:
-----------------------------------------------------------
ED	Set the LEDs according to next byte I send
	bit 0=Scroll lock 1=on
	bit 1=Num lock
	bit 2=Caps lock
	bits 3-7 must be 0
F4	clear the key buffer and start scanning
F6	restore default values
FE	retransmit last character, please
FF	Reset, you stupid keyboard!

Whew! That about raps it up for the AT keybard! Enough said, right?


XT keyboards transmit much the same way except they only use 10 bits.
Two start bits (both high) and 8 data bits, transmitted in order 0-1-2...-7
The last bit is a make/break bit which is 1 to signify a break.

The XT can have no commands sent to it. The way to reset it is to drive
the Clock line low for some longish period of time. The keyboard will not
send data (it will hold off) if the data line is being held low by an
external source (the controller)

AMIGA SIDE=========================================

Now I bet you are all wondering which keys are mapped to which keys.
I am using the 101 AT keyboard.

AT			Amiga
==			=====

Left Ctrl		Left Amiga
Right Ctrl		Right Amiga
F11			Numeric Keypad (
F12			Numeric Keypad ) (doesn't work on A1000's)
Capslock		Control (IF used in conjunction with another key)
Delete			Delete
Page Down		Help
PrintScreen		Left Amiga
ScrollLock		Right Amiga
NumLock			Control
(the above three keys mapped for easy one-hand reset)
Insert			Amiga+Left Cursor
Home			Amiga+Up Cursor
End			Amiga+Down Cursor
PageUp			Amiga+Right Cursor
(the above keys mapped for easy mouse pointer control in workbench.)

The BTC keyboard I used also included a Macro key (conveniently) that
is mapped as a control key.


All other keys are mapped exactly the same.

Since the Control Keys on the AT are mapped to the Amiga keys,
I made a little routine that defines the Capslock Key to work as
Control if you hold it down first, then type the other key.
Just use it as you would an ordinary Control key.
This only works for the AT, not the XT since I can't control the lights
on the XT.

The explanation for how the Amiga Keyboard works is provided in the
Hardware Reference Manual. I will not repeat this info here, for fear of
copyright infringements and because the manual is cheap and a valuable
must for anyone who indulges in this kind of thing.


<><><><><><><><><><><><><><><><><><><><><><><><><><><><>

SOFTWARE:

I have included the source and the machine code for the software that
runs this circuit. The timing loops are pretty stringent so if you want to
change things, better have a logic analyzer on hand!

I am also going to include a simple 8051 code assembler for those who don't
like to hand-code. If you keep your programs neatly written, it should 
assemble fine.

Documentation is within the program listing. It's not too hard to follow if
you know what you are doing.

Feel free to change anything you want, but before you redistribute it,
please tell me of the changes. Make it known within the program that you
have made changes.

The circuit, once built, should never have to be removed once plugged into
your computer. It should Auto Detect which style keyboard is hooked up
if the XT/AT pin (now coded as Port 1.7 (pin 8)) is not tied low.
IF for some reason the circuit does not start up fine, you may need
a reset CIRCUIT switch. This is different than the reset Computer
switch. This switch SHOULD restart the circuit and make it sync
up to the computer and the keyboard.

I will sell anybody any number of the parts needed, from circuit board
to telephone connectors to the whole thing.

Circuit board alone: 5$
Telephone connector: 1.50$
Whole thing minus case:25$ plus shipping.
Full documentation: 1$ plus postage.

Any questions? Be glad to answer em!
Email address: rudolpe@jacobs.cs.orst.edu
Phone # 503-745-7466 (Oregon)

@\Rogue\Monster\
else
  echo "shar: Will not over write keydoc"
fi
# to concatenate archives, remove anything after this line
exit 0
