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;
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;
}
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;
}
/* 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
{
// 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 */
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);
}
/* 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 */
/* Set up the HW vector interrupts */
EnableHwIRQ(1, BiosKeyboardIrq);
- // EnableHwIRQ(12, BiosMouseIrq);
return TRUE;
}