/* PC-AT Keyboard emulation */

/* Todo: (added by KT 22-Jun-2000 
	1. Check scancodes I have added are the actual scancodes for set 2 or 3.
	2. Check how codes are changed based on Shift/Control states for those sets
	   that require it - info in Help PC! 

*/

#include "driver.h"
#include "machine/pckeybrd.h"

/* AT keyboard documentation comes from www.beyondlogic.org and HelpPC documentation */

/* to enable logging of keyboard read/writes */
#define LOG_KEYBOARD	0


/*
	The PS/2 models have three make/break scan code sets.  The first
	  set matches the PC & XT make/break scan code set and is the one
	  listed here.	Scan code sets are selected by writing the value F0
	  to the keyboard via the ~8042~ (port 60h).  The following is a brief
	  description of the scan code sets (see the PS/2 Technical Reference
	  manuals for more information on scan code sets 2 and 3):

	ù  set 1, each key has a base scan code.  Some keys generate
	   extra scan codes to generate artificial shift states.  This
	   is similar to the standard scan code set used on the PC and XT.
	ù  set 2, each key sends one make scan code and two break scan
	   codes bytes (F0 followed by the make code).	This scan code
	   set is available on the IBM AT also.
	ù  set 3, each key sends one make scan code and two break scan
	   codes bytes (F0 followed by the make code) and no keys are
	   altered by Shift/Alt/Ctrl keys.
	ù  typematic scan codes are the same as the make scan code

*/


/* using the already existing input port definitions, this table re-maps
to scancode set 3.
I don't have the details for scan-code set 2,3 but they sound very similar
to the scancode set I have here. - KT 22/Jun/2000 */


/* key set 3 */
static int at_keyboard_scancode_set_2_3[]=
{
	0,
	0x076,
	0x016,
	0x01e,
	0x026,
	0x025,
	0x02e,
	0x036,
	0x03d,
	0x03e,
	0x046,
	0x045,
	0x04e,
	0x055,
	0x066,
	0x00d,
	0x015,
	0x01d,
	0x024,
	0x02d,
	0x02c,
	0x035,
	0x03c,
	0x043,
	0x044,
	0x04d,
	0x054,
	0x05b,
	0x05a,
	0x014,
	0x01c,
	0x01b,
	0x023,
	0x02b,
	0x034,
	0x033,
	0x03b,
	0x042,
	0x04b,
	0x04c,
	0x052,
	0x00e,
	0x012,
	0x05d,
	0x01a,
	0x022,
	0x021,
	0x02a,
	0x032,
	0x031,
	0x03a,
	0x041,
	0x049,
	0x04a,
	0x059,
	0x000,
	0x011,
	0x029,
	0x058,
	0x05,
	0x06,
	0x04,
	0x0c,
	0x03,
	0x0b,
	0x083,
	0x0a,
	0x01,
	0x09,
	0x077,
	0x07e,
	0x06c,
	0x075,
	0x07d,
	0x07b,
	0x06b,
	0x073,
	0x074,
	0x079,
	0x069,
	0x072,
	0x07a,
	0x070,
	0x071,
	0x00,
	0x00,
	0x078,
	0x07,
	0x05a,
	0x014,
	0x04a,
	0x000,
	0x011,
	0x06c,
	0x075,
	0x07d,
	0x06b,
	0x074,
	0x069,
	0x072,
	0x07a,
	0x070,
	0x071,
	0x000,
	0x000,
	0x000
};


#define AT_KEYBOARD_QUEUE_MAXSIZE	256

typedef struct at_keyboard
{	
	AT_KEYBOARD_TYPE type;
	int on;
	UINT8 delay;   /* 240/60 -> 0,25s */
	UINT8 repeat;   /* 240/ 8 -> 30/s */
	int numlock;
	UINT8 queue[AT_KEYBOARD_QUEUE_MAXSIZE];
	UINT8 head;
	UINT8 tail;
	UINT8 make[128];	

	int input_state;
	int scan_code_set;
	int last_code;
	int input_port_base;
} at_keyboard;

static at_keyboard keyboard;

typedef struct extended_keyboard_code
{
	const char *pressed;
	const char *released;
} extended_keyboard_code;


static extended_keyboard_code keyboard_mf2_code[0x10][2/*numlock off, on*/]={ 
	{	{ "\xe0\x1c", "\xe0\x9c" } }, /* keypad enter */
	{	{ "\xe0\x1d", "\xe0\x9d" } }, /* right control */
	{	{ "\xe0\x35", "\xe0\xb5" } },
	{	{ "\xe0\x37", "\xe0\xb7" } },
	{	{ "\xe0\x38", "\xe0\xb8" } },
	{	{ "\xe0\x47", "\xe0\xc7" }, { "\xe0\x2a\xe0\x47", "\xe0\xc7\xe0\xaa" } },
	{	{ "\xe0\x48", "\xe0\xc8" }, { "\xe0\x2a\xe0\x48", "\xe0\xc8\xe0\xaa" } },
	{	{ "\xe0\x49", "\xe0\xc9" }, { "\xe0\x2a\xe0\x49", "\xe0\xc9\xe0\xaa" } },
	{	{ "\xe0\x4b", "\xe0\xcb" }, { "\xe0\x2a\xe0\x4b", "\xe0\xcb\xe0\xaa" } },
	{	{ "\xe0\x4d", "\xe0\xcd" },	{ "\xe0\x2a\xe0\x4d", "\xe0\xcd\xe0\xaa" } },
	{	{ "\xe0\x4f", "\xe0\xcf" }, { "\xe0\x2a\xe0\x4f", "\xe0\xcf\xe0\xaa" } },
	{	{ "\xe0\x50", "\xe0\xd0" }, { "\xe0\x2a\xe0\x50", "\xe0\xd0\xe0\xaa" } },
	{	{ "\xe0\x51", "\xe0\xd1" }, { "\xe0\x2a\xe0\x51", "\xe0\xd1\xe0\xaa" } },
	{	{ "\xe0\x52", "\xe0\xd2" }, { "\xe0\x2a\xe0\x52", "\xe0\xd2\xe0\xaa" } },
	{	{ "\xe0\x53", "\xe0\xd3" }, { "\xe0\x2a\xe0\x53", "\xe0\xd3\xe0\xaa" } },
	{	{ "\xe1\x1d\x45\xe1\x9d\xc5" }, { "\xe0\x2a\xe1\x1d\x45\xe1\x9d\xc5" } }
};

/* I don't think these keys change if num-lock is active! */
/* pc-at extended keyboard make/break codes for code set 3 */
static extended_keyboard_code at_keyboard_extended_codes_set_2_3[]=
{
	/*keypad enter */
	{
		"\xe0\x5a",
		"\xe0\xf0\x5a"
	},
	/* right control */
	{
		"\xe0\x14",
		"\xe0\xf0\x14"
	},
	/* keypad slash */
	{
		"\xe0\x4a",
		"\xe0\xf0\x4a"
	},
	/* print screen */
	{
		"\xe0\x12\xe0\x7c",
		0, /* I don't know the break sequence */

	},
	/* right alt */
	{
		"\xe0\x11",
		"\xe0\xf0\x11"
	},
	/* home */
	{
		"\xe0\x6c",
		"\xe0\xf0\x6c"
	},
	/* cursor up */
	{
		"\xe0\x75",
		"\xe0\xf0\x75"
	},
	/* page up */
	{
		"\xe0\x7d",
		"\xe0\xf0\x7d"
	},
	/* cursor left */
	{
		"\xe0\x6b",
		"\xe0\xf0\x6b",
	},
	/* cursor right */
	{
		"\xe0\x74",
		"\xe0\xf0\x74"
	},
	/* end */
	{
		"\xe0\x69",
		"\xe0\xf0\x69",
	},
	/* cursor down */
	{
		"\xe0\x72",
		"\xe0\xf0\x72"
	},
	/* page down */
	{
		"\xe0\x7a",
		"\xe0\xf0\x7a"
	},
	/* insert */
	{
		"\xe0\x70",
		"\xe0\xf0\x70",
	},
	/* delete */
	{
		"\xe0\x71",
		"\xe0\xf0\x71"
	},
	/* pause */
	{
		"\xe1\x14\x77\xe1\xf0\x14\xf0\x77",
		0, /*?? I don't know the break sequence */
	}
	
};

static void at_keyboard_queue_insert(UINT8 data);
static int at_keyboard_queue_size(void);



void at_keyboard_init(AT_KEYBOARD_TYPE type)
{
	keyboard.type = type;
	keyboard.input_port_base = 4;
	keyboard.on = 1;
	keyboard.delay = 60;
	keyboard.repeat = 8;
	keyboard.numlock = 0;
	keyboard.head = keyboard.tail = 0;
	keyboard.input_state = 0;
	memset(&keyboard.make[0], 0, sizeof(UINT8)*128);
	/* set default led state */
	set_led_status(2, 0);
	set_led_status(0, 0);
	set_led_status(1, 0);

	keyboard.scan_code_set = 3;
}



void at_keyboard_reset(void)
{
	keyboard.head = keyboard.tail = 0;
	keyboard.input_state = 0;
	memset(&keyboard.make[0], 0, sizeof(UINT8)*128);
	/* set default led state */
	set_led_status(2, 0);
	set_led_status(0, 0);
	set_led_status(1, 0);

	keyboard.scan_code_set=1;
	at_keyboard_queue_insert(0xaa);
}

/* set initial scan set */
void	at_keyboard_set_scan_code_set(int set)
{
	keyboard.scan_code_set = set;
}

/* set base index for input ports */
void at_keyboard_set_input_port_base(int base)
{
	keyboard.input_port_base = base;
}



/* insert a code into the buffer */
static void at_keyboard_queue_insert(UINT8 data)
{
	if (LOG_KEYBOARD)
		logerror("keyboard queueing %.2x\n",data);

	keyboard.queue[keyboard.head] = data;
	keyboard.head++;
	keyboard.head %= (sizeof(keyboard.queue) / sizeof(keyboard.queue[0]));
}



static int at_keyboard_queue_size(void)
{
	int queue_size;
	queue_size = keyboard.head - keyboard.tail;
	if (queue_size < 0)
		queue_size += sizeof(keyboard.queue) / sizeof(keyboard.queue[0]);
	return queue_size;
}



/* add a list of codes to the keyboard buffer */
static void at_keyboard_helper(const char *codes)
{
	int i;
	for (i = 0; codes[i]; i++)
		at_keyboard_queue_insert(codes[i]);
}


/* add codes for standard keys */
static void at_keyboard_standard_scancode_insert(int our_code, int pressed)
{
	int scancode = our_code;

	switch (keyboard.scan_code_set)
	{
		case 1:
		{
			/* the original code was designed for this set, and there is
			a 1:1 correspondance for the scancodes */
			scancode = our_code;
		
			if (!pressed)
			{
				/* adjust code for break code */
				scancode|=0x080;
			}
		}
		break;

		case 2:
		case 3:
		{
			/* lookup scancode */
			scancode = at_keyboard_scancode_set_2_3[our_code];

			if (!pressed)
			{
				/* break code */
				at_keyboard_queue_insert(0x0f0);
			}

		}
		break;
	}

	at_keyboard_queue_insert(scancode);
}

static void at_keyboard_extended_scancode_insert(int code, int pressed)
{
	code = code - 0x060;

	switch (keyboard.scan_code_set)
	{
		case 1:
		{
			if (pressed)
			{
				if (keyboard_mf2_code[code][keyboard.numlock].pressed)
					at_keyboard_helper(keyboard_mf2_code[code][keyboard.numlock].pressed);
				else
					at_keyboard_helper(keyboard_mf2_code[code][0].pressed);
			}
			else
			{
				if (keyboard_mf2_code[code][keyboard.numlock].released)
					at_keyboard_helper(keyboard_mf2_code[code][keyboard.numlock].released);
				else if (keyboard_mf2_code[code][0].released)
					at_keyboard_helper(keyboard_mf2_code[code][0].released);
			}
		}
		break;

		case 2:
		case 3:
		{
			extended_keyboard_code *key = &at_keyboard_extended_codes_set_2_3[code];

			if (pressed)
			{
				if (key->pressed)
				{
					at_keyboard_helper(key->pressed);
				}
			}
			else
			{
				if (key->released)
				{
					at_keyboard_helper(key->released);
				}
			}
		}
		break;
	}

}


/**************************************************************************
 *	scan keys and stuff make/break codes
 **************************************************************************/
void at_keyboard_polling(void)
{
	int i;

	if (keyboard.on)
	{
		/* add codes for keys that are set */
		for( i = 0x01; i < 0x80; i++  )
		{
			if (i==0x60) i+=0x10; /* keys 0x60..0x6f need special handling */

			if( readinputport((i/16) + keyboard.input_port_base) & (1 << (i & 15)) )
			{
				if( keyboard.make[i] == 0 )
				{
					keyboard.make[i] = 1;

					if (i==0x45) keyboard.numlock^=1;

					at_keyboard_standard_scancode_insert(i,1);
				}
				else
				{
					keyboard.make[i] += 1;
					
					if( keyboard.make[i] == keyboard.delay )
					{
						at_keyboard_standard_scancode_insert(i, 1);
					}
					else
					{
						if( keyboard.make[i] == keyboard.delay + keyboard.repeat )
						{
							keyboard.make[i] = keyboard.delay;
							at_keyboard_standard_scancode_insert(i, 1);
						}
					}
				}
			}
			else
			{
				if( keyboard.make[i] )
				{
					keyboard.make[i] = 0;

					at_keyboard_standard_scancode_insert(i, 0);
				}
			}
		}

			/* extended scan-codes */
			for( i = 0x60; i < 0x70; i++  )
			{
				if( readinputport((i/16) + keyboard.input_port_base) & (1 << (i & 15)) )
				{
					if( keyboard.make[i] == 0 )
					{
						keyboard.make[i] = 1;
						
						at_keyboard_extended_scancode_insert(i,1);
						
					}
					else
					{
						keyboard.make[i] += 1;
						if( keyboard.make[i] == keyboard.delay )
						{
							at_keyboard_extended_scancode_insert(i, 1);
						}
						else
						{
							if( keyboard.make[i] == keyboard.delay + keyboard.repeat )
							{
								keyboard.make[i]=keyboard.delay;
								
								at_keyboard_extended_scancode_insert(i, 1);
							}
						}
					}
				}
				else
				{
					if( keyboard.make[i] )
					{
						keyboard.make[i] = 0;
						
						at_keyboard_extended_scancode_insert(i,0);
					}
				}
		}
	}
}

int at_keyboard_read(void)
{
	int data;
	if (keyboard.tail == keyboard.head)
		return -1;

	data = keyboard.queue[keyboard.tail];

	if (LOG_KEYBOARD)
		logerror("at_keyboard_read(): Keyboard Read 0x%02x\n",data);

	keyboard.tail++;
	keyboard.tail %= sizeof(keyboard.queue) / sizeof(keyboard.queue[0]);
	return data;
}

static void at_clear_buffer_and_acknowledge(void)
{
	/* clear output buffer and respond with acknowledge */
	keyboard.head = keyboard.tail = 0;
	at_keyboard_queue_insert(0x0fa);
}

/* From Ralf Browns Interrupt list:

Values for keyboard commands (data also goes to PORT 0060h):
Value	Count	Description
 EDh	double	set/reset mode indicators Caps Num Scrl
		bit 2 = CapsLk, bit 1 = NumLk, bit 0 = ScrlLk
		all other bits must be zero.
 EEh	sngl	diagnostic echo. returns EEh.
 EFh	sngl	NOP (No OPeration). reserved for future use
 EF+26h	double	[Cherry MF2 G80-1501HAD] read 256 bytes of chipcard data
		keyboard must be disabled before this and has to
		be enabled after finished.
 F0h	double	get/set scan code set
		00h get current set
		01h scancode set 1 (PCs and PS/2 mod 30, except Type 2 ctrlr)

		02h scancode set 2 (ATs, PS/2, default)
		03h scancode set 3
 F2h	sngl	read keyboard ID (read two ID bytes)
		AT keyboards returns FA (ACK)
		MF2 returns AB 41 (translation) or
			    AB 83 (pass through)
 F3h	double	set typematic rate/delay
		format of the second byte:
		bit7=0 : reserved
		bit6-5 : typemativ delay
			 00b=250ms     10b= 750ms
			 01b=500ms     11b=1000ms
		bit4-0 : typematic rate (see #P050)
 F4h	sngl	enable keyboard
 F5h	sngl	disable keyboard. set default parameters (no keyboard scanning)
 F6h	sngl	set default parameters
 F7h	sngl	[MCA] set all keys to typematic (scancode set 3)

 F8h	sngl	[MCA] set all keys to make/release
 F9h	sngl	[MCA] set all keys to make only
 FAh	sngl	[MCA] set all keys to typematic/make/release
 FBh	sngl	[MCA] set al keys to typematic
 FCh	double	[MCA] set specific key to make/release
 FDh	double	[MCA] set specific key to make only
 FEh	sngl	resend last scancode
 FFh	sngl	perform internal power-on reset function
Note:	each command is acknowledged by FAh (ACK), if not mentioned otherwise.
	  See PORT 0060h-R for details.
SeeAlso: #P046
*/

void at_keyboard_write(UINT8 data)
{
	if (LOG_KEYBOARD)
		logerror("keyboard write %.2x\n",data);

	switch (keyboard.input_state)
	{
		case 0:
			switch (data) {
			case 0xed: /* leds schalten */
				/* acknowledge */
				at_keyboard_queue_insert(0x0fa);
				/* now waiting for  code... */
				keyboard.input_state=1;
				break;
			case 0xee: /* echo */
				/* echo code with no acknowledge */
				at_keyboard_queue_insert(0xee);
				break;
			case 0xf0: /* scancodes adjust */
				/* acknowledge */
				at_clear_buffer_and_acknowledge();
				/* waiting for data */
				keyboard.input_state=2;
				break;
			case 0xf2: /* identify keyboard */
				/* ack and two byte keyboard id */
				at_keyboard_queue_insert(0xfa);

				/* send keyboard code */
				if (keyboard.type == AT_KEYBOARD_TYPE_MF2) {
					at_keyboard_queue_insert(0xab);
					at_keyboard_queue_insert(0x41);
				}
				else
				{
					/* from help-pc docs */
					at_keyboard_queue_insert(0x0ab);
					at_keyboard_queue_insert(0x083);
				}

				break;
			case 0xf3: /* adjust rates */
				/* acknowledge */
				at_keyboard_queue_insert(0x0fa);

				keyboard.input_state=3;
				break;
			case 0xf4: /* activate */
				at_clear_buffer_and_acknowledge();

				keyboard.on=1;
				break;
			case 0xf5:
				/* acknowledge */
				at_clear_buffer_and_acknowledge();
				/* standardvalues */
				keyboard.on=0;
				break;
			case 0xf6:
				at_clear_buffer_and_acknowledge();
				/* standardvalues */
				keyboard.on=1;
				break;
			case 0xfe: /* resend */
				/* should not happen, for now send 0  */
				at_keyboard_queue_insert(0);	/*keyboard.last_code); */
				break;
			case 0xff: /* reset */
				/* it doesn't state this in the docs I have read, but I assume
				that the keyboard input buffer is cleared. The PCW16 sends &ff,
				and requires that 0x0fa is the first byte to be read */
					
				at_clear_buffer_and_acknowledge();

	/*			   acknowledge    */
	/*			at_keyboard_queue_insert(0xfa); */
				/* BAT completion code */
				at_keyboard_queue_insert(0xaa);
				break;
			}
			break;
		case 1: 
			/* code received */
			keyboard.input_state=0;

			/* command? */
			if (data & 0x080)
			{
				/* command received instead of code - execute command */
				at_keyboard_write(data);
			}
			else
			{
				/* send acknowledge */
				at_keyboard_queue_insert(0x0fa);
			
				/* led  bits */
				/* bits: 0 scroll lock, 1 num lock, 2 capslock */
				
				/* led's in same order as my keyboard leds. */
				/* num lock, caps lock, scroll lock */
				set_led_status(2, (data & 0x01));
				set_led_status(0, ((data & 0x02)>>1));
				set_led_status(1, ((data & 0x04)>>2));

			}
			break;
		case 2:
			keyboard.input_state=0;

			/* command? */
			if (data & 0x080)
			{
				/* command received instead of code - execute command */
				at_keyboard_write(data);
			}
			else
			{
				/* 00  return byte indicating scan code set in use
				01  select scan code set 1  (used on PC & XT)
				02  select scan code set 2
				03  select scan code set 3
				*/

				if (data == 0x00)
				{
						at_keyboard_queue_insert(keyboard.scan_code_set);
				}
				else
				{
					keyboard.scan_code_set = data;
				}
			}
		
			break;
		case 3:
			/* 6,5: 250ms, 500ms, 750ms, 1s */
			/* 4..0: 30 26.7 .... 2 chars/s*/
		
			/* command? */
			keyboard.input_state=0;
			if (data & 0x080)
			{
				/* command received instead of code - execute command */
				at_keyboard_write(data);
			}
			else
			{
				/* received keyboard repeat */

			}

			break;
	}
}

/***************************************************************************
  unicode_char_to_at_keycode
***************************************************************************/

static UINT8 unicode_char_to_at_keycode(unicode_char_t ch)
{
	UINT8 b;
	switch(ch) {
	case '\032':					b = 1;		break;
	case '1':						b = 2;		break;
	case '2':						b = 3;		break;
	case '3':						b = 4;		break;
	case '4':						b = 5;		break;
	case '5':						b = 6;		break;
	case '6':						b = 7;		break;
	case '7':						b = 8;		break;
	case '8':						b = 9;		break;
	case '9':						b = 10;		break;
	case '0':						b = 11;		break;
	case '-':						b = 12;		break;
	case '=':						b = 13;		break;
	case '\010':					b = 14;		break;
	case '\t':						b = 15;		break;
	case 'q':						b = 16;		break;
	case 'w':						b = 17;		break;
	case 'e':						b = 18;		break;
	case 'r':						b = 19;		break;
	case 't':						b = 20;		break;
	case 'y':						b = 21;		break;
	case 'u':						b = 22;		break;
	case 'i':						b = 23;		break;
	case 'o':						b = 24;		break;
	case 'p':						b = 25;		break;
	case '[':						b = 26;		break;
	case ']':						b = 27;		break;
	case '\r':						b = 28;		break;
	case UCHAR_MAMEKEY(CAPSLOCK):	b = 29;		break;
	case 'a':						b = 30;		break;
	case 's':						b = 31;		break;
	case 'd':						b = 32;		break;
	case 'f':						b = 33;		break;
	case 'g':						b = 34;		break;
	case 'h':						b = 35;		break;
	case 'j':						b = 36;		break;
	case 'k':						b = 37;		break;
	case 'l':						b = 38;		break;
	case ';':						b = 39;		break;
	case '\'':						b = 40;		break;
	case '`':						b = 41;		break;
	case '\\':						b = 43;		break;
	case 'z':						b = 44;		break;
	case 'x':						b = 45;		break;
	case 'c':						b = 46;		break;
	case 'v':						b = 47;		break;
	case 'b':						b = 48;		break;
	case 'n':						b = 49;		break;
	case 'm':						b = 50;		break;
	case ',':						b = 51;		break;
	case '.':						b = 52;		break;
	case '/':						b = 53;		break;
	case ' ':						b = 0x39;	break;
	case UCHAR_MAMEKEY(F1):			b = 0x3b;	break;
	case UCHAR_MAMEKEY(F2):			b = 0x3c;	break;
	case UCHAR_MAMEKEY(F3):			b = 0x3d;	break;
	case UCHAR_MAMEKEY(F4):			b = 0x3e;	break;
	case UCHAR_MAMEKEY(F5):			b = 0x3f;	break;
	case UCHAR_MAMEKEY(F6):			b = 0x40;	break;
	case UCHAR_MAMEKEY(F7):			b = 0x41;	break;
	case UCHAR_MAMEKEY(F8):			b = 0x42;	break;
	case UCHAR_MAMEKEY(F9):			b = 0x43;	break;
	case UCHAR_MAMEKEY(F10):		b = 0x44;	break;
	case UCHAR_MAMEKEY(NUMLOCK):	b = 0x45;	break;
	case UCHAR_MAMEKEY(SCRLOCK):	b = 0x46;	break;
	case UCHAR_MAMEKEY(7_PAD):		b = 0x47;	break;
	case UCHAR_MAMEKEY(8_PAD):		b = 0x48;	break;
	case UCHAR_MAMEKEY(9_PAD):		b = 0x49;	break;
	case UCHAR_MAMEKEY(MINUS_PAD):	b = 0x4a;	break;
	case UCHAR_MAMEKEY(4_PAD):		b = 0x4b;	break;
	case UCHAR_MAMEKEY(5_PAD):		b = 0x4c;	break;
	case UCHAR_MAMEKEY(6_PAD):		b = 0x4d;	break;
	case UCHAR_MAMEKEY(PLUS_PAD):	b = 0x4e;	break;
	case UCHAR_MAMEKEY(1_PAD):		b = 0x4f;	break;
	case UCHAR_MAMEKEY(2_PAD):		b = 0x50;	break;
	case UCHAR_MAMEKEY(3_PAD):		b = 0x51;	break;
	case UCHAR_MAMEKEY(0_PAD):		b = 0x52;	break;
	case UCHAR_MAMEKEY(DEL_PAD):	b = 0x53;	break;
	case UCHAR_MAMEKEY(F11):		b = 0x57;	break;
	case UCHAR_MAMEKEY(F12):		b = 0x58;	break;
	case '~':						b = 0x81;	break;
	case '!':						b = 0x82;	break;
	case '@':						b = 0x83;	break;
	case '#':						b = 0x84;	break;
	case '$':						b = 0x85;	break;
	case '%':						b = 0x86;	break;
	case '^':						b = 0x87;	break;
	case '&':						b = 0x88;	break;
	case '*':						b = 0x89;	break;
	case '(':						b = 0x8a;	break;
	case ')':						b = 0x8b;	break;
	case '_':						b = 0x8c;	break;
	case '+':						b = 0x8d;	break;
	case 'Q':						b = 0x90;	break;
	case 'W':						b = 0x91;	break;
	case 'E':						b = 0x92;	break;
	case 'R':						b = 0x93;	break;
	case 'T':						b = 0x94;	break;
	case 'Y':						b = 0x95;	break;
	case 'U':						b = 0x96;	break;
	case 'I':						b = 0x97;	break;
	case 'O':						b = 0x98;	break;
	case 'P':						b = 0x99;	break;
	case '{':						b = 0x9a;	break;
	case '}':						b = 0x9b;	break;
	case 'A':						b = 0x9e;	break;
	case 'S':						b = 0x9f;	break;
	case 'D':						b = 0xa0;	break;
	case 'F':						b = 0xa1;	break;
	case 'G':						b = 0xa2;	break;
	case 'H':						b = 0xa3;	break;
	case 'J':						b = 0xa4;	break;
	case 'K':						b = 0xa5;	break;
	case 'L':						b = 0xa6;	break;
	case ':':						b = 0xa7;	break;
	case '\"':						b = 0xa8;	break;
	case '|':						b = 0xab;	break;
	case 'Z':						b = 0xac;	break;
	case 'X':						b = 0xad;	break;
	case 'C':						b = 0xae;	break;
	case 'V':						b = 0xaf;	break;
	case 'B':						b = 0xb0;	break;
	case 'N':						b = 0xb1;	break;
	case 'M':						b = 0xb2;	break;
	case '<':						b = 0xb3;	break;
	case '>':						b = 0xb4;	break;
	case '?':						b = 0xb5;	break;
	default:						b = 0;		break;
	}
	return b;
}

/***************************************************************************
  QUEUE_CHARS( at_keyboard )
***************************************************************************/

QUEUE_CHARS( at_keyboard )
{
	int i;
	UINT8 b;

	for (i = 0; (i < text_len) && ((at_keyboard_queue_size()) + 4 < AT_KEYBOARD_QUEUE_MAXSIZE); i++)
	{
		b = unicode_char_to_at_keycode(text[i]);
		if (b)
		{
			if (b & 0x80)
				at_keyboard_standard_scancode_insert(0x36, 1);

			at_keyboard_standard_scancode_insert(b & 0x7f, 1);
			at_keyboard_standard_scancode_insert(b & 0x7f, 0);

			if (b & 0x80)
				at_keyboard_standard_scancode_insert(0x36, 0);
		}
	}
	return i;
}



/***************************************************************************
  Keyboard declaration
***************************************************************************/

#define PC_KEYB_HELPER(bit,text,key1,key2) \
	PORT_BIT( bit, 0x0000, IPT_KEYBOARD) PORT_NAME(text) PORT_CODE(key1) PORT_CODE(key2)

INPUT_PORTS_START( pc_keyboard )
    PORT_START  /* IN4 */
	PORT_BIT ( 0x0001, 0x0000, IPT_UNUSED ) 	/* unused scancode 0 */
	PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(26)			/* Esc                         01  81 */
	PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')	/* 1                           02  82 */
	PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')	/* 2                           03  83 */
	PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')	/* 3                           04  84 */
	PORT_BIT( 0x0020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')	/* 4                           05  85 */
	PORT_BIT( 0x0040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')	/* 5                           06  86 */
	PORT_BIT( 0x0080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')	/* 6                           07  87 */
	PORT_BIT( 0x0100, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')	/* 7                           08  88 */
	PORT_BIT( 0x0200, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')	/* 8                           09  89 */
	PORT_BIT( 0x0400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')	/* 9                           0A  8A */
	PORT_BIT( 0x0800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')	/* 0                           0B  8B */
	PORT_BIT( 0x1000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')	/* -                           0C  8C */
	PORT_BIT( 0x2000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')	/* =                           0D  8D */
	PORT_BIT( 0x4000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)			/* Backspace                   0E  8E */
	PORT_BIT( 0x8000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)			/* Tab                         0F  8F */
		
	PORT_START	/* IN5 */
	PORT_BIT( 0x0001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') /* Q                           10  90 */
	PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('W') /* W                           11  91 */
	PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E') /* E                           12  92 */
	PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('R') /* R                           13  93 */
	PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('T') /* T                           14  94 */
	PORT_BIT( 0x0020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') /* Y                           15  95 */
	PORT_BIT( 0x0040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U') /* U                           16  96 */
	PORT_BIT( 0x0080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I') /* I                           17  97 */
	PORT_BIT( 0x0100, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O') /* O                           18  98 */
	PORT_BIT( 0x0200, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P') /* P                           19  99 */
	PORT_BIT( 0x0400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') /* [                           1A  9A */
	PORT_BIT( 0x0800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') /* ]                           1B  9B */
	PORT_BIT( 0x1000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) /* Enter                       1C  9C */
	PORT_BIT( 0x2000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))      /* Left Ctrl                   1D  9D */
	PORT_BIT( 0x4000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A') /* A                           1E  9E */
	PORT_BIT( 0x8000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S') /* S                           1F  9F */
		
	PORT_START	/* IN6 */
	PORT_BIT( 0x0001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D') /* D                           20  A0 */
	PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F') /* F                           21  A1 */
	PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G') /* G                           22  A2 */
	PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('H') /* H                           23  A3 */
	PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('J') /* J                           24  A4 */
	PORT_BIT( 0x0020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K') /* K                           25  A5 */
	PORT_BIT( 0x0040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L') /* L                           26  A6 */
	PORT_BIT( 0x0080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') /* ;                           27  A7 */
	PORT_BIT( 0x0100, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('\"') /* '                           28  A8 */
	PORT_BIT( 0x0200, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') /* `                           29  A9 */
	PORT_BIT( 0x0400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT)) /* Left Shift                  2A  AA */
	PORT_BIT( 0x0800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') /* \                           2B  AB */
	PORT_BIT( 0x1000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') /* Z                           2C  AC */
	PORT_BIT( 0x2000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('X') /* X                           2D  AD */
	PORT_BIT( 0x4000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C') /* C                           2E  AE */
	PORT_BIT( 0x8000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('V') /* V                           2F  AF */
		
	PORT_START	/* IN7 */
	PORT_BIT( 0x0001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B') /* B                           30  B0 */
	PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('N') /* N                           31  B1 */
	PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M') /* M                           32  B2 */
	PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') /* ,                           33  B3 */
	PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') /* .                           34  B4 */
	PORT_BIT( 0x0020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') /* /                           35  B5 */
	PORT_BIT( 0x0040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) /* Right Shift                 36  B6 */
	PORT_BIT( 0x0080, 0x0000, IPT_KEYBOARD) PORT_NAME("KP * (PrtScr)") PORT_CODE(KEYCODE_ASTERISK)		/* Keypad *  (PrtSc)           37  B7 */
	PORT_BIT( 0x0100, 0x0000, IPT_KEYBOARD) PORT_NAME("Alt") PORT_CODE(KEYCODE_LALT)					/* Left Alt                    38  B8 */
	PORT_BIT( 0x0200, 0x0000, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')	/* Space                       39  B9 */
	PORT_BIT( 0x0400, 0x0000, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE	/* Caps Lock                   3A  BA */
	PORT_BIT( 0x0800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))			/* F1                          3B  BB */
	PORT_BIT( 0x1000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))			/* F2                          3C  BC */
	PORT_BIT( 0x2000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))			/* F3                          3D  BD */
	PORT_BIT( 0x4000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))			/* F4                          3E  BE */
	PORT_BIT( 0x8000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))			/* F5                          3F  BF */
		
	PORT_START	/* IN8 */
	PORT_BIT( 0x0001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))			 /* F6                          40  C0 */
	PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))			 /* F7                          41  C1 */
	PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))			 /* F8                          42  C2 */
	PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))		     /* F9                          43  C3 */
	PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))	     /* F10                         44  C4 */
	PC_KEYB_HELPER( 0x0020, "NumLock",      KEYCODE_NUMLOCK,    CODE_NONE )     /* Num Lock                    45  C5 */
	PC_KEYB_HELPER( 0x0040, "ScrLock",      KEYCODE_SCRLOCK,    CODE_NONE )     /* Scroll Lock                 46  C6 */
	PC_KEYB_HELPER( 0x0080, "KP 7 (Home)",  KEYCODE_7_PAD,      KEYCODE_HOME )  /* Keypad 7  (Home)            47  C7 */
	PC_KEYB_HELPER( 0x0100, "KP 8 (Up)",    KEYCODE_8_PAD,      KEYCODE_UP )    /* Keypad 8  (Up arrow)        48  C8 */
	PC_KEYB_HELPER( 0x0200, "KP 9 (PgUp)",  KEYCODE_9_PAD,      KEYCODE_PGUP)   /* Keypad 9  (PgUp)            49  C9 */
	PC_KEYB_HELPER( 0x0400, "KP -",         KEYCODE_MINUS_PAD,  CODE_NONE )     /* Keypad -                    4A  CA */
	PC_KEYB_HELPER( 0x0800, "KP 4 (Left)",  KEYCODE_4_PAD,      KEYCODE_LEFT )  /* Keypad 4  (Left arrow)      4B  CB */
	PC_KEYB_HELPER( 0x1000, "KP 5",         KEYCODE_5_PAD,      CODE_NONE )     /* Keypad 5                    4C  CC */
	PC_KEYB_HELPER( 0x2000, "KP 6 (Right)", KEYCODE_6_PAD,      KEYCODE_RIGHT ) /* Keypad 6  (Right arrow)     4D  CD */
	PC_KEYB_HELPER( 0x4000, "KP +",         KEYCODE_PLUS_PAD,   CODE_NONE )     /* Keypad +                    4E  CE */
	PC_KEYB_HELPER( 0x8000, "KP 1 (End)",   KEYCODE_1_PAD,      KEYCODE_END )   /* Keypad 1  (End)             4F  CF */
		
	PORT_START	/* IN9 */
	PC_KEYB_HELPER( 0x0001, "KP 2 (Down)",  KEYCODE_2_PAD,      KEYCODE_DOWN )   /* Keypad 2  (Down arrow)      50  D0 */
	PC_KEYB_HELPER( 0x0002, "KP 3 (PgDn)",  KEYCODE_3_PAD,      KEYCODE_PGDN )   /* Keypad 3  (PgDn)            51  D1 */
	PC_KEYB_HELPER( 0x0004, "KP 0 (Ins)",   KEYCODE_0_PAD,      KEYCODE_INSERT ) /* Keypad 0  (Ins)             52  D2 */
	PC_KEYB_HELPER( 0x0008, "KP . (Del)",   KEYCODE_DEL_PAD,    KEYCODE_DEL )    /* Keypad .  (Del)             53  D3 */
	PORT_BIT ( 0x0030, 0x0000, IPT_UNUSED )
	PC_KEYB_HELPER( 0x0040, "(84/102)\\",   KEYCODE_BACKSLASH2, CODE_NONE )      /* Backslash 2                 56  D6 */
	PORT_BIT ( 0xff80, 0x0000, IPT_UNUSED )
		
	PORT_START	/* IN10 */
	PORT_BIT ( 0xffff, 0x0000, IPT_UNUSED )
		
	PORT_START	/* IN11 */
	PORT_BIT ( 0xffff, 0x0000, IPT_UNUSED )
INPUT_PORTS_END



#define AT_KEYB_HELPER(bit, text, key1) \
	PORT_BIT( bit, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(text) PORT_CODE(key1)

INPUT_PORTS_START( at_keyboard )
	PORT_START	/* IN4 */
	PORT_BIT ( 0x0001, 0x0000, IPT_UNUSED ) 	/* unused scancode 0 */
	AT_KEYB_HELPER( 0x0002, "Esc",          KEYCODE_ESC         ) /* Esc                         01  81 */
	AT_KEYB_HELPER( 0x0004, "1 !",          KEYCODE_1           ) /* 1                           02  82 */
	AT_KEYB_HELPER( 0x0008, "2 @",          KEYCODE_2           ) /* 2                           03  83 */
	AT_KEYB_HELPER( 0x0010, "3 #",          KEYCODE_3           ) /* 3                           04  84 */
	AT_KEYB_HELPER( 0x0020, "4 $",          KEYCODE_4           ) /* 4                           05  85 */
	AT_KEYB_HELPER( 0x0040, "5 %",          KEYCODE_5           ) /* 5                           06  86 */
	AT_KEYB_HELPER( 0x0080, "6 ^",          KEYCODE_6           ) /* 6                           07  87 */
	AT_KEYB_HELPER( 0x0100, "7 &",          KEYCODE_7           ) /* 7                           08  88 */
	AT_KEYB_HELPER( 0x0200, "8 *",          KEYCODE_8           ) /* 8                           09  89 */
	AT_KEYB_HELPER( 0x0400, "9 (",          KEYCODE_9           ) /* 9                           0A  8A */
	AT_KEYB_HELPER( 0x0800, "0 )",          KEYCODE_0           ) /* 0                           0B  8B */
	AT_KEYB_HELPER( 0x1000, "- _",          KEYCODE_MINUS       ) /* -                           0C  8C */
	AT_KEYB_HELPER( 0x2000, "= +",          KEYCODE_EQUALS      ) /* =                           0D  8D */
	AT_KEYB_HELPER( 0x4000, "<--",          KEYCODE_BACKSPACE   ) /* Backspace                   0E  8E */
	AT_KEYB_HELPER( 0x8000, "Tab",          KEYCODE_TAB         ) /* Tab                         0F  8F */
		
	PORT_START	/* IN5 */
	AT_KEYB_HELPER( 0x0001, "Q",            KEYCODE_Q           ) /* Q                           10  90 */
	AT_KEYB_HELPER( 0x0002, "W",            KEYCODE_W           ) /* W                           11  91 */
	AT_KEYB_HELPER( 0x0004, "E",            KEYCODE_E           ) /* E                           12  92 */
	AT_KEYB_HELPER( 0x0008, "R",            KEYCODE_R           ) /* R                           13  93 */
	AT_KEYB_HELPER( 0x0010, "T",            KEYCODE_T           ) /* T                           14  94 */
	AT_KEYB_HELPER( 0x0020, "Y",            KEYCODE_Y           ) /* Y                           15  95 */
	AT_KEYB_HELPER( 0x0040, "U",            KEYCODE_U           ) /* U                           16  96 */
	AT_KEYB_HELPER( 0x0080, "I",            KEYCODE_I           ) /* I                           17  97 */
	AT_KEYB_HELPER( 0x0100, "O",            KEYCODE_O           ) /* O                           18  98 */
	AT_KEYB_HELPER( 0x0200, "P",            KEYCODE_P           ) /* P                           19  99 */
	AT_KEYB_HELPER( 0x0400, "[ {",          KEYCODE_OPENBRACE   ) /* [                           1A  9A */
	AT_KEYB_HELPER( 0x0800, "] }",          KEYCODE_CLOSEBRACE  ) /* ]                           1B  9B */
	AT_KEYB_HELPER( 0x1000, "Enter",        KEYCODE_ENTER       ) /* Enter                       1C  9C */
	AT_KEYB_HELPER( 0x2000, "L-Ctrl",       KEYCODE_LCONTROL    ) /* Left Ctrl                   1D  9D */
	AT_KEYB_HELPER( 0x4000, "A",            KEYCODE_A           ) /* A                           1E  9E */
	AT_KEYB_HELPER( 0x8000, "S",            KEYCODE_S           ) /* S                           1F  9F */
		
	PORT_START	/* IN6 */
	AT_KEYB_HELPER( 0x0001, "D",            KEYCODE_D           ) /* D                           20  A0 */
	AT_KEYB_HELPER( 0x0002, "F",            KEYCODE_F           ) /* F                           21  A1 */
	AT_KEYB_HELPER( 0x0004, "G",            KEYCODE_G           ) /* G                           22  A2 */
	AT_KEYB_HELPER( 0x0008, "H",            KEYCODE_H           ) /* H                           23  A3 */
	AT_KEYB_HELPER( 0x0010, "J",            KEYCODE_J           ) /* J                           24  A4 */
	AT_KEYB_HELPER( 0x0020, "K",            KEYCODE_K           ) /* K                           25  A5 */
	AT_KEYB_HELPER( 0x0040, "L",            KEYCODE_L           ) /* L                           26  A6 */
	AT_KEYB_HELPER( 0x0080, "; :",          KEYCODE_COLON       ) /* ;                           27  A7 */
	AT_KEYB_HELPER( 0x0100, "' \"",         KEYCODE_QUOTE       ) /* '                           28  A8 */
	AT_KEYB_HELPER( 0x0200, "` ~",          KEYCODE_TILDE       ) /* `                           29  A9 */
	AT_KEYB_HELPER( 0x0400, "L-Shift",      KEYCODE_LSHIFT      ) /* Left Shift                  2A  AA */
	AT_KEYB_HELPER( 0x0800, "\\ |",         KEYCODE_BACKSLASH   ) /* \                           2B  AB */
	AT_KEYB_HELPER( 0x1000, "Z",            KEYCODE_Z           ) /* Z                           2C  AC */
	AT_KEYB_HELPER( 0x2000, "X",            KEYCODE_X           ) /* X                           2D  AD */
	AT_KEYB_HELPER( 0x4000, "C",            KEYCODE_C           ) /* C                           2E  AE */
	AT_KEYB_HELPER( 0x8000, "V",            KEYCODE_V           ) /* V                           2F  AF */
		
	PORT_START	/* IN7 */
	AT_KEYB_HELPER( 0x0001, "B",            KEYCODE_B           ) /* B                           30  B0 */
	AT_KEYB_HELPER( 0x0002, "N",            KEYCODE_N           ) /* N                           31  B1 */
	AT_KEYB_HELPER( 0x0004, "M",            KEYCODE_M           ) /* M                           32  B2 */
	AT_KEYB_HELPER( 0x0008, ", <",          KEYCODE_COMMA       ) /* ,                           33  B3 */
	AT_KEYB_HELPER( 0x0010, ". >",          KEYCODE_STOP        ) /* .                           34  B4 */
	AT_KEYB_HELPER( 0x0020, "/ ?",          KEYCODE_SLASH       ) /* /                           35  B5 */
	AT_KEYB_HELPER( 0x0040, "R-Shift",      KEYCODE_RSHIFT      ) /* Right Shift                 36  B6 */
	AT_KEYB_HELPER( 0x0080, "KP * (PrtScr)",KEYCODE_ASTERISK    ) /* Keypad *  (PrtSc)           37  B7 */
	AT_KEYB_HELPER( 0x0100, "Alt",          KEYCODE_LALT        ) /* Left Alt                    38  B8 */
	AT_KEYB_HELPER( 0x0200, "Space",        KEYCODE_SPACE       ) /* Space                       39  B9 */
	AT_KEYB_HELPER( 0x0400, "Caps",         KEYCODE_CAPSLOCK    ) /* Caps Lock                   3A  BA */
	AT_KEYB_HELPER( 0x0800, "F1",           KEYCODE_F1          ) /* F1                          3B  BB */
	AT_KEYB_HELPER( 0x1000, "F2",           KEYCODE_F2          ) /* F2                          3C  BC */
	AT_KEYB_HELPER( 0x2000, "F3",           KEYCODE_F3          ) /* F3                          3D  BD */
	AT_KEYB_HELPER( 0x4000, "F4",           KEYCODE_F4          ) /* F4                          3E  BE */
	AT_KEYB_HELPER( 0x8000, "F5",           KEYCODE_F5          ) /* F5                          3F  BF */
		
	PORT_START	/* IN8 */
	AT_KEYB_HELPER( 0x0001, "F6",           KEYCODE_F6          ) /* F6                          40  C0 */
	AT_KEYB_HELPER( 0x0002, "F7",           KEYCODE_F7          ) /* F7                          41  C1 */
	AT_KEYB_HELPER( 0x0004, "F8",           KEYCODE_F8          ) /* F8                          42  C2 */
	AT_KEYB_HELPER( 0x0008, "F9",           KEYCODE_F9          ) /* F9                          43  C3 */
	AT_KEYB_HELPER( 0x0010, "F10",          KEYCODE_F10         ) /* F10                         44  C4 */
	AT_KEYB_HELPER( 0x0020, "NumLock",      KEYCODE_NUMLOCK     ) /* Num Lock                    45  C5 */
	AT_KEYB_HELPER( 0x0040, "ScrLock",      KEYCODE_SCRLOCK     ) /* Scroll Lock                 46  C6 */
	AT_KEYB_HELPER( 0x0080, "KP 7 (Home)",  KEYCODE_7_PAD       ) /* Keypad 7  (Home)            47  C7 */
	AT_KEYB_HELPER( 0x0100, "KP 8 (Up)",    KEYCODE_8_PAD       ) /* Keypad 8  (Up arrow)        48  C8 */
	AT_KEYB_HELPER( 0x0200, "KP 9 (PgUp)",  KEYCODE_9_PAD       ) /* Keypad 9  (PgUp)            49  C9 */
	AT_KEYB_HELPER( 0x0400, "KP -",         KEYCODE_MINUS_PAD   ) /* Keypad -                    4A  CA */
	AT_KEYB_HELPER( 0x0800, "KP 4 (Left)",  KEYCODE_4_PAD       ) /* Keypad 4  (Left arrow)      4B  CB */
	AT_KEYB_HELPER( 0x1000, "KP 5",         KEYCODE_5_PAD       ) /* Keypad 5                    4C  CC */
	AT_KEYB_HELPER( 0x2000, "KP 6 (Right)", KEYCODE_6_PAD       ) /* Keypad 6  (Right arrow)     4D  CD */
	AT_KEYB_HELPER( 0x4000, "KP +",         KEYCODE_PLUS_PAD    ) /* Keypad +                    4E  CE */
	AT_KEYB_HELPER( 0x8000, "KP 1 (End)",   KEYCODE_1_PAD       ) /* Keypad 1  (End)             4F  CF */
		
	PORT_START	/* IN9 */
	AT_KEYB_HELPER( 0x0001, "KP 2 (Down)",  KEYCODE_2_PAD       ) /* Keypad 2  (Down arrow)      50  D0 */
	AT_KEYB_HELPER( 0x0002, "KP 3 (PgDn)",  KEYCODE_3_PAD       ) /* Keypad 3  (PgDn)            51  D1 */
	AT_KEYB_HELPER( 0x0004, "KP 0 (Ins)",   KEYCODE_0_PAD       ) /* Keypad 0  (Ins)             52  D2 */
	AT_KEYB_HELPER( 0x0008, "KP . (Del)",   KEYCODE_DEL_PAD     ) /* Keypad .  (Del)             53  D3 */
	PORT_BIT ( 0x0030, 0x0000, IPT_UNUSED )
	AT_KEYB_HELPER( 0x0040, "(84/102)\\",   KEYCODE_BACKSLASH2  ) /* Backslash 2                 56  D6 */
	AT_KEYB_HELPER( 0x0080, "(MF2)F11",		KEYCODE_F11         ) /* F11                         57  D7 */
	AT_KEYB_HELPER( 0x0100, "(MF2)F12",		KEYCODE_F12         ) /* F12                         58  D8 */
	PORT_BIT ( 0xfe00, 0x0000, IPT_UNUSED )
		
	PORT_START	/* IN10 */
	AT_KEYB_HELPER( 0x0001, "(MF2)KP Enter",		KEYCODE_ENTER_PAD   ) /* PAD Enter                   60  e0 */
	AT_KEYB_HELPER( 0x0002, "(MF2)Right Control",	KEYCODE_RCONTROL    ) /* Right Control               61  e1 */
	AT_KEYB_HELPER( 0x0004, "(MF2)KP /",			KEYCODE_SLASH_PAD   ) /* PAD Slash                   62  e2 */
	AT_KEYB_HELPER( 0x0008, "(MF2)PRTSCR",			KEYCODE_PRTSCR      ) /* Print Screen                63  e3 */
	AT_KEYB_HELPER( 0x0010, "(MF2)ALTGR",			KEYCODE_RALT        ) /* ALTGR                       64  e4 */
	AT_KEYB_HELPER( 0x0020, "(MF2)Home",			KEYCODE_HOME        ) /* Home                        66  e6 */
	AT_KEYB_HELPER( 0x0040, "(MF2)Cursor Up",		KEYCODE_UP          ) /* Up                          67  e7 */
	AT_KEYB_HELPER( 0x0080, "(MF2)Page Up",			KEYCODE_PGUP        ) /* Page Up                     68  e8 */
	AT_KEYB_HELPER( 0x0100, "(MF2)Cursor Left",		KEYCODE_LEFT        ) /* Left                        69  e9 */
	AT_KEYB_HELPER( 0x0200, "(MF2)Cursor Right",	KEYCODE_RIGHT       ) /* Right                       6a  ea */
	AT_KEYB_HELPER( 0x0400, "(MF2)End",				KEYCODE_END         ) /* End                         6b  eb */
	AT_KEYB_HELPER( 0x0800, "(MF2)Cursor Down",		KEYCODE_DOWN        ) /* Down                        6c  ec */
	AT_KEYB_HELPER( 0x1000, "(MF2)Page Down",		KEYCODE_PGDN        ) /* Page Down                   6d  ed */
	AT_KEYB_HELPER( 0x2000, "(MF2)Insert",			KEYCODE_INSERT      ) /* Insert                      6e  ee */
	AT_KEYB_HELPER( 0x4000, "(MF2)Delete",			KEYCODE_DEL         ) /* Delete                      6f  ef */
	AT_KEYB_HELPER( 0x8000, "(MF2)Pause",			KEYCODE_PAUSE       ) /* Pause                       65  e5 */
	PORT_START	/* IN11 */
	AT_KEYB_HELPER( 0x0001, "Print Screen", KEYCODE_PRTSCR           ) /* Print Screen alternate      77  f7 */
	PORT_BIT ( 0xfffe, 0x0000, IPT_UNUSED )
INPUT_PORTS_END



/***************************************************************************
  Inputx stuff
***************************************************************************/

ACCEPT_CHAR( at_keyboard )
{
	return unicode_char_to_at_keycode(ch) != 0;
}



CHARQUEUE_EMPTY( at_keyboard )
{
	return at_keyboard_queue_size() == 0;
}

