#include "ps2.h"
#include "timer.h"
+#include "registers.h"
+
/* PRIVATE VARIABLES **********************************************************/
PBIOS_DATA_AREA Bda;
static BOOLEAN BiosKbdBufferPush(WORD Data)
{
- /* Get the location of the element after the head */
- WORD NextElement = Bda->KeybdBufferHead + 2;
+ /* Get the location of the element after the tail */
+ WORD NextElement = Bda->KeybdBufferTail + 2;
/* Wrap it around if it's at or beyond the end */
if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart;
/* If it's full, fail */
- if (NextElement == Bda->KeybdBufferTail) return FALSE;
+ if (NextElement == Bda->KeybdBufferHead) return FALSE;
/* Put the value in the queue */
*((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data;
IntVecTable[i * 2] = Offset;
IntVecTable[i * 2 + 1] = BIOS_SEGMENT;
- BiosCode[Offset++] = 0xFA; // cli
+ BiosCode[Offset++] = 0xFB; // sti
BiosCode[Offset++] = 0x6A; // push i
BiosCode[Offset++] = (BYTE)i;
+ BiosCode[Offset++] = 0x6A; // push 0
+ BiosCode[Offset++] = 0x00;
+
+ BiosCode[Offset++] = 0xF8; // clc
+
BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
BiosCode[Offset++] = LOBYTE(EMULATOR_INT_BOP);
BiosCode[Offset++] = HIBYTE(EMULATOR_INT_BOP);
- BiosCode[Offset++] = 0x83; // add sp, 2
+ BiosCode[Offset++] = 0x73; // jnc +3
+ BiosCode[Offset++] = 0x03;
+
+ // HACK: The following instruction should be HLT!
+ BiosCode[Offset++] = 0x90; // nop
+
+ BiosCode[Offset++] = 0xEB; // jmp -10
+ BiosCode[Offset++] = 0xF6;
+
+ BiosCode[Offset++] = 0x83; // add sp, 4
BiosCode[Offset++] = 0xC4;
- BiosCode[Offset++] = 0x02;
+ BiosCode[Offset++] = 0x04;
BiosCode[Offset++] = 0xCF; // iret
}
WORD BiosGetCharacter(VOID)
{
- WORD CharacterData;
- INPUT_RECORD InputRecord;
- DWORD Count;
+ WORD CharacterData = 0;
/* Check if there is a key available */
if (Bda->KeybdBufferHead != Bda->KeybdBufferTail)
}
else
{
- while (TRUE)
- {
- /* Wait for a console event */
- WaitForSingleObject(BiosConsoleInput, INFINITE);
-
- /* Read the event, and make sure it's a keypress */
- if (!ReadConsoleInput(BiosConsoleInput, &InputRecord, 1, &Count)) continue;
- if (InputRecord.EventType != KEY_EVENT) continue;
- if (!InputRecord.Event.KeyEvent.bKeyDown) continue;
-
- /* Save the scan code and end the loop */
- CharacterData = (InputRecord.Event.KeyEvent.wVirtualScanCode << 8)
- | InputRecord.Event.KeyEvent.uChar.AsciiChar;
-
- break;
- }
+ /* Set the handler CF to repeat the BOP */
+ EmulatorSetFlag(EMULATOR_FLAG_CF);
}
return CharacterData;
switch (HIBYTE(Eax))
{
+ /* Wait for keystroke and read */
case 0x00:
+ /* Wait for extended keystroke and read */
+ case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h
{
/* Read the character (and wait if necessary) */
EmulatorSetRegister(EMULATOR_REG_AX, BiosGetCharacter());
-
break;
}
+ /* Get keystroke status */
case 0x01:
+ /* Get extended keystroke status */
+ case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h
{
WORD Data = BiosPeekCharacter();
break;
}
-
+
+ /* Get shift status */
+ case 0x02:
+ {
+ /* Return the lower byte of the keyboard shift status word */
+ setAL(LOBYTE(Bda->KeybdShiftFlags));
+ break;
+ }
+
+ /* Reserved */
+ case 0x04:
+ {
+ DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n");
+ break;
+ }
+
+ /* Push keystroke */
+ case 0x05:
+ {
+ /* Return 0 if success, 1 if failure */
+ setAL(BiosKbdBufferPush(getCX()) == FALSE);
+ break;
+ }
+
+ /* Get extended shift status */
+ case 0x12:
+ {
+ /*
+ * Be careful! The returned word is similar to Bda->KeybdShiftFlags
+ * but the high byte is organized differently:
+ * the bytes 2 and 3 of the high byte are not the same...
+ */
+ WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
+
+ /* Return the extended keyboard shift status word */
+ setAX(KeybdShiftFlags);
+ break;
+ }
+
default:
{
DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n",
BYTE ScanCode, VirtualKey;
WORD Character;
- /* Check if there is a scancode available */
- if (!(KeyboardReadStatus() & 1)) break;
-
- /* Get the scan code and virtual key code */
- ScanCode = KeyboardReadData();
- VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
-
- /* Check if this is a key press or release */
- if (!(ScanCode & (1 << 7)))
+ /* Loop while there is a scancode available */
+ while (KeyboardReadStatus() & 1)
{
- /* Key press */
- if (VirtualKey == VK_NUMLOCK
- || VirtualKey == VK_CAPITAL
- || VirtualKey == VK_SCROLL)
+ /* Get the scan code and virtual key code */
+ ScanCode = KeyboardReadData();
+ VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
+
+ /* Check if this is a key press or release */
+ if (!(ScanCode & (1 << 7)))
{
- /* For toggle keys, toggle the lowest bit in the keyboard map */
- BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
- }
+ /* Key press */
+ if (VirtualKey == VK_NUMLOCK
+ || VirtualKey == VK_CAPITAL
+ || VirtualKey == VK_SCROLL)
+ {
+ /* For toggle keys, toggle the lowest bit in the keyboard map */
+ BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
+ }
+
+ /* Set the highest bit */
+ BiosKeyboardMap[VirtualKey] |= (1 << 7);
- /* Set the highest bit */
- BiosKeyboardMap[VirtualKey] |= (1 << 7);
+ /* Find out which character this is */
+ Character = 0;
+ if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
+ {
+ /* Not ASCII */
+ Character = 0;
+ }
- /* Find out which character this is */
- if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) > 0)
- {
/* Push it onto the BIOS keyboard queue */
BiosKbdBufferPush((ScanCode << 8) | (Character & 0xFF));
+
+ }
+ else
+ {
+ /* Key release, unset the highest bit */
+ BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
}
- }
- else
- {
- /* Key release, unset the highest bit */
- BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
}
break;