From: Aleksandar Andrejevic Date: Thu, 18 Jul 2013 00:01:18 +0000 (+0000) Subject: [NTVDM] X-Git-Tag: backups/0.3.17@66124~1365^2~554 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=bebaf9e812fdf206ccf6895f4e7182cfa1411aba [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 --- diff --git a/subsystems/ntvdm/bios.c b/subsystems/ntvdm/bios.c index ba930ee46c9..1dad7276f74 100644 --- a/subsystems/ntvdm/bios.c +++ b/subsystems/ntvdm/bios.c @@ -661,11 +661,10 @@ WORD BiosGetCharacter() 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 @@ VOID BiosVideoService() DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX); DWORD Ebx = EmulatorGetRegister(EMULATOR_REG_BX); - // TODO: Add support for multiple pages! switch (HIBYTE(Eax)) { /* Set Video Mode */ @@ -692,6 +690,10 @@ VOID BiosVideoService() 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; CursorInfo.bVisible = !Invisible; @@ -723,20 +725,13 @@ VOID BiosVideoService() /* 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 @@ VOID BiosVideoService() } /* 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 @@ VOID BiosVideoService() 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: + 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 */ 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); + /* Make sure we don't write over the end of video memory */ + Repeat = min(Repeat, + (CONSOLE_VIDEO_MEM_END - Address) + / PixelSize); - /* Write the character to the output */ - FillConsoleOutputCharacterA(BiosConsoleOutput, - LOBYTE(Eax), - LOWORD(Ecx), - ScreenBufferInfo.dwCursorPosition, - &CharsWritten); - } - else + /* Copy the values to the memory */ + for (i = 0; i < Repeat; i++) { - // 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; + } } - 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; } @@ -915,6 +892,32 @@ VOID BiosVideoService() 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: { DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n", diff --git a/subsystems/ntvdm/dos.c b/subsystems/ntvdm/dos.c index 7d2b2936add..d89c8c2075e 100644 --- a/subsystems/ntvdm/dos.c +++ b/subsystems/ntvdm/dos.c @@ -1393,10 +1393,14 @@ VOID DosInt21h(WORD CodeSegment) if (Segment != 0) { EmulatorSetRegister(EMULATOR_REG_AX, Segment); - EmulatorSetRegister(EMULATOR_REG_BX, MaxAvailable); 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; } diff --git a/subsystems/ntvdm/ntvdm.c b/subsystems/ntvdm/ntvdm.c index ca5ef84f735..5f0d0545986 100644 --- a/subsystems/ntvdm/ntvdm.c +++ b/subsystems/ntvdm/ntvdm.c @@ -80,8 +80,12 @@ INT wmain(INT argc, WCHAR *argv[]) /* 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()) {