[NTVDM]: Fix a bug introduced in revision 64324, where I didn't restore the original...
[reactos.git] / reactos / subsystems / ntvdm / bios / bios32 / kbdbios32.c
index 9d95ccd..0782f3e 100644 (file)
@@ -35,18 +35,15 @@ static BOOLEAN BiosKbdBufferPush(WORD Data)
     if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart;
 
     /* If it's full, fail */
-    if (NextElement == Bda->KeybdBufferHead) return FALSE;
+    if (NextElement == Bda->KeybdBufferHead)
+    {
+        DPRINT1("BIOS keyboard buffer full.\n");
+        return FALSE;
+    }
 
     /* Put the value in the queue */
     *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data;
-    Bda->KeybdBufferTail += sizeof(WORD);
-
-    /* Check if we are at, or have passed, the end of the buffer */
-    if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd)
-    {
-        /* Return it to the beginning */
-        Bda->KeybdBufferTail = Bda->KeybdBufferStart;
-    }
+    Bda->KeybdBufferTail = NextElement;
 
     /* Return success */
     return TRUE;
@@ -91,22 +88,13 @@ static WORD BiosPeekCharacter(VOID)
     else return 0xFFFF;
 }
 
-WORD BiosGetCharacter(VOID)
+static WORD BiosGetCharacter(VOID)
 {
     WORD CharacterData = 0;
 
-    /* Check if there is a key available */
-    if (BiosKbdBufferTop(&CharacterData))
-    {
-        /* A key was available, remove it from the queue */
-        BiosKbdBufferPop();
-    }
-    else
-    {
-        /* No key available. Set the handler CF to repeat the BOP */
-        setCF(1);
-        // CharacterData = 0xFFFF;
-    }
+    /* Check if there is a key available, and if so, remove it from the queue */
+    if (BiosKbdBufferTop(&CharacterData)) BiosKbdBufferPop();
+    else CharacterData = 0xFFFF;
 
     return CharacterData;
 }
@@ -121,7 +109,17 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
         case 0x10:  // FIXME: Temporarily do the same as INT 16h, 00h
         {
             /* Read the character (and wait if necessary) */
-            setAX(BiosGetCharacter());
+            WORD Character = BiosGetCharacter();
+
+            if (Character == 0xFFFF)
+            {
+                /* No key available. Set the handler CF to repeat the BOP */
+                setCF(1);
+                break;
+            }
+
+            setAX(Character);
+
             break;
         }
 
@@ -130,13 +128,13 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
         /* Get extended keystroke status */
         case 0x11:  // FIXME: Temporarily do the same as INT 16h, 01h
         {
-            WORD Data = BiosPeekCharacter();
+            WORD Character = BiosPeekCharacter();
 
-            if (Data != 0xFFFF)
+            if (Character != 0xFFFF)
             {
                 /* There is a character, clear ZF and return it */
                 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
-                setAX(Data);
+                setAX(Character);
             }
             else
             {
@@ -196,11 +194,37 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
 // Keyboard IRQ 1
 static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
 {
+    BOOLEAN SkipScanCode;
     BYTE ScanCode, VirtualKey;
     WORD Character;
 
-    /* Get the scan code and virtual key code */
-    ScanCode = IOReadB(PS2_DATA_PORT);
+    /*
+     * Get the scan code from the PS/2 port, then call the
+     * INT 15h, AH=4Fh Keyboard Intercept function to try to
+     * translate the scan code. CF must be set before the call.
+     * In return, if CF is set we continue processing the scan code
+     * stored in AL, and if not, we skip it.
+     */
+    BYTE CF, AX;
+    CF = getCF();
+    AX = getAX();
+
+    setCF(1);
+    setAL(IOReadB(PS2_DATA_PORT));
+    setAH(0x4F);
+    Int32Call(&BiosContext, BIOS_MISC_INTERRUPT);
+
+    /* Retrieve the modified scan code in AL */
+    SkipScanCode = (getCF() == 0);
+    ScanCode = getAL();
+
+    setAX(AX);
+    setCF(CF);
+
+    /* Check whether CF is clear. If so, skip the scan code. */
+    if (SkipScanCode) goto Quit;
+
+    /* Get the corresponding virtual key code */
     VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
 
     /* Check if this is a key press or release */
@@ -257,6 +281,10 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
     if (BiosKeyboardMap[VK_CAPITAL]  & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK;
     if (BiosKeyboardMap[VK_INSERT]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT;
 
+    DPRINT("BiosKeyboardIrq - Character = 0x%X, ScanCode = 0x%X, KeybdShiftFlags = 0x%X\n",
+           Character, ScanCode, Bda->KeybdShiftFlags);
+
+Quit:
     PicIRQComplete(Stack);
 }
 
@@ -270,7 +298,10 @@ BOOLEAN KbdBios32Initialize(VOID)
     /* Initialize the BDA */
     Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
     Bda->KeybdBufferEnd   = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
-    Bda->KeybdBufferHead  = Bda->KeybdBufferTail = 0;
+    Bda->KeybdBufferHead  = Bda->KeybdBufferTail = Bda->KeybdBufferStart;
+
+    // FIXME: Fill the keyboard buffer with invalid values, for diagnostic purposes...
+    RtlFillMemory(((LPVOID)((ULONG_PTR)Bda + Bda->KeybdBufferStart)), BIOS_KBD_BUFFER_SIZE * sizeof(WORD), 'A');
 
     /* Register the BIOS 32-bit Interrupts */
 
@@ -279,7 +310,6 @@ BOOLEAN KbdBios32Initialize(VOID)
 
     /* Set up the HW vector interrupts */
     EnableHwIRQ(1, BiosKeyboardIrq);
-    // EnableHwIRQ(12, BiosMouseIrq);
 
     return TRUE;
 }