mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[NTVDM]
Add a compile-time option (not default) to run ntvdm manually with the target executable as a parameter. Fix screen clearing bug. Rewrite several INT 10h functions to work for all video pages. svn path=/branches/ntvdm/; revision=59497
This commit is contained in:
parent
f82876686a
commit
bebaf9e812
3 changed files with 102 additions and 91 deletions
|
@ -661,11 +661,10 @@ WORD BiosGetCharacter()
|
||||||
|
|
||||||
VOID BiosVideoService()
|
VOID BiosVideoService()
|
||||||
{
|
{
|
||||||
INT CursorHeight;
|
INT i, CursorHeight;
|
||||||
BOOLEAN Invisible = FALSE;
|
BOOLEAN Invisible = FALSE;
|
||||||
COORD Position;
|
COORD Position;
|
||||||
CONSOLE_CURSOR_INFO CursorInfo;
|
CONSOLE_CURSOR_INFO CursorInfo;
|
||||||
CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo;
|
|
||||||
CHAR_INFO Character;
|
CHAR_INFO Character;
|
||||||
SMALL_RECT Rect;
|
SMALL_RECT Rect;
|
||||||
DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX);
|
DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX);
|
||||||
|
@ -673,7 +672,6 @@ VOID BiosVideoService()
|
||||||
DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX);
|
DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX);
|
||||||
DWORD Ebx = EmulatorGetRegister(EMULATOR_REG_BX);
|
DWORD Ebx = EmulatorGetRegister(EMULATOR_REG_BX);
|
||||||
|
|
||||||
// TODO: Add support for multiple pages!
|
|
||||||
switch (HIBYTE(Eax))
|
switch (HIBYTE(Eax))
|
||||||
{
|
{
|
||||||
/* Set Video Mode */
|
/* Set Video Mode */
|
||||||
|
@ -692,6 +690,10 @@ VOID BiosVideoService()
|
||||||
if (CursorHeight < 1) CursorHeight = 1;
|
if (CursorHeight < 1) CursorHeight = 1;
|
||||||
if (CursorHeight > 100) CursorHeight = 100;
|
if (CursorHeight > 100) CursorHeight = 100;
|
||||||
|
|
||||||
|
/* Update the BDA */
|
||||||
|
Bda->CursorStartLine = HIBYTE(Ecx);
|
||||||
|
Bda->CursorEndLine = LOBYTE(Ecx) & 0x1F;
|
||||||
|
|
||||||
/* Set the cursor */
|
/* Set the cursor */
|
||||||
CursorInfo.dwSize = (CursorHeight * 100) / CONSOLE_FONT_HEIGHT;
|
CursorInfo.dwSize = (CursorHeight * 100) / CONSOLE_FONT_HEIGHT;
|
||||||
CursorInfo.bVisible = !Invisible;
|
CursorInfo.bVisible = !Invisible;
|
||||||
|
@ -723,20 +725,13 @@ VOID BiosVideoService()
|
||||||
/* Get Cursor Position */
|
/* Get Cursor Position */
|
||||||
case 0x03:
|
case 0x03:
|
||||||
{
|
{
|
||||||
INT StartLine;
|
|
||||||
|
|
||||||
/* Make sure the selected video page exists */
|
/* Make sure the selected video page exists */
|
||||||
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
|
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
|
||||||
|
|
||||||
/* Retrieve the data */
|
|
||||||
GetConsoleCursorInfo(BiosConsoleOutput, &CursorInfo);
|
|
||||||
|
|
||||||
/* Find the first line */
|
|
||||||
StartLine = 32 - ((CursorInfo.dwSize * 32) / 100);
|
|
||||||
|
|
||||||
/* Return the result */
|
/* Return the result */
|
||||||
EmulatorSetRegister(EMULATOR_REG_AX, 0);
|
EmulatorSetRegister(EMULATOR_REG_AX, 0);
|
||||||
EmulatorSetRegister(EMULATOR_REG_CX, (StartLine << 8) | 0x1F);
|
EmulatorSetRegister(EMULATOR_REG_CX,
|
||||||
|
(Bda->CursorStartLine << 8) | Bda->CursorEndLine);
|
||||||
EmulatorSetRegister(EMULATOR_REG_DX, Bda->CursorPosition[HIBYTE(Ebx)]);
|
EmulatorSetRegister(EMULATOR_REG_DX, Bda->CursorPosition[HIBYTE(Ebx)]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -758,9 +753,12 @@ VOID BiosVideoService()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scroll Up/Down Window */
|
/* Scroll Up/Down Window */
|
||||||
|
// TODO: Implement for different pages
|
||||||
case 0x06:
|
case 0x06:
|
||||||
case 0x07:
|
case 0x07:
|
||||||
{
|
{
|
||||||
|
BYTE Lines = LOBYTE(Eax);
|
||||||
|
|
||||||
Rect.Top = HIBYTE(Ecx);
|
Rect.Top = HIBYTE(Ecx);
|
||||||
Rect.Left = LOBYTE(Ecx);
|
Rect.Left = LOBYTE(Ecx);
|
||||||
Rect.Bottom = HIBYTE(Edx);
|
Rect.Bottom = HIBYTE(Edx);
|
||||||
|
@ -769,116 +767,95 @@ VOID BiosVideoService()
|
||||||
Character.Attributes = HIBYTE(Ebx);
|
Character.Attributes = HIBYTE(Ebx);
|
||||||
Position.X = Rect.Left;
|
Position.X = Rect.Left;
|
||||||
|
|
||||||
if (HIBYTE(Eax) == 0x06) Position.Y = Rect.Top - LOBYTE(Eax);
|
/* 0 means clear entire window */
|
||||||
else Position.Y = Rect.Top + LOBYTE(Eax);
|
if (Lines == 0) Lines = Rect.Bottom - Rect.Top;
|
||||||
|
|
||||||
|
if (HIBYTE(Eax) == 0x06) Position.Y = Rect.Top - Lines;
|
||||||
|
else Position.Y = Rect.Top + Lines;
|
||||||
|
|
||||||
ScrollConsoleScreenBuffer(BiosConsoleOutput,
|
ScrollConsoleScreenBuffer(BiosConsoleOutput,
|
||||||
&Rect,
|
&Rect,
|
||||||
&Rect,
|
&Rect,
|
||||||
Position,
|
Position,
|
||||||
&Character);
|
&Character);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read Character And Attribute At Cursor Position */
|
/* Read Character And Attribute At Cursor Position */
|
||||||
case 0x08:
|
case 0x08:
|
||||||
{
|
{
|
||||||
COORD BufferSize = { 1, 1 }, Origin = { 0, 0 };
|
DWORD Address;
|
||||||
|
|
||||||
|
/* Make sure this is text mode */
|
||||||
|
if (!VideoModes[CurrentVideoMode].Text) break;
|
||||||
|
|
||||||
/* Make sure the selected video page exists */
|
/* Make sure the selected video page exists */
|
||||||
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
|
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
|
||||||
|
|
||||||
if (HIBYTE(Ebx) == CurrentVideoPage)
|
|
||||||
{
|
|
||||||
/* Get the cursor position */
|
|
||||||
GetConsoleScreenBufferInfo(BiosConsoleOutput,
|
|
||||||
&ScreenBufferInfo);
|
|
||||||
|
|
||||||
/* Read at cursor position */
|
|
||||||
Rect.Left = ScreenBufferInfo.dwCursorPosition.X;
|
|
||||||
Rect.Top = ScreenBufferInfo.dwCursorPosition.Y;
|
|
||||||
|
|
||||||
/* Read the console output */
|
/* Find the address */
|
||||||
ReadConsoleOutput(BiosConsoleOutput,
|
Address = BiosGetVideoMemoryStart()
|
||||||
&Character,
|
+ HIBYTE(Ebx) * BiosGetVideoPageSize()
|
||||||
BufferSize,
|
+ (HIBYTE(Bda->CursorPosition[HIBYTE(Ebx)])
|
||||||
Origin,
|
* VideoModes[CurrentVideoMode].Height
|
||||||
&Rect);
|
+ LOBYTE(Bda->CursorPosition[HIBYTE(Ebx)]))
|
||||||
|
* VideoModes[CurrentVideoMode].Bpp / 8;
|
||||||
|
|
||||||
/* Return the result */
|
/* Update the video memory at that address */
|
||||||
EmulatorSetRegister(EMULATOR_REG_AX,
|
BiosUpdateVideoMemory(Address,
|
||||||
(LOBYTE(Character.Attributes) << 8)
|
Address + VideoModes[CurrentVideoMode].Bpp / 8);
|
||||||
| Character.Char.AsciiChar);
|
|
||||||
}
|
/* Return the result in AX */
|
||||||
else
|
EmulatorSetRegister(EMULATOR_REG_AX,
|
||||||
{
|
*((LPWORD)((ULONG_PTR)BaseAddress + Address)));
|
||||||
// TODO: NOT IMPLEMENTED
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write Character And Attribute At Cursor Position */
|
/* Write Character And Attribute At Cursor Position */
|
||||||
case 0x09:
|
case 0x09:
|
||||||
{
|
|
||||||
DWORD CharsWritten;
|
|
||||||
|
|
||||||
/* Make sure the selected video page exists */
|
|
||||||
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
|
|
||||||
|
|
||||||
if (HIBYTE(Ebx) == CurrentVideoPage)
|
|
||||||
{
|
|
||||||
/* Get the cursor position */
|
|
||||||
GetConsoleScreenBufferInfo(BiosConsoleOutput,
|
|
||||||
&ScreenBufferInfo);
|
|
||||||
|
|
||||||
/* Write the attribute to the output */
|
|
||||||
FillConsoleOutputAttribute(BiosConsoleOutput,
|
|
||||||
LOBYTE(Ebx),
|
|
||||||
LOWORD(Ecx),
|
|
||||||
ScreenBufferInfo.dwCursorPosition,
|
|
||||||
&CharsWritten);
|
|
||||||
|
|
||||||
/* Write the character to the output */
|
|
||||||
FillConsoleOutputCharacterA(BiosConsoleOutput,
|
|
||||||
LOBYTE(Eax),
|
|
||||||
LOWORD(Ecx),
|
|
||||||
ScreenBufferInfo.dwCursorPosition,
|
|
||||||
&CharsWritten);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: NOT IMPLEMENTED
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write Character Only At Cursor Position */
|
|
||||||
case 0x0A:
|
case 0x0A:
|
||||||
{
|
{
|
||||||
DWORD CharsWritten;
|
BYTE PixelSize = VideoModes[CurrentVideoMode].Bpp / 8;
|
||||||
|
WORD Data = (LOBYTE(Ebx) << 8) | LOBYTE(Eax);
|
||||||
|
WORD Repeat = LOWORD(Ecx);
|
||||||
|
DWORD Address = BiosGetVideoMemoryStart()
|
||||||
|
+ CurrentVideoPage * BiosGetVideoPageSize()
|
||||||
|
+ (HIBYTE(Bda->CursorPosition[CurrentVideoPage])
|
||||||
|
* VideoModes[CurrentVideoMode].Height
|
||||||
|
+ LOBYTE(Bda->CursorPosition[CurrentVideoPage]))
|
||||||
|
* PixelSize;
|
||||||
|
|
||||||
|
/* Make sure this is text mode */
|
||||||
|
if (!VideoModes[CurrentVideoMode].Text) break;
|
||||||
|
|
||||||
/* Make sure the selected video page exists */
|
/* Make sure the selected video page exists */
|
||||||
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
|
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
|
||||||
|
|
||||||
if (HIBYTE(Ebx) == CurrentVideoPage)
|
/* Make sure we don't write over the end of video memory */
|
||||||
{
|
Repeat = min(Repeat,
|
||||||
/* Get the cursor position */
|
(CONSOLE_VIDEO_MEM_END - Address)
|
||||||
GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
|
/ PixelSize);
|
||||||
|
|
||||||
/* Write the character to the output */
|
/* Copy the values to the memory */
|
||||||
FillConsoleOutputCharacterA(BiosConsoleOutput,
|
for (i = 0; i < Repeat; i++)
|
||||||
LOBYTE(Eax),
|
|
||||||
LOWORD(Ecx),
|
|
||||||
ScreenBufferInfo.dwCursorPosition,
|
|
||||||
&CharsWritten);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// TODO: NOT IMPLEMENTED
|
if (PixelSize == sizeof(BYTE) || HIBYTE(Eax) == 0x0A)
|
||||||
|
{
|
||||||
|
/* Just characters, no attributes */
|
||||||
|
*((LPBYTE)((ULONG_PTR)BaseAddress + Address) + i * PixelSize) = LOBYTE(Data);
|
||||||
|
}
|
||||||
|
else if (PixelSize == sizeof(WORD))
|
||||||
|
{
|
||||||
|
/* First byte for characters, second for attributes */
|
||||||
|
*((LPWORD)((ULONG_PTR)BaseAddress + Address) + i) = Data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the range */
|
||||||
|
BiosUpdateConsole(Address,
|
||||||
|
Address + Repeat * (VideoModes[CurrentVideoMode].Bpp / 8));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,6 +892,32 @@ VOID BiosVideoService()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scroll Window */
|
||||||
|
case 0x12:
|
||||||
|
{
|
||||||
|
Rect.Top = HIBYTE(Ecx);
|
||||||
|
Rect.Left = LOBYTE(Ecx);
|
||||||
|
Rect.Bottom = HIBYTE(Edx);
|
||||||
|
Rect.Right = LOBYTE(Edx);
|
||||||
|
Character.Char.UnicodeChar = L' ';
|
||||||
|
Character.Attributes = 0x07;
|
||||||
|
Position.X = Rect.Left;
|
||||||
|
Position.Y = Rect.Top;
|
||||||
|
|
||||||
|
if (LOBYTE(Ebx) == 0) Position.Y -= LOBYTE(Eax);
|
||||||
|
else if (LOBYTE(Ebx) == 1) Position.Y += LOBYTE(Eax);
|
||||||
|
else if (LOBYTE(Ebx) == 2) Position.X -= LOBYTE(Eax);
|
||||||
|
else if (LOBYTE(Ebx) == 3) Position.X += LOBYTE(Eax);
|
||||||
|
|
||||||
|
ScrollConsoleScreenBuffer(BiosConsoleOutput,
|
||||||
|
&Rect,
|
||||||
|
&Rect,
|
||||||
|
Position,
|
||||||
|
&Character);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n",
|
DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n",
|
||||||
|
|
|
@ -1393,10 +1393,14 @@ VOID DosInt21h(WORD CodeSegment)
|
||||||
if (Segment != 0)
|
if (Segment != 0)
|
||||||
{
|
{
|
||||||
EmulatorSetRegister(EMULATOR_REG_AX, Segment);
|
EmulatorSetRegister(EMULATOR_REG_AX, Segment);
|
||||||
EmulatorSetRegister(EMULATOR_REG_BX, MaxAvailable);
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_CF);
|
EmulatorClearFlag(EMULATOR_FLAG_CF);
|
||||||
}
|
}
|
||||||
else EmulatorSetFlag(EMULATOR_FLAG_CF);
|
else
|
||||||
|
{
|
||||||
|
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
EmulatorSetRegister(EMULATOR_REG_BX, MaxAvailable);
|
||||||
|
EmulatorSetFlag(EMULATOR_FLAG_CF);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,8 +80,12 @@ INT wmain(INT argc, WCHAR *argv[])
|
||||||
/* Set the handler routine */
|
/* Set the handler routine */
|
||||||
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
|
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
/* The DOS command line must be ASCII */
|
/* The DOS command line must be ASCII */
|
||||||
WideCharToMultiByte(CP_ACP, 0, GetCommandLine(), -1, CommandLine, 128, NULL, NULL);
|
WideCharToMultiByte(CP_ACP, 0, GetCommandLine(), -1, CommandLine, 128, NULL, NULL);
|
||||||
|
#else
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, argv[1], -1, CommandLine, 128, NULL, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!EmulatorInitialize())
|
if (!EmulatorInitialize())
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue