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:
Aleksandar Andrejevic 2013-10-24 01:01:49 +00:00
parent 5eb7c07bb8
commit 01d5a36cf5
5 changed files with 96 additions and 73 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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]);
}

View file

@ -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
{

View file

@ -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);
}