'*****************************************************************************
'* 
'* VARIOUS TOOLS, USEFUL IN MAIN BIOS EMULATION
'*
'*****************************************************************************

//DEBUG.ON 'uncomment to enable debug messages (can be slow for hi-freq events)

'/////////////////////////////// KEYBOARD ////////////////////////////////////

//State constants
const XT_CTRL as byte=0x4
const XT_ALT as byte=0x8
const XT_SHIFT as byte=0x3
const XT_CAPS as byte=0x40
const XT_NUM as byte=0x20
const XT_SCROLL as byte=0x80

//Convert XT scancode to ASCII
public function ConvertXTScanCode(Src as byte, SKeys as word, ECode as word, _
  byref Dst as word) as boolean
 //Convert keys, which depend on mode flags (and ignore others)
 //CTRL keys //TODO - other keys
 if (SKeys and XT_CTRL)<>0 then
 result=true : select case Src 
 case 0x0E: Dst=0x0E7F //CTRL+BackSpace
 case 0x1C: Dst=iif(ECode=0xE0,0x1C0A,0x1C0A) 'CTRL+Enter/Gray Enter
 case 0x4F: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x7500,0x7633) 'CTRL+End/CTRL+Num1
 case 0x51: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x7600,0x7633) 'CTRL+PgDn/CTRL+Num3
 case 0x4B: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x7300,0x7334) 'CTRL+Left/CTRL+Num4
 case 0x4D: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x7400,0x7436) 'CTRL+Right/CTRL+Num6
 case 0x47: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x7700,0x7737) 'CTRL+Home/CTRL+Num7
 case 0x49: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x8400,0x8439) 'CTRL+PgUp/CTRL+Num9
 case 0x1E : Dst=0x1E01 //CTRL+A
 case 0x30 : Dst=0x3002 //CTRL+B
 case 0x2E : Dst=0x2E03 //CTRL+C
 case 0x20 : Dst=0x2004 //CTRL+D
 case 0x12 : Dst=0x1205 //CTRL+E
 case 0x21 : Dst=0x2106 //CTRL+F
 case 0x22 : Dst=0x2207 //CTRL+G
 case 0x23 : Dst=0x2308 //CTRL+H
 case 0x17 : Dst=0x1709 //CTRL+I
 case 0x24 : Dst=0x240A //CTRL+J
 case 0x25 : Dst=0x250B //CTRL+K
 case 0x26 : Dst=0x260C //CTRL+L
 case 0x32 : Dst=0x320D //CTRL+M
 case 0x31 : Dst=0x310E //CTRL+N
 case 0x18 : Dst=0x180F //CTRL+O
 case 0x19 : Dst=0x1910 //CTRL+P
 case 0x10 : Dst=0x1011 //CTRL+Q
 case 0x13 : Dst=0x1312 //CTRL+R
 case 0x1F : Dst=0x1F13 //CTRL+S
 case 0x14 : Dst=0x1414 //CTRL+T
 case 0x16 : Dst=0x1615 //CTRL+U
 case 0x2F : Dst=0x2F16 //CTRL+V    
 case 0x11 : Dst=0x1117 //CTRL+W
 case 0x2D : Dst=0x2D18 //CTRL+X
 case 0x15 : Dst=0x1519 //CTRL+Y
 case 0x2C : Dst=0x2C1A //CTRL+Z
 case 0x3B : Dst=0x5E00 //CTRL+F1
 case 0x3C : Dst=0x5F00 //CTRL+F2
 case 0x3D : Dst=0x6000 //CTRL+F3
 case 0x3E : Dst=0x6100 //CTRL+F4
 case 0x3F : Dst=0x6200 //CTRL+F5
 case 0x40 : Dst=0x6300 //CTRL+F6
 case 0x41 : Dst=0x6400 //CTRL+F7
 case 0x42 : Dst=0x6500 //CTRL+F8
 case 0x43 : Dst=0x6600 //CTRL+F9
 case 0x44 : Dst=0x6700 //CTRL+F10
 case 0x0C : Dst=0x0C1F //CTRL+Minus
 case 0x1A : Dst=0x1A1B //CTRL+Open Bracket
 case 0x1B : Dst=0x1B1D //CTRL+Close Bracket
 case 0x2B : Dst=0x2B1C //CTRL+Back Slash
 case else : result=false : end 
 if result then exit : end if
 //ALT keys //TODO - other keys
 if (SKeys and XT_ALT)<>0 then
 result=true : select case Src 
 case 0x0B : Dst=0x7800 //ALT+0
 case 0x02 : Dst=0x7900 //ALT+1
 case 0x03 : Dst=0x7A00 //ALT+2
 case 0x04 : Dst=0x7B00 //ALT+3
 case 0x05 : Dst=0x7C00 //ALT+4
 case 0x06 : Dst=0x7D00 //ALT+5
 case 0x07 : Dst=0x7E00 //ALT+6
 case 0x08 : Dst=0x7F00 //ALT+7
 case 0x09 : Dst=0x8000 //ALT+8
 case 0x0A : Dst=0x8100 //ALT+9
 case 0x1E : Dst=0x1E00 //ALT+A
 case 0x30 : Dst=0x3000 //ALT+B
 case 0x2E : Dst=0x2E00 //ALT+C
 case 0x20 : Dst=0x2000 //ALT+D
 case 0x12 : Dst=0x1200 //ALT+E
 case 0x21 : Dst=0x2100 //ALT+F
 case 0x22 : Dst=0x2200 //ALT+G
 case 0x23 : Dst=0x2300 //ALT+H
 case 0x17 : Dst=0x1700 //ALT+I
 case 0x24 : Dst=0x2400 //ALT+J
 case 0x25 : Dst=0x2500 //ALT+K
 case 0x26 : Dst=0x2600 //ALT+L
 case 0x32 : Dst=0x3200 //ALT+M
 case 0x31 : Dst=0x3100 //ALT+N
 case 0x18 : Dst=0x1800 //ALT+O
 case 0x19 : Dst=0x1900 //ALT+P
 case 0x10 : Dst=0x1000 //ALT+Q
 case 0x13 : Dst=0x1300 //ALT+R
 case 0x1F : Dst=0x1F00 //ALT+S
 case 0x14 : Dst=0x1400 //ALT+T
 case 0x16 : Dst=0x1600 //ALT+U
 case 0x2F : Dst=0x2F00 //ALT+V    
 case 0x11 : Dst=0x1100 //ALT+W
 case 0x2D : Dst=0x2D00 //ALT+X
 case 0x15 : Dst=0x1500 //ALT+Y
 case 0x2C : Dst=0x2C00 //ALT+Z
 case 0x3B : Dst=0x6800 //ALT+F1
 case 0x3C : Dst=0x6900 //ALT+F2
 case 0x3D : Dst=0x6A00 //ALT+F3
 case 0x3E : Dst=0x6B00 //ALT+F4
 case 0x3F : Dst=0x6C00 //ALT+F5
 case 0x40 : Dst=0x6D00 //ALT+F6
 case 0x41 : Dst=0x6E00 //ALT+F7
 case 0x42 : Dst=0x6F00 //ALT+F8
 case 0x43 : Dst=0x7000 //ALT+F9
 case 0x44 : Dst=0x7100 //ALT+F10
 case 0x0C : Dst=0x8200 //ALT+Minus
 case 0x0D : Dst=0x8300 //ALT+Equal
 case else : result=false : end 
 if result then exit : end if
 //CAPITAL letters (CAPS or SHIFT)
 if ((SKeys and XT_CAPS)<>0) or ((SKeys and XT_SHIFT)<>0) then
 result=true : select case Src 
 case 0x1E : Dst=0x1E41 //A
 case 0x30 : Dst=0x3042 //B
 case 0x2E : Dst=0x2E43 //C
 case 0x20 : Dst=0x2044 //D
 case 0x12 : Dst=0x1245 //E
 case 0x21 : Dst=0x2146 //F
 case 0x22 : Dst=0x2247 //G
 case 0x23 : Dst=0x2348 //H
 case 0x17 : Dst=0x1749 //I
 case 0x24 : Dst=0x244A //J
 case 0x25 : Dst=0x254B //K
 case 0x26 : Dst=0x264C //L
 case 0x32 : Dst=0x324D //M
 case 0x31 : Dst=0x314E //N
 case 0x18 : Dst=0x184F //O
 case 0x19 : Dst=0x1950 //P
 case 0x10 : Dst=0x1051 //Q
 case 0x13 : Dst=0x1352 //R
 case 0x1F : Dst=0x1F53 //S
 case 0x14 : Dst=0x1454 //T
 case 0x16 : Dst=0x1655 //U
 case 0x2F : Dst=0x2F56 //V    
 case 0x11 : Dst=0x1157 //W
 case 0x2D : Dst=0x2D58 //X
 case 0x15 : Dst=0x1559 //Y
 case 0x2C : Dst=0x2C5A //Z
 case else : result=false : end 
 if result then exit : end if
 //UPPER case (SHIFT)
 if (SKeys and XT_SHIFT)<>0 then
 result=true : select case Src  
 case 0x0F: Dst=0x0F00 //Tabulation
 case 0x0B : Dst=0x0B29 //)
 case 0x02 : Dst=0x0221 //!
 case 0x03 : Dst=0x0340 //@
 case 0x04 : Dst=0x0423 //#
 case 0x05 : Dst=0x0524 //$
 case 0x06 : Dst=0x0625 //%
 case 0x07 : Dst=0x075E //^
 case 0x08 : Dst=0x0826 //&
 case 0x09 : Dst=0x092A //*
 case 0x0A : Dst=0x0A28 //(                      
 case 0x3B : Dst=0x5400 //F1
 case 0x3C : Dst=0x5500 //F2
 case 0x3D : Dst=0x5600 //F3
 case 0x3E : Dst=0x5700 //F4
 case 0x3F : Dst=0x5800 //F5
 case 0x40 : Dst=0x5900 //F6
 case 0x41 : Dst=0x5A00 //F7
 case 0x42 : Dst=0x5B00 //F8
 case 0x43 : Dst=0x5C00 //F9
 case 0x44 : Dst=0x5D00 //F10 
 case 0x0C : Dst=0x0C5F //Underline _
 case 0x0D : Dst=0x0D2B //Plus +
 case 0x1A : Dst=0x1A7B //Open Bracket {
 case 0x1B : Dst=0x1B7D //Close Bracket }
 case 0x27 : Dst=0x273A //Colon :
 case 0x33 : Dst=0x333C //Smaller < 
 case 0x34 : Dst=0x343E //Bigger >
 case 0x2B : Dst=0x2B7C //|
 case 0x35 : Dst=iif(ECode=0xE0,0x352F,0x353F) //?/Gray /
 case 0x28 : Dst=0x2822 //Double quotes "
 case 0x29 : Dst=0x297E //Tilde ~
 case else : result=false : end 
 if result then exit : end if
 //GENERIC conversion (without use of mode state flags)
 result=true : select case Src 
 case 0x0E: Dst=0x0E08 //BackSpace
 case 0x0F: Dst=0x0F09 //Tabulation
 case 0x1C: Dst=iif(ECode=0xE0,0x1C0D,0x1C0D) 'Enter/Gray Enter
 case 0x3A: Dst=0x3A00 //CapsLock
 case 0x01: Dst=0x011B //Escape
 case 0x39: Dst=0x3920 //Space
 case 0x52: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x5200,0x5230) 'Insert/Num0
 case 0x4F: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4F00,0x4F31) 'End/Num1
 case 0x50: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x5000,0x5032) 'Down/Num2
 case 0x51: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x5100,0x5133) 'PgDn/Num3
 case 0x4B: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4B00,0x4B34) 'Left/Num4
 case 0x4C: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4C00,0x4C35) 'Num5
 case 0x4D: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4D00,0x4D36) 'Right/Num6
 case 0x47: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4700,0x4737) 'Home/Num7
 case 0x48: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4800,0x4838) 'Up/Num8
 case 0x49: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4900,0x4939) 'PgUp/Num9
 case 0x53: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x5300,0x532E) 'Delete/Num.
 case 0x4E: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4E2B,0x4E2B) 'Add/Gray +
 case 0x4A: Dst=iif((ECode=0xE0) or ((SKeys and XT_NUM)=0),0x4A2D,0x4A2D) 'Subtract/Gray -
 case 0x37: Dst=iif(ECode=0xE0,0x372A,0x372A) 'Gray *
 case 0x0B : Dst=0x0B30 //0
 case 0x02 : Dst=0x0231 //1
 case 0x03 : Dst=0x0332 //2
 case 0x04 : Dst=0x0433 //3
 case 0x05 : Dst=0x0534 //4
 case 0x06 : Dst=0x0635 //5
 case 0x07 : Dst=0x0736 //6
 case 0x08 : Dst=0x0837 //7
 case 0x09 : Dst=0x0938 //8
 case 0x0A : Dst=0x0A39 //9
 case 0x1E : Dst=0x1E61 //a
 case 0x30 : Dst=0x3062 //b
 case 0x2E : Dst=0x2E63 //c
 case 0x20 : Dst=0x2064 //d
 case 0x12 : Dst=0x1265 //e
 case 0x21 : Dst=0x2166 //f
 case 0x22 : Dst=0x2267 //g
 case 0x23 : Dst=0x2368 //h
 case 0x17 : Dst=0x1769 //i
 case 0x24 : Dst=0x246A //j
 case 0x25 : Dst=0x256B //k
 case 0x26 : Dst=0x266C //l
 case 0x32 : Dst=0x326D //m
 case 0x31 : Dst=0x316E //n
 case 0x18 : Dst=0x186F //o
 case 0x19 : Dst=0x1970 //p
 case 0x10 : Dst=0x1071 //q
 case 0x13 : Dst=0x1372 //r
 case 0x1F : Dst=0x1F73 //s
 case 0x14 : Dst=0x1474 //t
 case 0x16 : Dst=0x1675 //u
 case 0x2F : Dst=0x2F76 //v
 case 0x11 : Dst=0x1177 //w
 case 0x2D : Dst=0x2D78 //x
 case 0x15 : Dst=0x1579 //y
 case 0x2C : Dst=0x2C7A //z
 case 0x3B : Dst=0x3B00 //F1
 case 0x3C : Dst=0x3C00 //F2
 case 0x3D : Dst=0x3D00 //F3
 case 0x3E : Dst=0x3E00 //F4
 case 0x3F : Dst=0x3F00 //F5
 case 0x40 : Dst=0x4000 //F6
 case 0x41 : Dst=0x4100 //F7
 case 0x42 : Dst=0x4200 //F8
 case 0x43 : Dst=0x4300 //F9
 case 0x44 : Dst=0x4400 //F10
 case 0x45 : Dst=0x4500 //NumLock
 case 0x46 : Dst=0x4600 //ScrollLock
 case 0x0C : Dst=0x0C2D //Minus -
 case 0x0D : Dst=0x0D3D //Equal =
 case 0x1A : Dst=0x1A5B //Open Bracket [
 case 0x1B : Dst=0x1B5D //Close Bracket ]
 case 0x27 : Dst=0x273B //Semicolon ;
 case 0x33 : Dst=0x332C //Comma ,
 case 0x34 : Dst=0x342E //Period .
 case 0x2B : Dst=0x2B5C //Back Slash \
 case 0x35 : Dst=iif(ECode=0xE0,0x352F,0x352F) //Slash/Gray /
 case 0x28 : Dst=0x2827 //Quote '
 case 0x29 : Dst=0x2960 //Back Quote `
 case else : result=false : end select
end 
