Author: aandrejevic
Date: Mon Jul 15 01:37:38 2013
New Revision: 59489
URL:
http://svn.reactos.org/svn/reactos?rev=59489&view=rev
Log:
[NTVDM]
Implement the Bios Data Area (BDA).
Fix keyboard character translation bug.
Modified:
branches/ntvdm/subsystems/ntvdm/bios.c
branches/ntvdm/subsystems/ntvdm/bios.h
Modified: branches/ntvdm/subsystems/ntvdm/bios.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.c?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] Mon Jul 15 01:37:38 2013
@@ -16,23 +16,18 @@
/* PRIVATE VARIABLES **********************************************************/
+static PBIOS_DATA_AREA Bda;
static BYTE BiosKeyboardMap[256];
-static WORD BiosKbdBuffer[BIOS_KBD_BUFFER_SIZE];
-static UINT BiosKbdBufferStart = 0, BiosKbdBufferEnd = 0;
-static BOOLEAN BiosKbdBufferEmpty = TRUE;
-static DWORD BiosTickCount = 0;
-static BOOLEAN BiosPassedMidnight = FALSE;
static HANDLE BiosConsoleInput = INVALID_HANDLE_VALUE;
static HANDLE BiosConsoleOutput = INVALID_HANDLE_VALUE;
-static BYTE CurrentVideoMode = BIOS_DEFAULT_VIDEO_MODE;
-static BYTE CurrentVideoPage = 0;
-static COORD BiosCursorPositions[BIOS_MAX_PAGES];
static HANDLE BiosGraphicsOutput = NULL;
static LPVOID ConsoleFramebuffer = NULL;
static HANDLE ConsoleMutex = NULL;
+static BYTE CurrentVideoMode, CurrentVideoPage;
static BOOLEAN VideoNeedsUpdate = TRUE;
static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 };
static CONSOLE_SCREEN_BUFFER_INFO BiosSavedBufferInfo;
+
static VIDEO_MODE VideoModes[] =
{
/* Width | Height | Text | Bpp | Gray | Pages | Segment */
@@ -103,17 +98,25 @@
static BOOLEAN BiosKbdBufferPush(WORD Data)
{
+ /* Get the location of the element after the head */
+ WORD NextElement = Bda->KeybdBufferHead + 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 (!BiosKbdBufferEmpty && (BiosKbdBufferStart == BiosKbdBufferEnd))
- {
- return FALSE;
- }
-
- /* Otherwise, add the value to the queue */
- BiosKbdBuffer[BiosKbdBufferEnd] = Data;
- BiosKbdBufferEnd++;
- BiosKbdBufferEnd %= BIOS_KBD_BUFFER_SIZE;
- BiosKbdBufferEmpty = FALSE;
+ if (NextElement == Bda->KeybdBufferTail) 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;
+ }
/* Return success */
return TRUE;
@@ -122,23 +125,30 @@
static BOOLEAN BiosKbdBufferTop(LPWORD Data)
{
/* If it's empty, fail */
- if (BiosKbdBufferEmpty) return FALSE;
+ if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
/* Otherwise, get the value and return success */
- *Data = BiosKbdBuffer[BiosKbdBufferStart];
+ *Data = *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferHead));
+
return TRUE;
}
static BOOLEAN BiosKbdBufferPop()
{
/* If it's empty, fail */
- if (BiosKbdBufferEmpty) return FALSE;
-
- /* Otherwise, remove the value and return success */
- BiosKbdBufferStart++;
- BiosKbdBufferStart %= BIOS_KBD_BUFFER_SIZE;
- if (BiosKbdBufferStart == BiosKbdBufferEnd) BiosKbdBufferEmpty = TRUE;
-
+ if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE;
+
+ /* Remove the value from the queue */
+ Bda->KeybdBufferHead += sizeof(WORD);
+
+ /* Check if we are at, or have passed, the end of the buffer */
+ if (Bda->KeybdBufferHead >= Bda->KeybdBufferEnd)
+ {
+ /* Return it to the beginning */
+ Bda->KeybdBufferHead = Bda->KeybdBufferStart;
+ }
+
+ /* Return success */
return TRUE;
}
@@ -271,8 +281,16 @@
SetConsoleActiveScreenBuffer(BiosGraphicsOutput);
}
- /* Set the video mode */
+ /* Change the mode number */
CurrentVideoMode = ModeNumber;
+ CurrentVideoPage = 0;
+
+ /* Update the BDA */
+ Bda->VideoMode = CurrentVideoMode;
+ Bda->VideoPage = CurrentVideoPage;
+ Bda->VideoPageSize = BiosGetVideoPageSize();
+ Bda->VideoPageOffset = 0;
+ Bda->ScreenColumns = VideoModes[ModeNumber].Width;
return TRUE;
}
@@ -280,6 +298,7 @@
BOOLEAN BiosSetVideoPage(BYTE PageNumber)
{
ULONG PageStart;
+ COORD Coordinates;
CONSOLE_SCREEN_BUFFER_INFO BufferInfo;
/* Make sure this is a valid page number */
@@ -291,17 +310,25 @@
/* Save the cursor */
if (!GetConsoleScreenBufferInfo(BiosConsoleOutput, &BufferInfo)) return FALSE;
- BiosCursorPositions[CurrentVideoPage] = BufferInfo.dwCursorPosition;
+ Bda->CursorPosition[CurrentVideoPage] = MAKEWORD(BufferInfo.dwCursorPosition.X,
+ BufferInfo.dwCursorPosition.Y);
/* Set the page */
CurrentVideoPage = PageNumber;
+ /* Update the BDA */
+ Bda->VideoPage = CurrentVideoPage;
+ Bda->VideoPageSize = BiosGetVideoPageSize();
+ Bda->VideoPageOffset = CurrentVideoPage * Bda->VideoPageSize;
+
/* Update the console */
- PageStart = BiosGetVideoMemoryStart() + CurrentVideoPage * BiosGetVideoPageSize();
+ PageStart = BiosGetVideoMemoryStart() + Bda->VideoPage * BiosGetVideoPageSize();
BiosUpdateConsole(PageStart, PageStart + BiosGetVideoPageSize());
/* Set the cursor */
- SetConsoleCursorPosition(BiosConsoleOutput, BiosCursorPositions[PageNumber]);
+ Coordinates.X = LOBYTE(Bda->CursorPosition[Bda->VideoPage]);
+ Coordinates.Y = HIBYTE(Bda->CursorPosition[Bda->VideoPage]);
+ SetConsoleCursorPosition(BiosConsoleOutput, Coordinates);
return TRUE;
}
@@ -332,6 +359,12 @@
WORD Offset = 0;
LPWORD IntVecTable = (LPWORD)((ULONG_PTR)BaseAddress);
LPBYTE BiosCode = (LPBYTE)((ULONG_PTR)BaseAddress + TO_LINEAR(BIOS_SEGMENT, 0));
+
+ /* Initialize the BDA */
+ Bda = (PBIOS_DATA_AREA)((ULONG_PTR)BaseAddress + TO_LINEAR(BDA_SEGMENT, 0));
+ Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
+ Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
+ Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE *
sizeof(WORD);
/* Generate ISR stubs and fill the IVT */
for (i = 0; i < 256; i++)
@@ -388,8 +421,8 @@
}
/* Store the cursor position */
- ZeroMemory(&BiosCursorPositions, sizeof(BiosCursorPositions));
- BiosCursorPositions[0] = BiosSavedBufferInfo.dwCursorPosition;
+ Bda->CursorPosition[0] = MAKEWORD(BiosSavedBufferInfo.dwCursorPosition.X,
+ BiosSavedBufferInfo.dwCursorPosition.Y);
/* Set the default video mode */
BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
@@ -582,7 +615,7 @@
WORD CharacterData;
/* Check if there is a key available */
- if (BiosKbdBufferEmpty) return 0xFFFF;
+ if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return 0xFFFF;
/* Get the key from the queue, but don't remove it */
BiosKbdBufferTop(&CharacterData);
@@ -597,7 +630,7 @@
DWORD Count;
/* Check if there is a key available */
- if (!BiosKbdBufferEmpty)
+ if (Bda->KeybdBufferHead != Bda->KeybdBufferTail)
{
/* Get the key from the queue, and remove it */
BiosKbdBufferTop(&CharacterData);
@@ -673,15 +706,14 @@
/* Make sure the selected video page exists */
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
- Position.X = LOBYTE(Edx);
- Position.Y = HIBYTE(Edx);
-
- BiosCursorPositions[HIBYTE(Ebx)] = Position;
+ Bda->CursorPosition[HIBYTE(Ebx)] = LOWORD(Edx);
/* Check if this is the current video page */
if (HIBYTE(Ebx) == CurrentVideoPage)
{
/* Yes, change the actual cursor */
+ Position.X = LOBYTE(Edx);
+ Position.Y = HIBYTE(Edx);
SetConsoleCursorPosition(BiosConsoleOutput, Position);
}
@@ -705,9 +737,8 @@
/* Return the result */
EmulatorSetRegister(EMULATOR_REG_AX, 0);
EmulatorSetRegister(EMULATOR_REG_CX, (StartLine << 8) | 0x1F);
- EmulatorSetRegister(EMULATOR_REG_DX,
- (LOBYTE(BiosCursorPositions[HIBYTE(Ebx)].Y) << 8)
- | LOBYTE(BiosCursorPositions[HIBYTE(Ebx)].X));
+ EmulatorSetRegister(EMULATOR_REG_DX, Bda->CursorPosition[HIBYTE(Ebx)]);
+
break;
}
@@ -877,10 +908,9 @@
case 0x0F:
{
EmulatorSetRegister(EMULATOR_REG_AX,
- (VideoModes[CurrentVideoMode].Width << 8)
- | CurrentVideoMode);
+ MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
EmulatorSetRegister(EMULATOR_REG_BX,
- (CurrentVideoPage << 8) | LOBYTE(Ebx));
+ MAKEWORD(LOBYTE(Ebx), Bda->VideoPage));
break;
}
@@ -946,15 +976,15 @@
{
/* Set AL to 1 if midnight had passed, 0 otherwise */
Eax &= 0xFFFFFF00;
- if (BiosPassedMidnight) Eax |= 1;
+ if (Bda->MidnightPassed) Eax |= 1;
/* Return the tick count in CX:DX */
EmulatorSetRegister(EMULATOR_REG_AX, Eax);
- EmulatorSetRegister(EMULATOR_REG_CX, HIWORD(BiosTickCount));
- EmulatorSetRegister(EMULATOR_REG_DX, LOWORD(BiosTickCount));
+ EmulatorSetRegister(EMULATOR_REG_CX, HIWORD(Bda->TickCounter));
+ EmulatorSetRegister(EMULATOR_REG_DX, LOWORD(Bda->TickCounter));
/* Reset the midnight flag */
- BiosPassedMidnight = FALSE;
+ Bda->MidnightPassed = FALSE;
break;
}
@@ -962,10 +992,10 @@
case 0x01:
{
/* Set the tick count to CX:DX */
- BiosTickCount = MAKELONG(LOWORD(Edx), LOWORD(Ecx));
+ Bda->TickCounter = MAKELONG(LOWORD(Edx), LOWORD(Ecx));
/* Reset the midnight flag */
- BiosPassedMidnight = FALSE;
+ Bda->MidnightPassed = FALSE;
break;
}
@@ -981,13 +1011,13 @@
VOID BiosSystemTimerInterrupt()
{
/* Increase the system tick count */
- BiosTickCount++;
+ Bda->TickCounter++;
}
VOID BiosEquipmentService()
{
/* Return the equipment list */
- EmulatorSetRegister(EMULATOR_REG_AX, BIOS_EQUIPMENT_LIST);
+ EmulatorSetRegister(EMULATOR_REG_AX, Bda->EquipmentList);
}
VOID BiosHandleIrq(BYTE IrqNumber)
@@ -1014,7 +1044,7 @@
/* Get the scan code and virtual key code */
ScanCode = KeyboardReadData();
- VirtualKey = MapVirtualKey(ScanCode, MAPVK_VSC_TO_VK);
+ VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
/* Check if this is a key press or release */
if (!(ScanCode & (1 << 7)))
@@ -1032,10 +1062,11 @@
BiosKeyboardMap[VirtualKey] |= (1 << 7);
/* Find out which character this is */
- ToAscii(ScanCode, VirtualKey, BiosKeyboardMap, &Character, 0);
-
- /* Push it onto the BIOS keyboard queue */
- BiosKbdBufferPush((ScanCode << 8) | (Character & 0xFF));
+ if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0)
> 0)
+ {
+ /* Push it onto the BIOS keyboard queue */
+ BiosKbdBufferPush((ScanCode << 8) | (Character & 0xFF));
+ }
}
else
{
Modified: branches/ntvdm/subsystems/ntvdm/bios.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.h?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] Mon Jul 15 01:37:38 2013
@@ -18,6 +18,7 @@
#define CONSOLE_VIDEO_MEM_END 0xBFFFF
#define ROM_AREA_START 0xC0000
#define ROM_AREA_END 0xFFFFF
+#define BDA_SEGMENT 0x40
#define BIOS_PIC_MASTER_INT 0x08
#define BIOS_PIC_SLAVE_INT 0x70
#define BIOS_SEGMENT 0xF000
@@ -27,8 +28,8 @@
#define BIOS_TIME_INTERRUPT 0x1A
#define BIOS_SYS_TIMER_INTERRUPT 0x1C
#define CONSOLE_FONT_HEIGHT 8
-#define BIOS_KBD_BUFFER_SIZE 256
-#define BIOS_EQUIPMENT_LIST 0x3C // HACK: Disable FPU for now
+#define BIOS_KBD_BUFFER_SIZE 16
+#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now
#define BIOS_DEFAULT_VIDEO_MODE 0x03
#define BIOS_MAX_PAGES 8
#define BIOS_MAX_VIDEO_MODE 0x13
@@ -43,6 +44,56 @@
BYTE Pages;
WORD Segment;
} VIDEO_MODE;
+
+#pragma pack(push, 1)
+
+typedef struct
+{
+ WORD SerialPorts[4];
+ WORD ParallelPorts[3];
+ WORD EbdaSegment;
+ WORD EquipmentList;
+ BYTE Reserved0;
+ WORD MemorySize;
+ WORD Reserved1;
+ WORD KeyboardFlags;
+ BYTE AlternateKeypad;
+ WORD KeybdBufferHead;
+ WORD KeybdBufferTail;
+ WORD KeybdBuffer[BIOS_KBD_BUFFER_SIZE];
+ BYTE DriveRecalibrate;
+ BYTE DriveMotorStatus;
+ BYTE MotorShutdownCounter;
+ BYTE LastDisketteOperation;
+ BYTE Reserved2[7];
+ BYTE VideoMode;
+ WORD ScreenColumns;
+ WORD VideoPageSize;
+ WORD VideoPageOffset;
+ WORD CursorPosition[BIOS_MAX_PAGES];
+ BYTE CursorEndLine;
+ BYTE CursorStartLine;
+ BYTE VideoPage;
+ WORD CrtBasePort;
+ BYTE CrtModeControl;
+ BYTE CrtColorPaletteMask;
+ DWORD Uptime;
+ BYTE Reserved3;
+ DWORD TickCounter;
+ BYTE MidnightPassed;
+ BYTE BreakFlag;
+ WORD SoftReset;
+ BYTE LastDiskOperation;
+ BYTE NumDisks;
+ BYTE DriveControlByte;
+ BYTE DiskPortOffset;
+ BYTE LptTimeOut[4];
+ BYTE ComTimeOut[4];
+ WORD KeybdBufferStart;
+ WORD KeybdBufferEnd;
+} BIOS_DATA_AREA, *PBIOS_DATA_AREA;
+
+#pragma pack(pop)
/* FUNCTIONS ******************************************************************/