diff --git a/subsystems/ntvdm/bios/bios.c b/subsystems/ntvdm/bios/bios.c index edc69efd3c6..9674d0eea2f 100644 --- a/subsystems/ntvdm/bios/bios.c +++ b/subsystems/ntvdm/bios/bios.c @@ -86,8 +86,7 @@ static VOID WINAPI BiosInitBop(LPWORD Stack) /* PUBLIC FUNCTIONS ***********************************************************/ BOOLEAN -BiosInitialize(IN LPCSTR BiosFileName, - IN HANDLE ConsoleOutput) +BiosInitialize(IN LPCSTR BiosFileName) { /* Register the BIOS support BOPs */ RegisterBop(BOP_BIOSINIT, BiosInitBop); @@ -143,7 +142,7 @@ BiosInitialize(IN LPCSTR BiosFileName, } else { - Bios32Loaded = Bios32Initialize(ConsoleOutput); + Bios32Loaded = Bios32Initialize(); return Bios32Loaded; } } diff --git a/subsystems/ntvdm/bios/bios.h b/subsystems/ntvdm/bios/bios.h index 984f31a4942..909afdfc6bf 100644 --- a/subsystems/ntvdm/bios/bios.h +++ b/subsystems/ntvdm/bios/bios.h @@ -106,8 +106,7 @@ C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133); extern PBIOS_DATA_AREA Bda; BOOLEAN -BiosInitialize(IN LPCSTR BiosFileName, - IN HANDLE ConsoleOutput); +BiosInitialize(IN LPCSTR BiosFileName); VOID BiosCleanup(VOID); diff --git a/subsystems/ntvdm/bios/bios32/bios32.c b/subsystems/ntvdm/bios/bios32/bios32.c index 47ddccf9fd8..9041409b98c 100644 --- a/subsystems/ntvdm/bios/bios32/bios32.c +++ b/subsystems/ntvdm/bios/bios32/bios32.c @@ -361,7 +361,7 @@ static VOID InitializeBiosInt32(VOID) /* * The BIOS POST (Power On-Self Test) */ -BOOLEAN Bios32Initialize(IN HANDLE ConsoleOutput) +BOOLEAN Bios32Initialize(VOID) { BOOLEAN Success; UCHAR Low, High; @@ -403,7 +403,7 @@ BOOLEAN Bios32Initialize(IN HANDLE ConsoleOutput) if (!KbdBios32Initialize()) return FALSE; /* Initialize the Video BIOS */ - if (!VidBios32Initialize(ConsoleOutput)) return FALSE; + if (!VidBios32Initialize()) return FALSE; /* Enable interrupts */ setIF(1); diff --git a/subsystems/ntvdm/bios/bios32/bios32.h b/subsystems/ntvdm/bios/bios32/bios32.h index 4104ee4d76c..1ee601e2827 100644 --- a/subsystems/ntvdm/bios/bios32/bios32.h +++ b/subsystems/ntvdm/bios/bios32/bios32.h @@ -129,7 +129,7 @@ extern PBIOS_DATA_AREA Bda; VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func); VOID PicIRQComplete(LPWORD Stack); -BOOLEAN Bios32Initialize(IN HANDLE ConsoleOutput); +BOOLEAN Bios32Initialize(VOID); VOID Bios32Cleanup(VOID); #endif // _BIOS32_H_ diff --git a/subsystems/ntvdm/bios/bios32/vidbios32.c b/subsystems/ntvdm/bios/bios32/vidbios32.c index acb1480078c..336f6b0d018 100644 --- a/subsystems/ntvdm/bios/bios32/vidbios32.c +++ b/subsystems/ntvdm/bios/bios32/vidbios32.c @@ -733,58 +733,6 @@ Done: return TRUE; } -static VOID VidBiosCopyTextConsoleToVgaMemory(HANDLE ConsoleOutput, PCOORD ConsoleSize) -{ - PCHAR_INFO CharBuffer; - COORD BufferSize = {Bda->ScreenColumns, Bda->ScreenRows + 1}; - COORD Origin = { 0, 0 }; - SMALL_RECT ConRect; - - INT i, j; - INT Counter = 0; - WORD Character; - DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize); - - /* Allocate a temporary buffer for ReadConsoleOutput */ - CharBuffer = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - BufferSize.X * BufferSize.Y - * sizeof(CHAR_INFO)); - if (CharBuffer == NULL) return; - - ConRect.Left = 0; - ConRect.Top = ConsoleSize->Y - BufferSize.Y; - ConRect.Right = ConRect.Left + BufferSize.X - 1; - ConRect.Bottom = ConRect.Top + BufferSize.Y - 1; - - /* Read the data from the console into the temporary buffer... */ - ReadConsoleOutputA(ConsoleOutput, - CharBuffer, - BufferSize, - Origin, - &ConRect); - - /* ... and copy the temporary buffer into the VGA memory */ - for (i = 0; i < BufferSize.Y; i++) - { - for (j = 0; j < BufferSize.X; j++) - { - Character = MAKEWORD(CharBuffer[Counter].Char.AsciiChar, - (BYTE)CharBuffer[Counter].Attributes); - ++Counter; - - /* Write to video memory */ - EmulatorWriteMemory(&EmulatorContext, - VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD), - (LPVOID)&Character, - sizeof(WORD)); - } - } - - /* Free the temporary buffer */ - HeapFree(GetProcessHeap(), 0, CharBuffer); -} - static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers) { INT i; @@ -925,6 +873,24 @@ static VOID VgaChangePalette(BYTE ModeNumber) VgaSetPalette(Palette, Size); } +static VOID VgaGetCursorPosition(PBYTE Row, PBYTE Column) +{ + SHORT ScreenColumns = VgaGetDisplayResolution().X; + BYTE OffsetLow, OffsetHigh; + WORD Offset; + + /* Get the cursor location */ + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG); + OffsetLow = IOReadB(VGA_CRTC_DATA); + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG); + OffsetHigh = IOReadB(VGA_CRTC_DATA); + + Offset = MAKEWORD(OffsetLow, OffsetHigh); + + *Row = (BYTE)(Offset / ScreenColumns); + *Column = (BYTE)(Offset % ScreenColumns); +} + static VOID VidBiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page) { /* Make sure the selected video page is valid */ @@ -1000,10 +966,11 @@ static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber) IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG); IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset)); - /* Get the character height */ + /* Update the character height */ IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_MAX_SCAN_LINE_REG); Bda->CharacterHeight = 1 + (IOReadB(VGA_CRTC_DATA) & 0x1F); + /* Update the screen size */ Resolution = VgaGetDisplayResolution(); Bda->ScreenColumns = Resolution.X; Bda->ScreenRows = Resolution.Y - 1; @@ -1012,6 +979,9 @@ static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber) for (Page = 0; Page < BIOS_MAX_PAGES; ++Page) VidBiosSetCursorPosition(0, 0, Page); + /* Refresh display */ + VgaRefreshDisplay(); + return TRUE; } @@ -1533,8 +1503,10 @@ static VOID WINAPI VidBiosVideoService(LPWORD Stack) /* PUBLIC FUNCTIONS ***********************************************************/ -BOOLEAN VidBios32Initialize(HANDLE ConsoleOutput) +BOOLEAN VidBios32Initialize(VOID) { + BYTE Row, Column; + /* Some interrupts are in fact addresses to tables */ ((PULONG)BaseAddress)[0x1D] = (ULONG)NULL; ((PULONG)BaseAddress)[0x1F] = (ULONG)NULL; @@ -1545,21 +1517,9 @@ BOOLEAN VidBios32Initialize(HANDLE ConsoleOutput) /* Set the default video mode */ VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE); - /* Set some screen properties if the console output handle is valid */ - if (ConsoleOutput != INVALID_HANDLE_VALUE) - { - CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; - - GetConsoleScreenBufferInfo(ConsoleOutput, &ConsoleInfo); - - /* Copy console data into VGA memory */ - VidBiosCopyTextConsoleToVgaMemory(ConsoleOutput, &ConsoleInfo.dwSize); - - /* Update the cursor position for the current page */ - VidBiosSetCursorPosition(ConsoleInfo.dwCursorPosition.Y, - ConsoleInfo.dwCursorPosition.X, - Bda->VideoPage); - } + /* Update cursor position */ + VgaGetCursorPosition(&Row, &Column); + VidBiosSetCursorPosition(Row, Column, Bda->VideoPage); /* Register the BIOS 32-bit Interrupts */ RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService); diff --git a/subsystems/ntvdm/bios/bios32/vidbios32.h b/subsystems/ntvdm/bios/bios32/vidbios32.h index 3610133bf30..39a4d515a63 100644 --- a/subsystems/ntvdm/bios/bios32/vidbios32.h +++ b/subsystems/ntvdm/bios/bios32/vidbios32.h @@ -36,7 +36,7 @@ enum /* FUNCTIONS ******************************************************************/ -BOOLEAN VidBios32Initialize(HANDLE BiosConsoleOutput); +BOOLEAN VidBios32Initialize(VOID); VOID VidBios32Cleanup(VOID); #endif // _VIDBIOS32_H_ diff --git a/subsystems/ntvdm/emulator.c b/subsystems/ntvdm/emulator.c index ab2fabed94b..e843ca01e4c 100644 --- a/subsystems/ntvdm/emulator.c +++ b/subsystems/ntvdm/emulator.c @@ -380,13 +380,14 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) /* Register the I/O Ports */ RegisterIoPort(CONTROL_SYSTEM_PORT61H, Port61hRead, Port61hWrite); - /* Initialize the PS2 port */ - PS2Initialize(ConsoleInput); - /* Set the console input mode */ // FIXME: Activate ENABLE_WINDOW_INPUT when we will want to perform actions // upon console window events (screen buffer resize, ...). SetConsoleMode(ConsoleInput, ENABLE_PROCESSED_INPUT /* | ENABLE_WINDOW_INPUT */); + // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); + + /* Initialize the PS2 port */ + PS2Initialize(ConsoleInput); /* Start the input thread */ InputThread = CreateThread(NULL, 0, &PumpConsoleInput, ConsoleInput, 0, NULL); diff --git a/subsystems/ntvdm/hardware/vga.c b/subsystems/ntvdm/hardware/vga.c index 7aa44f12566..cd471fcad86 100644 --- a/subsystems/ntvdm/hardware/vga.c +++ b/subsystems/ntvdm/hardware/vga.c @@ -402,12 +402,21 @@ __InvalidateConsoleDIBits(IN HANDLE hConsoleOutput, /* PRIVATE FUNCTIONS **********************************************************/ +static inline DWORD VgaGetAddressSize(VOID); + static BOOL VgaAttachToConsole(PCOORD Resolution) { - BOOL Success = FALSE; + BOOL Success; ULONG Length = 0; PVIDEO_HARDWARE_STATE_HEADER State; + SHORT i, j; + DWORD AddressSize, ScanlineSize; + DWORD Address = 0; + DWORD CurrentAddr; + SMALL_RECT ScreenRect; // ConRect; + COORD Origin = { 0, 0 }; + ASSERT(TextFramebuffer == NULL); // ResetEvent(AnotherEvent); @@ -442,9 +451,53 @@ static BOOL VgaAttachToConsole(PCOORD Resolution) { DisplayMessage(L"RegisterConsoleVDM failed with error %d\n", GetLastError()); VdmRunning = FALSE; + return FALSE; } - return Success; + /* Copy console data into VGA memory */ + + /* Get the data */ + AddressSize = VgaGetAddressSize(); + ScreenRect.Left = ScreenRect.Top = 0; + ScreenRect.Right = TextResolution.X; + ScreenRect.Bottom = TextResolution.Y; + + // ConRect.Left = 0; + // ConRect.Top = ConsoleSize->Y - BufferSize.Y; + // ConRect.Right = ConRect.Left + BufferSize.X - 1; + // ConRect.Bottom = ConRect.Top + BufferSize.Y - 1; + + ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2; + + /* Read the data from the console into the framebuffer... */ + ReadConsoleOutputA(TextConsoleBuffer, + CharBuff, + TextResolution, + Origin, + &ScreenRect); // &ConRect); + + /* ... and copy the framebuffer into the VGA memory */ + + /* Loop through the scanlines */ + for (i = 0; i < TextResolution.Y; i++) + { + /* Loop through the characters */ + for (j = 0; j < TextResolution.X; j++) + { + CurrentAddr = LOWORD((Address + j) * AddressSize); + + /* Store the character in plane 0 */ + VgaMemory[CurrentAddr] = CharBuff[i * TextResolution.X + j].Char.AsciiChar; + + /* Store the attribute in plane 1 */ + VgaMemory[CurrentAddr + VGA_BANK_SIZE] = (BYTE)CharBuff[i * TextResolution.X + j].Attributes; + } + + /* Move to the next scanline */ + Address += ScanlineSize; + } + + return TRUE; } static VOID VgaDetachFromConsole(VOID) @@ -893,12 +946,14 @@ static BOOL VgaEnterTextMode(PCOORD Resolution) { SMALL_RECT ConRect; + DPRINT1("VgaEnterTextMode\n"); + /* Switch to the text buffer */ SetConsoleActiveScreenBuffer(TextConsoleBuffer); /* Resize the console */ ConRect.Left = 0; // ConsoleInfo.srWindow.Left; - ConRect.Top = ConsoleInfo.srWindow.Top; + ConRect.Top = ConsoleInfo.srWindow.Top; // ConsoleSize->Y - Resolution->Y; ConRect.Right = ConRect.Left + Resolution->X - 1; ConRect.Bottom = ConRect.Top + Resolution->Y - 1; /* @@ -919,6 +974,8 @@ static BOOL VgaEnterTextMode(PCOORD Resolution) if (TextResolution.X != Resolution->X || TextResolution.Y != Resolution->Y) { + WORD Offset; + VgaDetachFromConsole(); /* VgaAttachToConsole sets TextResolution to the new resolution */ @@ -928,6 +985,14 @@ static BOOL VgaEnterTextMode(PCOORD Resolution) VdmRunning = FALSE; return FALSE; } + + /* Update the cursor position in the registers */ + Offset = ConsoleInfo.dwCursorPosition.Y * Resolution->X + + ConsoleInfo.dwCursorPosition.X; + DPRINT1("X = %d ; Y = %d\n", ConsoleInfo.dwCursorPosition.X, ConsoleInfo.dwCursorPosition.Y); + VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG] = LOBYTE(Offset); + VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG] = HIBYTE(Offset); + CursorMoved = TRUE; } /* The active framebuffer is now the text framebuffer */ @@ -1217,8 +1282,8 @@ static VOID VgaUpdateFramebuffer(VOID) CharInfo.Attributes = VgaMemory[CurrentAddr + VGA_BANK_SIZE]; /* Now check if the resulting character data has changed */ - if ((CharBuffer[i * Resolution.X + j].Char != CharInfo.Char) - || (CharBuffer[i * Resolution.X + j].Attributes != CharInfo.Attributes)) + if ((CharBuffer[i * Resolution.X + j].Char != CharInfo.Char) || + (CharBuffer[i * Resolution.X + j].Attributes != CharInfo.Attributes)) { /* Yes, write the new value */ CharBuffer[i * Resolution.X + j] = CharInfo; @@ -1265,8 +1330,10 @@ static VOID VgaUpdateTextCursor(VOID) Location += (VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] >> 5) & 3; /* Find the coordinates of the new position */ - Position.X = (WORD)(Location % ScanlineSize); - Position.Y = (WORD)(Location / ScanlineSize); + Position.X = (SHORT)(Location % ScanlineSize); + Position.Y = (SHORT)(Location / ScanlineSize); + + DPRINT1("VgaUpdateTextCursor: X = %d ; Y = %d\n", Position.X, Position.Y); /* Update the physical cursor */ SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo); diff --git a/subsystems/ntvdm/ntvdm.c b/subsystems/ntvdm/ntvdm.c index 3e2180f5846..a86cfba7a8e 100644 --- a/subsystems/ntvdm/ntvdm.c +++ b/subsystems/ntvdm/ntvdm.c @@ -151,7 +151,16 @@ static VOID ShowHideMousePointer(HANDLE ConOutHandle, BOOLEAN ShowPtr) { WCHAR szMenuString[255] = L""; - ShowConsoleCursor(ConOutHandle, ShowPtr); + if (ShowPtr) + { + /* Be sure the cursor will be shown */ + while (ShowConsoleCursor(ConOutHandle, TRUE) < 0) ; + } + else + { + /* Be sure the cursor will be hidden */ + while (ShowConsoleCursor(ConOutHandle, FALSE) >= 0) ; + } if (LoadStringW(GetModuleHandle(NULL), (!ShowPtr ? IDS_SHOW_MOUSE : IDS_HIDE_MOUSE), @@ -400,7 +409,7 @@ INT wmain(INT argc, WCHAR *argv[]) } /* Initialize the system BIOS */ - if (!BiosInitialize(NULL, ConsoleOutput)) + if (!BiosInitialize(NULL)) { wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n"); goto Cleanup;