Author: aandrejevic
Date: Thu Jul 18 00:01:18 2013
New Revision: 59497
URL:
http://svn.reactos.org/svn/reactos?rev=59497&view=rev
Log:
[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.
Modified:
branches/ntvdm/subsystems/ntvdm/bios.c
branches/ntvdm/subsystems/ntvdm/dos.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] Thu Jul 18 00:01:18 2013
@@ -661,11 +661,10 @@
VOID BiosVideoService()
{
- INT CursorHeight;
+ INT i, CursorHeight;
BOOLEAN Invisible = FALSE;
COORD Position;
CONSOLE_CURSOR_INFO CursorInfo;
- CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo;
CHAR_INFO Character;
SMALL_RECT Rect;
DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX);
@@ -673,7 +672,6 @@
DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX);
DWORD Ebx = EmulatorGetRegister(EMULATOR_REG_BX);
- // TODO: Add support for multiple pages!
switch (HIBYTE(Eax))
{
/* Set Video Mode */
@@ -691,6 +689,10 @@
CursorHeight = (HIBYTE(Ecx) & 0x1F) - (LOBYTE(Ecx) & 0x1F);
if (CursorHeight < 1) CursorHeight = 1;
if (CursorHeight > 100) CursorHeight = 100;
+
+ /* Update the BDA */
+ Bda->CursorStartLine = HIBYTE(Ecx);
+ Bda->CursorEndLine = LOBYTE(Ecx) & 0x1F;
/* Set the cursor */
CursorInfo.dwSize = (CursorHeight * 100) / CONSOLE_FONT_HEIGHT;
@@ -723,20 +725,13 @@
/* Get Cursor Position */
case 0x03:
{
- INT StartLine;
-
/* Make sure the selected video page exists */
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 */
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)]);
break;
@@ -758,9 +753,12 @@
}
/* Scroll Up/Down Window */
+ // TODO: Implement for different pages
case 0x06:
case 0x07:
{
+ BYTE Lines = LOBYTE(Eax);
+
Rect.Top = HIBYTE(Ecx);
Rect.Left = LOBYTE(Ecx);
Rect.Bottom = HIBYTE(Edx);
@@ -769,115 +767,94 @@
Character.Attributes = HIBYTE(Ebx);
Position.X = Rect.Left;
- if (HIBYTE(Eax) == 0x06) Position.Y = Rect.Top - LOBYTE(Eax);
- else Position.Y = Rect.Top + LOBYTE(Eax);
+ /* 0 means clear entire window */
+ 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,
&Rect,
&Rect,
Position,
&Character);
+
break;
}
/* Read Character And Attribute At Cursor Position */
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 */
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 */
- ReadConsoleOutput(BiosConsoleOutput,
- &Character,
- BufferSize,
- Origin,
- &Rect);
-
- /* Return the result */
- EmulatorSetRegister(EMULATOR_REG_AX,
- (LOBYTE(Character.Attributes) << 8)
- | Character.Char.AsciiChar);
- }
- else
- {
- // TODO: NOT IMPLEMENTED
- }
+ /* Find the address */
+ Address = BiosGetVideoMemoryStart()
+ + HIBYTE(Ebx) * BiosGetVideoPageSize()
+ + (HIBYTE(Bda->CursorPosition[HIBYTE(Ebx)])
+ * VideoModes[CurrentVideoMode].Height
+ + LOBYTE(Bda->CursorPosition[HIBYTE(Ebx)]))
+ * VideoModes[CurrentVideoMode].Bpp / 8;
+
+ /* Update the video memory at that address */
+ BiosUpdateVideoMemory(Address,
+ Address + VideoModes[CurrentVideoMode].Bpp / 8);
+
+ /* Return the result in AX */
+ EmulatorSetRegister(EMULATOR_REG_AX,
+ *((LPWORD)((ULONG_PTR)BaseAddress + Address)));
break;
}
/* Write Character And Attribute At Cursor Position */
case 0x09:
- {
- DWORD CharsWritten;
+ case 0x0A:
+ {
+ 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 */
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,
+ (CONSOLE_VIDEO_MEM_END - Address)
+ / PixelSize);
+
+ /* Copy the values to the memory */
+ for (i = 0; i < Repeat; i++)
{
- /* 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);
+ 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;
+ }
}
- else
- {
- // TODO: NOT IMPLEMENTED
- }
-
- break;
- }
-
- /* Write Character Only At Cursor Position */
- case 0x0A:
- {
- 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 character to the output */
- FillConsoleOutputCharacterA(BiosConsoleOutput,
- LOBYTE(Eax),
- LOWORD(Ecx),
- ScreenBufferInfo.dwCursorPosition,
- &CharsWritten);
- }
- else
- {
- // TODO: NOT IMPLEMENTED
- }
+
+ /* Update the range */
+ BiosUpdateConsole(Address,
+ Address + Repeat * (VideoModes[CurrentVideoMode].Bpp /
8));
break;
}
@@ -911,6 +888,32 @@
MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
EmulatorSetRegister(EMULATOR_REG_BX,
MAKEWORD(LOBYTE(Ebx), Bda->VideoPage));
+
+ 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;
}
Modified: branches/ntvdm/subsystems/ntvdm/dos.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] Thu Jul 18 00:01:18 2013
@@ -1393,10 +1393,14 @@
if (Segment != 0)
{
EmulatorSetRegister(EMULATOR_REG_AX, Segment);
+ EmulatorClearFlag(EMULATOR_FLAG_CF);
+ }
+ else
+ {
+ EmulatorSetRegister(EMULATOR_REG_AX, ERROR_NOT_ENOUGH_MEMORY);
EmulatorSetRegister(EMULATOR_REG_BX, MaxAvailable);
- EmulatorClearFlag(EMULATOR_FLAG_CF);
- }
- else EmulatorSetFlag(EMULATOR_FLAG_CF);
+ EmulatorSetFlag(EMULATOR_FLAG_CF);
+ }
break;
}
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] Thu Jul 18 00:01:18 2013
@@ -80,8 +80,12 @@
/* Set the handler routine */
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
+#ifndef TESTING
/* The DOS command line must be ASCII */
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())
{