Author: aandrejevic
Date: Fri Jul 5 00:08:18 2013
New Revision: 59424
URL:
http://svn.reactos.org/svn/reactos?rev=59424&view=rev
Log:
[NTVDM]
Implement BIOS video mode setting.
Fix bugs in video memory access emulation.
Modified:
branches/ntvdm/subsystems/ntvdm/bios.c
branches/ntvdm/subsystems/ntvdm/bios.h
branches/ntvdm/subsystems/ntvdm/emulator.c
branches/ntvdm/subsystems/ntvdm/ntvdm.c
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] Fri Jul 5 00:08:18 2013
@@ -22,6 +22,35 @@
static BOOLEAN BiosKbdBufferEmpty = TRUE;
static DWORD BiosTickCount = 0;
static BOOLEAN BiosPassedMidnight = FALSE;
+static HANDLE BiosConsoleInput, BiosConsoleOutput;
+static BYTE CurrentVideoMode = BIOS_DEFAULT_VIDEO_MODE;
+static BYTE CurrentVideoPage = 0;
+static HANDLE ConsoleBuffers[BIOS_MAX_PAGES] = { NULL };
+static LPVOID ConsoleFramebuffers[BIOS_MAX_PAGES] = { NULL };
+static VIDEO_MODE VideoModes[] =
+{
+ /* Width | Height | Text | Colors | Gray | Pages | Segment */
+ { 40, 25, TRUE, 16, TRUE, 8, 0xB800}, /* Mode 00h */
+ { 40, 25, TRUE, 16, FALSE, 8, 0xB800}, /* Mode 01h */
+ { 80, 25, TRUE, 16, TRUE, 8, 0xB800}, /* Mode 02h */
+ { 80, 25, TRUE, 16, FALSE, 8, 0xB800}, /* Mode 03h */
+ { 320, 200, FALSE, 4, FALSE, 4, 0xB800}, /* Mode 04h */
+ { 320, 200, FALSE, 4, TRUE, 4, 0xB800}, /* Mode 05h */
+ { 640, 200, FALSE, 2, FALSE, 2, 0xB800}, /* Mode 06h */
+ { 80, 25, TRUE, 3, FALSE, 1, 0xB000}, /* Mode 07h */
+ { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 08h - not used
*/
+ { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 09h - not used
*/
+ { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 0Ah - not used
*/
+ { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 0Bh - not used
*/
+ { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 0Ch - not used
*/
+ { 320, 200, FALSE, 16, FALSE, 8, 0xA000}, /* Mode 0Dh */
+ { 640, 200, FALSE, 16, FALSE, 4, 0xA000}, /* Mode 0Eh */
+ { 640, 350, FALSE, 3, FALSE, 2, 0xA000}, /* Mode 0Fh */
+ { 640, 350, FALSE, 4, FALSE, 2, 0xA000}, /* Mode 10h */
+ { 640, 480, FALSE, 2, FALSE, 1, 0xA000}, /* Mode 11h */
+ { 640, 480, FALSE, 16, FALSE, 1, 0xA000}, /* Mode 12h */
+ { 640, 480, FALSE, 256, FALSE, 1, 0xA000} /* Mode 13h */
+};
/* PRIVATE FUNCTIONS **********************************************************/
@@ -29,8 +58,10 @@
{
COORD Result = {0, 0};
- Result.X = ((Address - CONSOLE_VIDEO_MEM_START) >> 1) % CONSOLE_WIDTH;
- Result.Y = ((Address - CONSOLE_VIDEO_MEM_START) >> 1) / CONSOLE_WIDTH;
+ Result.X = ((Address - (VideoModes[CurrentVideoMode].Segment << 4)) >>
1)
+ % VideoModes[CurrentVideoMode].Width;
+ Result.Y = ((Address - (VideoModes[CurrentVideoMode].Segment << 4)) >>
1)
+ / VideoModes[CurrentVideoMode].Width;
return Result;
}
@@ -78,13 +109,160 @@
/* PUBLIC FUNCTIONS ***********************************************************/
-BOOLEAN BiosInitialize()
+BYTE BiosGetVideoMode()
+{
+ return CurrentVideoMode;
+}
+
+BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
+{
+ INT i;
+ COORD Coord;
+ CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo;
+ LPBITMAPINFO BitmapInfo;
+ LPWORD PaletteIndex;
+
+ /* Make sure this is a valid video mode */
+ if (ModeNumber > BIOS_MAX_VIDEO_MODE) return FALSE;
+ if (VideoModes[ModeNumber].Pages == 0) return FALSE;
+
+ /* Free the current buffers */
+ for (i = 0; i < VideoModes[CurrentVideoMode].Pages; i++)
+ {
+ if (ConsoleBuffers[i] != NULL) CloseHandle(ConsoleBuffers[i]);
+ }
+
+ if (VideoModes[ModeNumber].Text)
+ {
+ /* Page 0 is CONOUT$ */
+ ConsoleBuffers[0] = CreateFile(TEXT("CONOUT$"),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ /* Set the current page to page 0 */
+ CurrentVideoPage = 0;
+
+ /* Create console buffers for other pages */
+ for (i = 1; i < VideoModes[ModeNumber].Pages; i++)
+ {
+ ConsoleBuffers[i] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ |
FILE_SHARE_WRITE,
+ NULL,
+ CONSOLE_TEXTMODE_BUFFER,
+ NULL);
+ }
+
+ /* Set the size for the buffers */
+ for (i = 0; i < VideoModes[ModeNumber].Pages; i++)
+ {
+ Coord.X = VideoModes[ModeNumber].Width;
+ Coord.Y = VideoModes[ModeNumber].Height;
+
+ SetConsoleScreenBufferSize(ConsoleBuffers[i], Coord);
+ }
+ }
+ else
+ {
+ /* Allocate a bitmap info structure */
+ BitmapInfo = (LPBITMAPINFO)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(BITMAPINFOHEADER)
+ + VideoModes[ModeNumber].Colors
+ * sizeof(WORD));
+ if (BitmapInfo == NULL) return FALSE;
+
+ /* Fill the bitmap info header */
+ ZeroMemory(&BitmapInfo->bmiHeader, sizeof(BITMAPINFOHEADER));
+ BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ BitmapInfo->bmiHeader.biWidth = VideoModes[ModeNumber].Width;
+ BitmapInfo->bmiHeader.biHeight = VideoModes[ModeNumber].Height;
+ BitmapInfo->bmiHeader.biPlanes = 1;
+ BitmapInfo->bmiHeader.biCompression = BI_RGB;
+
+ /* Calculate the number of color bits */
+ for (i = 31; i >= 0; i--)
+ {
+ if (VideoModes[ModeNumber].Colors & (1 << i)) break;
+ }
+ if (i == 0) i = 32;
+ BitmapInfo->bmiHeader.biBitCount = i;
+
+ /* Calculate the image size */
+ BitmapInfo->bmiHeader.biSizeImage = BitmapInfo->bmiHeader.biWidth
+ * BitmapInfo->bmiHeader.biHeight
+ * (BitmapInfo->bmiHeader.biBitCount
>> 3);
+
+ /* Fill the palette data */
+ PaletteIndex = (LPWORD)((ULONG_PTR)BitmapInfo + sizeof(BITMAPINFOHEADER));
+ for (i = 0; i < VideoModes[ModeNumber].Colors; i++)
+ {
+ PaletteIndex[i] = i;
+ }
+
+ /* Create a console buffer for each page */
+ for (i = 0; i < VideoModes[ModeNumber].Pages; i++)
+ {
+ /* Fill the console graphics buffer info */
+ GraphicsBufferInfo.dwBitMapInfoLength = sizeof(BITMAPINFOHEADER)
+ + VideoModes[ModeNumber].Colors
+ * sizeof(WORD);
+ GraphicsBufferInfo.lpBitMapInfo = BitmapInfo;
+ GraphicsBufferInfo.dwUsage = DIB_PAL_COLORS;
+
+ /* Create the buffer */
+ ConsoleBuffers[i] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ |
FILE_SHARE_WRITE,
+ NULL,
+ CONSOLE_GRAPHICS_BUFFER,
+ &GraphicsBufferInfo);
+
+ /* Save the framebuffer address */
+ ConsoleFramebuffers[i] = GraphicsBufferInfo.lpBitMap;
+ }
+
+ /* Free the bitmap information */
+ HeapFree(GetProcessHeap(), 0, BitmapInfo);
+ }
+
+ /* Set the active page console buffer */
+ SetConsoleActiveScreenBuffer(ConsoleBuffers[CurrentVideoPage]);
+
+ /* Update the mode number */
+ CurrentVideoMode = ModeNumber;
+
+ return TRUE;
+}
+
+inline DWORD BiosGetVideoMemoryStart()
+{
+ return (VideoModes[CurrentVideoMode].Segment << 4);
+}
+
+inline VOID BiosVerticalRefresh()
+{
+ SMALL_RECT Region;
+
+ /* Ignore if we're in text mode */
+ if (VideoModes[CurrentVideoMode].Text) return;
+
+ /* Fill the rectangle structure */
+ Region.Left = Region.Top = 0;
+ Region.Right = VideoModes[CurrentVideoMode].Width;
+ Region.Bottom = VideoModes[CurrentVideoMode].Height;
+
+ /* Redraw the screen */
+ InvalidateConsoleDIBits(ConsoleBuffers[CurrentVideoPage],
+ &Region);
+}
+
+BOOLEAN BiosInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
{
INT i;
WORD Offset = 0;
- COORD Size = { CONSOLE_WIDTH, CONSOLE_HEIGHT};
- HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
- HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
LPWORD IntVecTable = (LPWORD)((ULONG_PTR)BaseAddress);
LPBYTE BiosCode = (LPBYTE)((ULONG_PTR)BaseAddress + TO_LINEAR(BIOS_SEGMENT, 0));
@@ -112,8 +290,12 @@
BiosCode[Offset++] = 0xCF; // iret
}
- /* Set the console buffer size */
- if (!SetConsoleScreenBufferSize(ConsoleOutput, Size)) return FALSE;
+ /* Set global console I/O handles */
+ BiosConsoleInput = ConsoleInput;
+ BiosConsoleOutput = ConsoleOutput;
+
+ /* Set the default video mode */
+ BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
/* Set the console input mode */
SetConsoleMode(ConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
@@ -153,27 +335,43 @@
COORD UnitSize = { 1, 1 };
CHAR_INFO Character;
SMALL_RECT Rect;
- HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
/* Start from the character address */
StartAddress &= ~1;
- /* Loop through all the addresses */
- for (i = StartAddress; i < EndAddress; i += 2)
- {
- /* Get the coordinates */
- Coordinates = BiosVideoAddressToCoord(i);
-
- /* Fill the rectangle structure */
- Rect.Left = Coordinates.X;
- Rect.Top = Coordinates.Y;
-
- /* Fill the character data */
- Character.Char.AsciiChar = *((PCHAR)((ULONG_PTR)BaseAddress + i));
- Character.Attributes = *((PBYTE)((ULONG_PTR)BaseAddress + i + 1));
-
- /* Write the character */
- WriteConsoleOutputA(ConsoleOutput, &Character, UnitSize, Origin, &Rect);
+ if (VideoModes[CurrentVideoMode].Text)
+ {
+ /* Loop through all the addresses */
+ for (i = StartAddress; i < EndAddress; i += 2)
+ {
+ /* Get the coordinates */
+ Coordinates = BiosVideoAddressToCoord(i);
+
+ /* Fill the rectangle structure */
+ Rect.Left = Coordinates.X;
+ Rect.Top = Coordinates.Y;
+ Rect.Right = Rect.Left;
+ Rect.Bottom = Rect.Top;
+
+ /* Fill the character data */
+ Character.Char.AsciiChar = *((PCHAR)((ULONG_PTR)BaseAddress + i));
+ Character.Attributes = *((PBYTE)((ULONG_PTR)BaseAddress + i + 1));
+
+ /* Write the character */
+ WriteConsoleOutputA(BiosConsoleOutput,
+ &Character,
+ UnitSize,
+ Origin,
+ &Rect);
+ }
+ }
+ else
+ {
+ /* Copy the data to the framebuffer */
+ RtlCopyMemory((LPVOID)((ULONG_PTR)ConsoleFramebuffers[CurrentVideoPage]
+ + StartAddress - BiosGetVideoMemoryStart()),
+ (LPVOID)((ULONG_PTR)BaseAddress + StartAddress),
+ EndAddress - StartAddress);
}
}
@@ -183,35 +381,45 @@
COORD Coordinates;
WORD Attribute;
DWORD CharsWritten;
- HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
-
- /* Loop through all the addresses */
- for (i = StartAddress; i < EndAddress; i++)
- {
- /* Get the coordinates */
- Coordinates = BiosVideoAddressToCoord(i);
-
- /* Check if this is a character byte or an attribute byte */
- if ((i - CONSOLE_VIDEO_MEM_START) % 2 == 0)
- {
- /* This is a regular character */
- ReadConsoleOutputCharacterA(ConsoleOutput,
- (LPSTR)((ULONG_PTR)BaseAddress + i),
- sizeof(CHAR),
- Coordinates,
- &CharsWritten);
- }
- else
- {
- /* This is an attribute */
- ReadConsoleOutputAttribute(ConsoleOutput,
- &Attribute,
- sizeof(CHAR),
- Coordinates,
- &CharsWritten);
-
- *(PCHAR)((ULONG_PTR)BaseAddress + i) = LOBYTE(Attribute);
- }
+
+ if (VideoModes[CurrentVideoMode].Text)
+ {
+ /* Loop through all the addresses */
+ for (i = StartAddress; i < EndAddress; i++)
+ {
+ /* Get the coordinates */
+ Coordinates = BiosVideoAddressToCoord(i);
+
+ /* Check if this is a character byte or an attribute byte */
+ if ((i - (VideoModes[CurrentVideoMode].Segment << 4)) % 2 == 0)
+ {
+ /* This is a regular character */
+ ReadConsoleOutputCharacterA(BiosConsoleOutput,
+ (LPSTR)((ULONG_PTR)BaseAddress + i),
+ sizeof(CHAR),
+ Coordinates,
+ &CharsWritten);
+ }
+ else
+ {
+ /* This is an attribute */
+ ReadConsoleOutputAttribute(BiosConsoleOutput,
+ &Attribute,
+ sizeof(CHAR),
+ Coordinates,
+ &CharsWritten);
+
+ *(PCHAR)((ULONG_PTR)BaseAddress + i) = LOBYTE(Attribute);
+ }
+ }
+ }
+ else
+ {
+ /* Copy the data to the emulator memory */
+ RtlCopyMemory((LPVOID)((ULONG_PTR)BaseAddress + StartAddress),
+ (LPVOID)((ULONG_PTR)ConsoleFramebuffers[CurrentVideoPage]
+ + StartAddress - BiosGetVideoMemoryStart()),
+ EndAddress - StartAddress);
}
}
@@ -231,7 +439,6 @@
WORD BiosGetCharacter()
{
WORD CharacterData;
- HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD InputRecord;
DWORD Count;
@@ -247,10 +454,10 @@
while (TRUE)
{
/* Wait for a console event */
- WaitForSingleObject(ConsoleInput, INFINITE);
+ WaitForSingleObject(BiosConsoleInput, INFINITE);
/* Read the event, and make sure it's a keypress */
- if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count))
continue;
+ if (!ReadConsoleInput(BiosConsoleInput, &InputRecord, 1, &Count))
continue;
if (InputRecord.EventType != KEY_EVENT) continue;
if (!InputRecord.Event.KeyEvent.bKeyDown) continue;
@@ -267,7 +474,6 @@
VOID BiosVideoService()
{
- HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
INT CursorHeight;
BOOLEAN Invisible = FALSE;
COORD Position;
@@ -282,6 +488,13 @@
switch (HIBYTE(Eax))
{
+ /* Set Video Mode */
+ case 0x00:
+ {
+ BiosSetVideoMode(LOBYTE(Eax));
+ break;
+ }
+
/* Set Text-Mode Cursor Shape */
case 0x01:
{
@@ -294,7 +507,7 @@
/* Set the cursor */
CursorInfo.dwSize = (CursorHeight * 100) / CONSOLE_FONT_HEIGHT;
CursorInfo.bVisible = !Invisible;
- SetConsoleCursorInfo(ConsoleOutput, &CursorInfo);
+ SetConsoleCursorInfo(BiosConsoleOutput, &CursorInfo);
break;
}
@@ -305,7 +518,7 @@
Position.X = LOBYTE(Edx);
Position.Y = HIBYTE(Edx);
- SetConsoleCursorPosition(ConsoleOutput, Position);
+ SetConsoleCursorPosition(BiosConsoleOutput, Position);
break;
}
@@ -315,8 +528,8 @@
INT StartLine;
/* Retrieve the data */
- GetConsoleCursorInfo(ConsoleOutput, &CursorInfo);
- GetConsoleScreenBufferInfo(ConsoleOutput, &ScreenBufferInfo);
+ GetConsoleCursorInfo(BiosConsoleOutput, &CursorInfo);
+ GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
/* Find the first line */
StartLine = 32 - ((CursorInfo.dwSize * 32) / 100);
@@ -344,7 +557,7 @@
if (HIBYTE(Eax) == 0x06) Position.Y = Rect.Top - LOBYTE(Eax);
else Position.Y = Rect.Top + LOBYTE(Eax);
- ScrollConsoleScreenBuffer(ConsoleOutput,
+ ScrollConsoleScreenBuffer(BiosConsoleOutput,
&Rect,
&Rect,
Position,
@@ -358,14 +571,14 @@
COORD BufferSize = { 1, 1 }, Origin = { 0, 0 };
/* Get the cursor position */
- GetConsoleScreenBufferInfo(ConsoleOutput, &ScreenBufferInfo);
+ GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
/* Read at cursor position */
Rect.Left = ScreenBufferInfo.dwCursorPosition.X;
Rect.Top = ScreenBufferInfo.dwCursorPosition.Y;
/* Read the console output */
- ReadConsoleOutput(ConsoleOutput, &Character, BufferSize, Origin,
&Rect);
+ ReadConsoleOutput(BiosConsoleOutput, &Character, BufferSize, Origin,
&Rect);
/* Return the result */
EmulatorSetRegister(EMULATOR_REG_AX,
@@ -381,17 +594,17 @@
DWORD CharsWritten;
/* Get the cursor position */
- GetConsoleScreenBufferInfo(ConsoleOutput, &ScreenBufferInfo);
+ GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
/* Write the attribute to the output */
- FillConsoleOutputAttribute(ConsoleOutput,
+ FillConsoleOutputAttribute(BiosConsoleOutput,
LOBYTE(Ebx),
LOWORD(Ecx),
ScreenBufferInfo.dwCursorPosition,
&CharsWritten);
/* Write the character to the output */
- FillConsoleOutputCharacterA(ConsoleOutput,
+ FillConsoleOutputCharacterA(BiosConsoleOutput,
LOBYTE(Eax),
LOWORD(Ecx),
ScreenBufferInfo.dwCursorPosition,
@@ -406,10 +619,10 @@
DWORD CharsWritten;
/* Get the cursor position */
- GetConsoleScreenBufferInfo(ConsoleOutput, &ScreenBufferInfo);
+ GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
/* Write the character to the output */
- FillConsoleOutputCharacterA(ConsoleOutput,
+ FillConsoleOutputCharacterA(BiosConsoleOutput,
LOBYTE(Eax),
LOWORD(Ecx),
ScreenBufferInfo.dwCursorPosition,
@@ -418,11 +631,14 @@
break;
}
+ /* Get Current Video Mode */
case 0x0F:
{
- /* Return just text mode information, for now */
- EmulatorSetRegister(EMULATOR_REG_AX, 0x5003);
- EmulatorSetRegister(EMULATOR_REG_BX, 0x0000);
+ EmulatorSetRegister(EMULATOR_REG_AX,
+ (VideoModes[CurrentVideoMode].Width << 8)
+ | CurrentVideoMode);
+ EmulatorSetRegister(EMULATOR_REG_BX,
+ (CurrentVideoPage << 8) | LOBYTE(Ebx));
break;
}
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] Fri Jul 5 00:08:18 2013
@@ -15,7 +15,6 @@
/* DEFINES ********************************************************************/
-#define CONSOLE_VIDEO_MEM_START 0xB8000
#define CONSOLE_VIDEO_MEM_END 0xBFFFF
#define ROM_AREA_START 0xC0000
#define ROM_AREA_END 0xFFFFF
@@ -26,17 +25,31 @@
#define BIOS_EQUIPMENT_INTERRUPT 0x11
#define BIOS_KBD_INTERRUPT 0x16
#define BIOS_TIME_INTERRUPT 0x1A
-#define CONSOLE_WIDTH 80
-#define CONSOLE_HEIGHT 25
#define CONSOLE_FONT_HEIGHT 8
#define BIOS_KBD_BUFFER_SIZE 256
#define BIOS_EQUIPMENT_LIST 0x3C // HACK: Disable FPU for now
+#define BIOS_DEFAULT_VIDEO_MODE 0x03
+#define BIOS_MAX_PAGES 8
+#define BIOS_MAX_VIDEO_MODE 0x13
+
+typedef struct
+{
+ DWORD Width;
+ DWORD Height;
+ BOOLEAN Text;
+ DWORD Colors;
+ BOOLEAN Gray;
+ BYTE Pages;
+ WORD Segment;
+} VIDEO_MODE;
/* FUNCTIONS ******************************************************************/
BOOLEAN BiosInitialize();
VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress);
VOID BiosUpdateVideoMemory(ULONG StartAddress, ULONG EndAddress);
+inline DWORD BiosGetVideoMemoryStart();
+inline VOID BiosVerticalRefresh();
WORD BiosPeekCharacter();
WORD BiosGetCharacter();
VOID BiosVideoService();
Modified: branches/ntvdm/subsystems/ntvdm/emulator.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] Fri Jul 5 00:08:18 2013
@@ -32,11 +32,11 @@
if ((Address + Size) >= MAX_ADDRESS) return;
/* Are we reading some of the console video memory? */
- if (((Address + Size) >= CONSOLE_VIDEO_MEM_START)
+ if (((Address + Size) >= BiosGetVideoMemoryStart())
&& (Address < CONSOLE_VIDEO_MEM_END))
{
/* Call the VDM BIOS to update the video memory */
- BiosUpdateVideoMemory(max(Address, CONSOLE_VIDEO_MEM_START),
+ BiosUpdateVideoMemory(max(Address, BiosGetVideoMemoryStart()),
min(Address + Size, CONSOLE_VIDEO_MEM_END));
}
@@ -59,11 +59,11 @@
RtlCopyMemory((LPVOID)((ULONG_PTR)BaseAddress + Address), Buffer, Size);
/* Check if we modified the console video memory */
- if (((Address + Size) >= CONSOLE_VIDEO_MEM_START)
+ if (((Address + Size) >= BiosGetVideoMemoryStart())
&& (Address < CONSOLE_VIDEO_MEM_END))
{
/* Call the VDM BIOS to update the screen */
- BiosUpdateConsole(max(Address, CONSOLE_VIDEO_MEM_START),
+ BiosUpdateConsole(max(Address, BiosGetVideoMemoryStart()),
min(Address + Size, CONSOLE_VIDEO_MEM_END));
}
}
Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.c?…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] Fri Jul 5 00:08:18 2013
@@ -73,19 +73,54 @@
DWORD LastTickCount = GetTickCount();
DWORD Cycles = 0;
DWORD LastCyclePrintout = GetTickCount();
+ DWORD LastVerticalRefresh = GetTickCount();
LARGE_INTEGER Frequency, LastTimerTick, Counter;
LONGLONG TimerTicks;
+ HANDLE ConsoleInput = INVALID_HANDLE_VALUE;
+ HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
+ CONSOLE_SCREEN_BUFFER_INFO SavedBufferInfo;
/* Set the handler routine */
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
+ /* Get the input and output handles to the real console */
+ ConsoleInput = CreateFile(TEXT("CONIN$"),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ ConsoleOutput = CreateFile(TEXT("CONOUT$"),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ if ((ConsoleInput == INVALID_HANDLE_VALUE)
+ || (ConsoleOutput == INVALID_HANDLE_VALUE))
+ {
+ wprintf(L"FATAL: Could not get handles to the console\n");
+ goto Cleanup;
+ }
+
+ /* Save the console screen buffer information */
+ if (!GetConsoleScreenBufferInfo(ConsoleOutput, &SavedBufferInfo))
+ {
+ wprintf(L"FATAL: Could not save the console screen buffer
information\n");
+ goto Cleanup;
+ }
+
/* The DOS command line must be ASCII */
WideCharToMultiByte(CP_ACP, 0, GetCommandLine(), -1, CommandLine, 128, NULL, NULL);
if (!EmulatorInitialize())
{
wprintf(L"FATAL: Failed to initialize the CPU emulator\n");
- return 1;
+ goto Cleanup;
}
/* Initialize the performance counter (needed for hardware timers) */
@@ -96,7 +131,7 @@
}
/* Initialize the system BIOS */
- if (!BiosInitialize())
+ if (!BiosInitialize(ConsoleInput, ConsoleOutput))
{
wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n");
goto Cleanup;
@@ -142,6 +177,13 @@
CheckForInputEvents();
LastTickCount = CurrentTickCount;
}
+
+ /* Check for vertical refresh */
+ if ((CurrentTickCount - LastVerticalRefresh) >= 16)
+ {
+ BiosVerticalRefresh();
+ LastVerticalRefresh = CurrentTickCount;
+ }
/* Continue CPU emulation */
for (i = 0; (i < STEPS_PER_CYCLE) && VdmRunning; i++)
@@ -159,7 +201,17 @@
}
Cleanup:
+ /* Restore the old screen buffer */
+ SetConsoleActiveScreenBuffer(ConsoleOutput);
+
+ /* Restore the screen buffer size */
+ SetConsoleScreenBufferSize(ConsoleOutput, SavedBufferInfo.dwSize);
+
EmulatorCleanup();
+
+ /* Close the console handles */
+ if (ConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleInput);
+ if (ConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleOutput);
return 0;
}