mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-01 12:23:29 +00:00
[NTVDM]
- Finally get rid of console output handles in the BIOS. - Move console text buffer copy from BIOS back into VGA memory (~= revert part of r61542), but do it ONLY when attaching the VGA emulation to the console. - Fix cursor positioning in BIOS & VGA (work in progress). - Initialize PS/2 after having setting basic console modes. - Showing/hiding mouse cursor (see the option in the console menu) is done in while() loops to be sure the cursor is really shown/hidden (based on the return value of ShowConsoleCursor). svn path=/branches/ntvdm/; revision=62373
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -36,7 +36,7 @@ enum
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOLEAN VidBios32Initialize(HANDLE BiosConsoleOutput);
|
||||
BOOLEAN VidBios32Initialize(VOID);
|
||||
VOID VidBios32Cleanup(VOID);
|
||||
|
||||
#endif // _VIDBIOS32_H_
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user