'******************************************************************************
'* 
'* KEYCODE CONVERSION TOOLS (virtual keys to XT/AT scancodes)
'* 
'******************************************************************************

dim i as integer, i64 as int64, b as byte

'------------------------- XT scancodes (Set 1) -------------------------------

//Convert virtual keycode to XT scancode
function XTKeyCode(Src as byte, byref Dst as byte) as byte
 result=1        : select case Src
 case VK_BACK    : Dst=0x0E //BackSpace
 case VK_TAB 	 : Dst=0x0F //Tabulation
 case VK_RETURN  : Dst=0x1C //Enter
 case VK_PAUSE   : Dst=0x54 //Pause
 case VK_CAPITAL : Dst=0x3A //CapsLock
 case VK_ESCAPE  : Dst=0x01 //Escape
 case VK_SPACE   : Dst=0x39 //Space
 case VK_PAGEUP  : Dst=0x49 //Page Up
 case VK_PAGEDN  : Dst=0x51 //Page Down
 case VK_END     : Dst=0x4F //End
 case VK_HOME    : Dst=0x47 //Home
 case VK_LEFT    : Dst=0x4B //Left
 case VK_UP 	 : Dst=0x48 //Up
 case VK_RIGHT   : Dst=0x4D //Right
 case VK_DOWN  	 : Dst=0x50 //Down
 case VK_INSERT  : Dst=0x52 //Insert
 case VK_DELETE  : Dst=0x53 //Delete
 case VK_PRNSCR  : Dst=0x37 //PrintScreen
 case VK_0 	 : Dst=0x0B //0
 case VK_1 	 : Dst=0x02 //1
 case VK_2 	 : Dst=0x03 //2
 case VK_3 	 : Dst=0x04 //3
 case VK_4 	 : Dst=0x05 //4
 case VK_5 	 : Dst=0x06 //5
 case VK_6 	 : Dst=0x07 //6
 case VK_7 	 : Dst=0x08 //7
 case VK_8 	 : Dst=0x09 //8
 case VK_9 	 : Dst=0x0A //9
 case VK_A 	 : Dst=0x1E //A
 case VK_B 	 : Dst=0x30 //B
 case VK_C 	 : Dst=0x2E //C
 case VK_D 	 : Dst=0x20 //D
 case VK_E 	 : Dst=0x12 //E
 case VK_F 	 : Dst=0x21 //F
 case VK_G 	 : Dst=0x22 //G
 case VK_H 	 : Dst=0x23 //H
 case VK_I 	 : Dst=0x17 //I
 case VK_J 	 : Dst=0x24 //J
 case VK_K 	 : Dst=0x25 //K
 case VK_L 	 : Dst=0x26 //L
 case VK_M 	 : Dst=0x32 //M
 case VK_N 	 : Dst=0x31 //N
 case VK_O 	 : Dst=0x18 //O
 case VK_P 	 : Dst=0x19 //P
 case VK_Q 	 : Dst=0x10 //Q
 case VK_R 	 : Dst=0x13 //R
 case VK_S 	 : Dst=0x1F //S
 case VK_T 	 : Dst=0x14 //T
 case VK_U 	 : Dst=0x16 //U
 case VK_V 	 : Dst=0x2F //V
 case VK_W 	 : Dst=0x11 //W
 case VK_X 	 : Dst=0x2D //X
 case VK_Y  	 : Dst=0x15 //Y
 case VK_Z 	 : Dst=0x2C //Z
 case VK_NUMPAD0 : Dst=0x52 //Numpad 0
 case VK_NUMPAD1 : Dst=0x4F //Numpad 1
 case VK_NUMPAD2 : Dst=0x50 //Numpad 2
 case VK_NUMPAD3 : Dst=0x51 //Numpad 3
 case VK_NUMPAD4 : Dst=0x4B //Numpad 4
 case VK_NUMPAD5 : Dst=0x4C //Numpad 5
 case VK_NUMPAD6 : Dst=0x4D //Numpad 6
 case VK_NUMPAD7 : Dst=0x47 //Numpad 7
 case VK_NUMPAD8 : Dst=0x48 //Numpad 8
 case VK_NUMPAD9 : Dst=0x49 //Numpad 9
 case VK_DECIMAL : Dst=0x53 //Numpad . 
 case VK_MULTIPLY: Dst=0x37 //Gray *
 case VK_ADD     : Dst=0x4E //Gray +
 case VK_EXTRETURN: Dst=0x1C //Gray Enter
 case VK_SUBTRACT: Dst=0x4A //Gray -
 case VK_DIVIDE  : Dst=0x35 //Gray /
 case VK_F1 	 : Dst=0x3B //F1
 case VK_F2 	 : Dst=0x3C //F2
 case VK_F3 	 : Dst=0x3D //F3
 case VK_F4 	 : Dst=0x3E //F4
 case VK_F5 	 : Dst=0x3F //F5
 case VK_F6 	 : Dst=0x40 //F6
 case VK_F7 	 : Dst=0x41 //F7
 case VK_F8 	 : Dst=0x42 //F8
 case VK_F9 	 : Dst=0x43 //F9
 case VK_F10 	 : Dst=0x44 //F10
 case VK_NUMLOCK : Dst=0x45 //NumLock
 case VK_SCROLL  : Dst=0x46 //ScrollLock 
 case VK_LSHIFT  : Dst=0x2A //Left Shift
 case VK_RSHIFT  : Dst=0x36 //Right Shift
 case VK_LCTRL   : Dst=0x1D //Control
 case VK_RCTRL   : Dst=0x1D //Control
 case VK_LALT    : Dst=0x38 //Alt
 case VK_RALT    : Dst=0x38 //Alt
 case VK_MINUS   : Dst=0x0C //Minus/Underline
 case VK_PLUS    : Dst=0x0D //Plus/Equal
 case VK_LBRACKET: Dst=0x1A //Left/Open Bracket
 case VK_RBRACKET: Dst=0x1B //Right/Close Bracket
 case VK_COLON   : Dst=0x27 //Colon
 case VK_COMMA   : Dst=0x33 //Comma
 case VK_PERIOD  : Dst=0x34 //Period
 case VK_BACK_SLASH: Dst=0x2B //Back Slash
 case VK_SLASH   : Dst=0x35 //Slash
 case VK_QUOTE   : Dst=0x28 //Quote
 case VK_BACK_QUOTE: Dst=0x29 //Back Quote
 case else       : result=0 : end
end

//Generate XT key conversion tables
public dim XTKeyDown(256,2) as int64 'pressed scancode and size
public dim XTKeyUp(256,2) as int64 'released scancode and size
for i=0 to 255 
 XTKeyDown(i,1)=XTKeyCode(i,b) : XTKeyUp(i,1)=XTKeyDown(i,1)
 XTKeyDown(i,0)=b : XTKeyUp(i,0)=b or 0x80
next

'------------------------- AT scancodes (Set 1 Extended) ----------------------

//Convert virtual keycode to AT scancode
function ATKeyCode(Src as byte, byref Dst as int64, pressed as boolean) as byte
 result=1 : dst=0 : select case Src
 case VK_BACK    : Dst=0x0E //BackSpace
 case VK_TAB 	 : Dst=0x0F //Tabulation
 case VK_RETURN  : Dst=0x1C //Enter
 case VK_PAUSE   : Dst=iif(pressed,0xC59DE1451DE1,0) //Pause (no released code)
 case VK_CAPITAL : Dst=0x3A //CapsLock
 case VK_ESCAPE  : Dst=0x01 //Escape
 case VK_SPACE   : Dst=0x39 //Space
 case VK_PAGEUP  : Dst=iif(pressed,0x49E0,0x49E0 or 0x8000) //Page Up
 case VK_PAGEDN  : Dst=iif(pressed,0x51E0,0x51E0 or 0x8000) //Page Down
 case VK_END     : Dst=iif(pressed,0x4FE0,0x4FE0 or 0x8000) //End
 case VK_HOME    : Dst=iif(pressed,0x47E0,0x47E0 or 0x8000) //Home
 case VK_LEFT    : Dst=iif(pressed,0x4BE0,0x4BE0 or 0x8000) //Left
 case VK_UP 	 : Dst=iif(pressed,0x48E0,0x48E0 or 0x8000) //Up
 case VK_RIGHT   : Dst=iif(pressed,0x4DE0,0x4DE0 or 0x8000) //Right
 case VK_DOWN  	 : Dst=iif(pressed,0x50E0,0x50E0 or 0x8000) //Down
 case VK_INSERT  : Dst=iif(pressed,0x52E0,0x52E0 or 0x8000) //Insert
 case VK_DELETE  : Dst=iif(pressed,0x53E0,0x53E0 or 0x8000) //Delete
 case VK_PRNSCR  : Dst=iif(pressed,0x37E02AE0,0xAAE0B7E0) //PrintScreen
 case VK_0 	 : Dst=0x0B //0
 case VK_1 	 : Dst=0x02 //1
 case VK_2 	 : Dst=0x03 //2
 case VK_3 	 : Dst=0x04 //3
 case VK_4 	 : Dst=0x05 //4
 case VK_5 	 : Dst=0x06 //5
 case VK_6 	 : Dst=0x07 //6
 case VK_7 	 : Dst=0x08 //7
 case VK_8 	 : Dst=0x09 //8
 case VK_9 	 : Dst=0x0A //9
 case VK_A 	 : Dst=0x1E //A
 case VK_B 	 : Dst=0x30 //B
 case VK_C 	 : Dst=0x2E //C
 case VK_D 	 : Dst=0x20 //D
 case VK_E 	 : Dst=0x12 //E
 case VK_F 	 : Dst=0x21 //F
 case VK_G 	 : Dst=0x22 //G
 case VK_H 	 : Dst=0x23 //H
 case VK_I 	 : Dst=0x17 //I
 case VK_J 	 : Dst=0x24 //J
 case VK_K 	 : Dst=0x25 //K
 case VK_L 	 : Dst=0x26 //L
 case VK_M 	 : Dst=0x32 //M
 case VK_N 	 : Dst=0x31 //N
 case VK_O 	 : Dst=0x18 //O
 case VK_P 	 : Dst=0x19 //P
 case VK_Q 	 : Dst=0x10 //Q
 case VK_R 	 : Dst=0x13 //R
 case VK_S 	 : Dst=0x1F //S
 case VK_T 	 : Dst=0x14 //T
 case VK_U 	 : Dst=0x16 //U
 case VK_V 	 : Dst=0x2F //V
 case VK_W 	 : Dst=0x11 //W
 case VK_X 	 : Dst=0x2D //X
 case VK_Y  	 : Dst=0x15 //Y
 case VK_Z 	 : Dst=0x2C //Z
 case VK_NUMPAD0 : Dst=0x52 //Numpad 0
 case VK_NUMPAD1 : Dst=0x4F //Numpad 1
 case VK_NUMPAD2 : Dst=0x50 //Numpad 2
 case VK_NUMPAD3 : Dst=0x51 //Numpad 3
 case VK_NUMPAD4 : Dst=0x4B //Numpad 4
 case VK_NUMPAD5 : Dst=0x4C //Numpad 5
 case VK_NUMPAD6 : Dst=0x4D //Numpad 6
 case VK_NUMPAD7 : Dst=0x47 //Numpad 7
 case VK_NUMPAD8 : Dst=0x48 //Numpad 8
 case VK_NUMPAD9 : Dst=0x49 //Numpad 9
 case VK_DECIMAL : Dst=0x53 //Numpad .
 case VK_MULTIPLY: Dst=0x37 //Gray *
 case VK_ADD     : Dst=0x4E //Gray +
 case VK_EXTRETURN: Dst=iif(pressed,0x1CE0,0x1CE0 or 0x8000) //Gray Enter
 case VK_SUBTRACT: Dst=0x4A //Gray -
 case VK_DIVIDE  : Dst=iif(pressed,0x35E0,0x35E0 or 0x8000) //Gray /
 case VK_F1 	 : Dst=0x3B //F1
 case VK_F2 	 : Dst=0x3C //F2
 case VK_F3 	 : Dst=0x3D //F3
 case VK_F4 	 : Dst=0x3E //F4
 case VK_F5 	 : Dst=0x3F //F5
 case VK_F6 	 : Dst=0x40 //F6
 case VK_F7 	 : Dst=0x41 //F7
 case VK_F8 	 : Dst=0x42 //F8
 case VK_F9 	 : Dst=0x43 //F9
 case VK_F10 	 : Dst=0x44 //F10
 case VK_NUMLOCK : Dst=0x45 //NumLock
 case VK_SCROLL  : Dst=0x46 //ScrollLock 
 case VK_LSHIFT  : Dst=0x2A //Left Shift
 case VK_RSHIFT  : Dst=0x36 //Right Shift
 case VK_LCTRL   : Dst=0x1D //Left Control
 case VK_RCTRL   : Dst=iif(pressed,0x1DE0,0x1DE0 or 0x8000) //Right Control
 case VK_LALT    : Dst=0x38 //Left Alt
 case VK_RALT    : Dst=iif(pressed,0x38E0,0x38E0 or 0x8000) //Right Alt
 case VK_MINUS   : Dst=0x0C //Minus/Underline
 case VK_PLUS    : Dst=0x0D //Plus/Equal
 case VK_LBRACKET: Dst=0x1A //Left/Open Bracket
 case VK_RBRACKET: Dst=0x1B //Right/Close Bracket
 case VK_COLON   : Dst=0x27 //Colon
 case VK_COMMA   : Dst=0x33 //Comma
 case VK_PERIOD  : Dst=0x34 //Period
 case VK_BACK_SLASH: Dst=0x2B //Back Slash
 case VK_SLASH   : Dst=0x35 //Slash
 case VK_QUOTE   : Dst=0x28 //Quote
 case VK_BACK_QUOTE: Dst=0x29 //Back Quote
 case else       : result=0 : end
 //detect scancode size
 if result>0 then : result=8
   if (not pressed) and (shr(dst,8)=0) then dst=dst or 0x80 'ordinary key released
   dim i as integer, i64 as int64 : i64=Dst : for i=1 to 8 
   if (i64 and 0xFF00000000000000)=0 then result=result-1 else exit
   i64=shl(i64,8) : next 
 end if
end

//Generate AT key conversion tables
public dim ATKeyDown(256,2) as int64 'pressed scancode and size
public dim ATKeyUp(256,2) as int64 'released scancode and size
for i=0 to 255 
 ATKeyDown(i,1)=ATKeyCode(i,i64,true) : ATKeyDown(i,0)=i64
 ATKeyUp(i,1)=ATKeyCode(i,i64,false) : ATKeyUp(i,0)=i64
next