mirror of
https://github.com/reactos/reactos.git
synced 2024-10-08 10:24:06 +00:00
[NTVDM]
Remove the code that performs waiting in 32-bit mode since that blocks the emulator and prevents interrupts from working. Implement a 16-bit waiting system in the interrupt handlers. Fix the PS/2 interrupt code. svn path=/branches/ntvdm/; revision=60739
This commit is contained in:
parent
5eb7c07bb8
commit
01d5a36cf5
|
@ -267,14 +267,14 @@ static LPBYTE VideoModes[] =
|
|||
|
||||
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;
|
||||
|
@ -468,18 +468,33 @@ BOOLEAN BiosInitialize(VOID)
|
|||
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++] = 0x44; // inc sp
|
||||
BiosCode[Offset++] = 0x44; // inc sp
|
||||
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++] = 0x04;
|
||||
|
||||
BiosCode[Offset++] = 0xCF; // iret
|
||||
}
|
||||
|
@ -590,9 +605,7 @@ WORD BiosPeekCharacter(VOID)
|
|||
|
||||
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)
|
||||
|
@ -603,24 +616,8 @@ WORD BiosGetCharacter(VOID)
|
|||
}
|
||||
else
|
||||
{
|
||||
VgaRefreshDisplay(); // HACK: Waiting here blocks the emulator!!!
|
||||
|
||||
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;
|
||||
|
|
|
@ -684,30 +684,17 @@ WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead)
|
|||
WORD Result = ERROR_SUCCESS;
|
||||
DWORD BytesRead32 = 0;
|
||||
HANDLE Handle = DosGetRealHandle(FileHandle);
|
||||
WORD i;
|
||||
|
||||
DPRINT("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count);
|
||||
|
||||
/* Make sure the handle is valid */
|
||||
if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
|
||||
|
||||
if (IsConsoleHandle(Handle))
|
||||
/* Read the file */
|
||||
if (!ReadFile(Handle, Buffer, Count, &BytesRead32, NULL))
|
||||
{
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
/* Call the BIOS function to read the character */
|
||||
((LPBYTE)Buffer)[i] = LOBYTE(BiosGetCharacter());
|
||||
BytesRead32++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the file */
|
||||
if (!ReadFile(Handle, Buffer, Count, &BytesRead32, NULL))
|
||||
{
|
||||
/* Store the error code */
|
||||
Result = (WORD)GetLastError();
|
||||
}
|
||||
/* Store the error code */
|
||||
Result = (WORD)GetLastError();
|
||||
}
|
||||
|
||||
/* The number of bytes read is always 16-bit */
|
||||
|
@ -1283,8 +1270,16 @@ CHAR DosReadCharacter(VOID)
|
|||
CHAR Character = '\0';
|
||||
WORD BytesRead;
|
||||
|
||||
/* Use the file reading function */
|
||||
DosReadFile(DOS_INPUT_HANDLE, &Character, sizeof(CHAR), &BytesRead);
|
||||
if (IsConsoleHandle(DosGetRealHandle(DOS_INPUT_HANDLE)))
|
||||
{
|
||||
/* Call the BIOS */
|
||||
Character = LOBYTE(BiosGetCharacter());
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the file reading function */
|
||||
DosReadFile(DOS_INPUT_HANDLE, &Character, sizeof(CHAR), &BytesRead);
|
||||
}
|
||||
|
||||
return Character;
|
||||
}
|
||||
|
@ -1381,7 +1376,12 @@ VOID DosInt21h(LPWORD Stack)
|
|||
{
|
||||
Character = DosReadCharacter();
|
||||
DosPrintCharacter(Character);
|
||||
EmulatorSetRegister(EMULATOR_REG_AX, (Eax & 0xFFFFFF00) | Character);
|
||||
|
||||
if (!EmulatorGetFlag(EMULATOR_FLAG_CF))
|
||||
{
|
||||
EmulatorSetRegister(EMULATOR_REG_AX, (Eax & 0xFFFFFF00) | Character);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1396,8 +1396,13 @@ VOID DosInt21h(LPWORD Stack)
|
|||
case 0x07:
|
||||
case 0x08:
|
||||
{
|
||||
EmulatorSetRegister(EMULATOR_REG_AX,
|
||||
(Eax & 0xFFFFFF00) | DosReadCharacter());
|
||||
Character = DosReadCharacter();
|
||||
|
||||
if (!EmulatorGetFlag(EMULATOR_FLAG_CF))
|
||||
{
|
||||
EmulatorSetRegister(EMULATOR_REG_AX, (Eax & 0xFFFFFF00) | Character);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1419,6 +1424,8 @@ VOID DosInt21h(LPWORD Stack)
|
|||
/* Read Buffered Input */
|
||||
case 0x0A:
|
||||
{
|
||||
DPRINT1("FIXME: This function is still not adapted to the new system!\n");
|
||||
|
||||
InputBuffer = (PDOS_INPUT_BUFFER)((ULONG_PTR)BaseAddress
|
||||
+ TO_LINEAR(DataSegment,
|
||||
LOWORD(Edx)));
|
||||
|
@ -1725,23 +1732,45 @@ VOID DosInt21h(LPWORD Stack)
|
|||
/* Read File */
|
||||
case 0x3F:
|
||||
{
|
||||
WORD Handle = LOWORD(Ebx);
|
||||
LPBYTE Buffer = (LPBYTE)((ULONG_PTR)BaseAddress + TO_LINEAR(DataSegment, LOWORD(Edx)));
|
||||
WORD Count = LOWORD(Ecx);
|
||||
WORD BytesRead = 0;
|
||||
WORD ErrorCode = DosReadFile(LOWORD(Ebx),
|
||||
(LPVOID)((ULONG_PTR)BaseAddress
|
||||
+ TO_LINEAR(DataSegment, LOWORD(Edx))),
|
||||
LOWORD(Ecx),
|
||||
&BytesRead);
|
||||
WORD ErrorCode = ERROR_SUCCESS;
|
||||
|
||||
if (IsConsoleHandle(DosGetRealHandle(Handle)))
|
||||
{
|
||||
while (Stack[STACK_COUNTER] < Count)
|
||||
{
|
||||
/* Read a character from the BIOS */
|
||||
Buffer[Stack[STACK_COUNTER]] = LOBYTE(BiosGetCharacter()); // FIXME: Security checks!
|
||||
|
||||
/* Stop if the BOP needs to be repeated */
|
||||
if (EmulatorGetFlag(EMULATOR_FLAG_CF)) break;
|
||||
|
||||
/* Increment the counter */
|
||||
Stack[STACK_COUNTER]++;
|
||||
}
|
||||
|
||||
if (Stack[STACK_COUNTER] < Count) ErrorCode = ERROR_NOT_READY;
|
||||
else BytesRead = Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the file reading function */
|
||||
ErrorCode = DosReadFile(Handle, Buffer, Count, &BytesRead);
|
||||
}
|
||||
|
||||
if (ErrorCode == 0)
|
||||
{
|
||||
/* Clear CF */
|
||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||
|
||||
/* Return the number of bytes read in AX */
|
||||
EmulatorSetRegister(EMULATOR_REG_AX,
|
||||
(Eax & 0xFFFF0000) | BytesRead);
|
||||
/* Clear CF */
|
||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||
|
||||
/* Return the number of bytes read in AX */
|
||||
EmulatorSetRegister(EMULATOR_REG_AX,
|
||||
(Eax & 0xFFFF0000) | BytesRead);
|
||||
}
|
||||
else
|
||||
else if (ErrorCode != ERROR_NOT_READY)
|
||||
{
|
||||
/* Set CF */
|
||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||
|
|
|
@ -590,9 +590,6 @@ VOID EmulatorStep(VOID)
|
|||
/* Skip the opcodes */
|
||||
EmulatorContext.state->reg_ip += 4;
|
||||
|
||||
// HACK: Refresh the display because the called function may wait.
|
||||
VgaRefreshDisplay();
|
||||
|
||||
/* Call the BOP handler */
|
||||
EmulatorBop(Instruction[1]);
|
||||
}
|
||||
|
|
|
@ -43,10 +43,11 @@
|
|||
/* Common definitions */
|
||||
#define EMULATOR_BOP 0xC4C4
|
||||
#define EMULATOR_INT_BOP 0xBEEF
|
||||
#define STACK_INT_NUM 0
|
||||
#define STACK_IP 1
|
||||
#define STACK_CS 2
|
||||
#define STACK_FLAGS 3
|
||||
#define STACK_COUNTER 0
|
||||
#define STACK_INT_NUM 1
|
||||
#define STACK_IP 2
|
||||
#define STACK_CS 3
|
||||
#define STACK_FLAGS 4
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -271,6 +271,7 @@ VOID CheckForInputEvents()
|
|||
HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD i, j, Count, TotalEvents;
|
||||
BYTE ScanCode;
|
||||
BOOLEAN Interrupt = FALSE;
|
||||
|
||||
/* Get the number of input events */
|
||||
if (!GetNumberOfConsoleInputEvents(ConsoleInput, &Count)) return;
|
||||
|
@ -300,13 +301,11 @@ VOID CheckForInputEvents()
|
|||
KeyboardQueuePush(ScanCode);
|
||||
}
|
||||
|
||||
/* Yes, IRQ 1 */
|
||||
PicInterruptRequest(1);
|
||||
|
||||
/* Stop the loop */
|
||||
break;
|
||||
Interrupt = TRUE;
|
||||
}
|
||||
|
||||
if (Interrupt) PicInterruptRequest(1);
|
||||
|
||||
Cleanup:
|
||||
HeapFree(GetProcessHeap(), 0, Buffer);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue