mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
[NTVDM]
Restore the console to normal size while no DOS task is running and keep track of the cursor position. Adapted from a patch by Hermès Bélusca-Maïto. svn path=/branches/ntvdm/; revision=63119
This commit is contained in:
parent
accafb817a
commit
fdf472cb6e
4 changed files with 126 additions and 95 deletions
|
@ -20,6 +20,9 @@
|
|||
#include "dem.h"
|
||||
#include "bop.h"
|
||||
|
||||
#include "bios/bios.h"
|
||||
#include "hardware/vga.h"
|
||||
|
||||
/* Extra PSDK/NDK Headers */
|
||||
#include <ndk/obtypes.h>
|
||||
|
||||
|
@ -117,7 +120,7 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
|
|||
STARTUPINFOA StartupInfo;
|
||||
PROCESS_INFORMATION ProcessInformation;
|
||||
|
||||
/* Remove return carriage character */
|
||||
/* NULL-terminate the command by removing the return carriage character */
|
||||
while (*CmdPtr != '\r') CmdPtr++;
|
||||
*CmdPtr = '\0';
|
||||
|
||||
|
@ -135,7 +138,8 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
|
|||
|
||||
StartupInfo.cb = sizeof(StartupInfo);
|
||||
|
||||
DosPrintCharacter('\n');
|
||||
VgaRefreshDisplay();
|
||||
VgaDetachFromConsole(FALSE);
|
||||
|
||||
Result = CreateProcessA(NULL,
|
||||
CommandLine,
|
||||
|
@ -166,8 +170,10 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
|
|||
DPRINT1("Failed when launched command '%s'\n");
|
||||
dwExitCode = GetLastError();
|
||||
}
|
||||
|
||||
DosPrintCharacter('\n');
|
||||
|
||||
VgaAttachToConsole();
|
||||
VgaRefreshDisplay();
|
||||
VidBiosSyncCursorPosition();
|
||||
|
||||
setAL((UCHAR)dwExitCode);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "emulator.h"
|
||||
#include "vga.h"
|
||||
#include "../bios/vidbios.h"
|
||||
|
||||
#include "io.h"
|
||||
|
||||
|
@ -189,6 +190,10 @@ static HANDLE StartEvent = NULL;
|
|||
static HANDLE EndEvent = NULL;
|
||||
static HANDLE AnotherEvent = NULL;
|
||||
|
||||
static CONSOLE_CURSOR_INFO OrgConsoleCursorInfo;
|
||||
static CONSOLE_SCREEN_BUFFER_INFO OrgConsoleBufferInfo;
|
||||
|
||||
|
||||
/*
|
||||
* Text mode -- we always keep a valid text mode framebuffer
|
||||
* even if we are in graphics mode. This is needed in order to
|
||||
|
@ -403,8 +408,24 @@ __InvalidateConsoleDIBits(IN HANDLE hConsoleOutput,
|
|||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static inline DWORD VgaGetAddressSize(VOID);
|
||||
static VOID VgaUpdateTextCursor(VOID);
|
||||
|
||||
static BOOL VgaAttachToConsole(PCOORD Resolution)
|
||||
static VOID VgaUpdateCursorPosition(VOID)
|
||||
{
|
||||
/*
|
||||
* Update the cursor position in the VGA registers.
|
||||
*/
|
||||
WORD Offset = ConsoleInfo.dwCursorPosition.Y * TextResolution.X +
|
||||
ConsoleInfo.dwCursorPosition.X;
|
||||
|
||||
VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG] = LOBYTE(Offset);
|
||||
VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG] = HIBYTE(Offset);
|
||||
|
||||
VidBiosSyncCursorPosition();
|
||||
VgaUpdateTextCursor();
|
||||
}
|
||||
|
||||
static BOOL VgaAttachToConsoleInternal(PCOORD Resolution)
|
||||
{
|
||||
BOOL Success;
|
||||
ULONG Length = 0;
|
||||
|
@ -414,13 +435,11 @@ static BOOL VgaAttachToConsole(PCOORD Resolution)
|
|||
DWORD AddressSize, ScanlineSize;
|
||||
DWORD Address = 0;
|
||||
DWORD CurrentAddr;
|
||||
SMALL_RECT ScreenRect; // ConRect;
|
||||
SMALL_RECT ConRect;
|
||||
COORD Origin = { 0, 0 };
|
||||
|
||||
ASSERT(TextFramebuffer == NULL);
|
||||
|
||||
// ResetEvent(AnotherEvent);
|
||||
|
||||
TextResolution = *Resolution;
|
||||
|
||||
/*
|
||||
|
@ -454,19 +473,36 @@ static BOOL VgaAttachToConsole(PCOORD Resolution)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Copy console data into VGA memory */
|
||||
/*
|
||||
* Resize the console
|
||||
*/
|
||||
ConRect.Left = 0;
|
||||
ConRect.Top = ConsoleInfo.srWindow.Top;
|
||||
ConRect.Right = ConRect.Left + Resolution->X - 1;
|
||||
ConRect.Bottom = ConRect.Top + Resolution->Y - 1;
|
||||
/*
|
||||
* Use this trick to effectively resize the console buffer and window,
|
||||
* because:
|
||||
* - SetConsoleScreenBufferSize fails if the new console screen buffer size
|
||||
* is smaller than the current console window size, and:
|
||||
* - SetConsoleWindowInfo fails if the new console window size is larger
|
||||
* than the current console screen buffer size.
|
||||
*/
|
||||
SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
|
||||
SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect);
|
||||
SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
|
||||
/* Update the saved console information */
|
||||
GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
ConRect.Left = ConRect.Top = 0;
|
||||
ConRect.Right = TextResolution.X;
|
||||
ConRect.Bottom = TextResolution.Y;
|
||||
ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
|
||||
|
||||
/* Read the data from the console into the framebuffer... */
|
||||
|
@ -474,7 +510,7 @@ static BOOL VgaAttachToConsole(PCOORD Resolution)
|
|||
CharBuff,
|
||||
TextResolution,
|
||||
Origin,
|
||||
&ScreenRect); // &ConRect);
|
||||
&ConRect);
|
||||
|
||||
/* ... and copy the framebuffer into the VGA memory */
|
||||
|
||||
|
@ -497,10 +533,23 @@ static BOOL VgaAttachToConsole(PCOORD Resolution)
|
|||
Address += ScanlineSize;
|
||||
}
|
||||
|
||||
VgaUpdateCursorPosition();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID VgaDetachFromConsole(VOID)
|
||||
BOOL VgaAttachToConsole(VOID)
|
||||
{
|
||||
if (TextResolution.X == 0 || TextResolution.Y == 0)
|
||||
DPRINT1("VgaAttachToConsole -- TextResolution uninitialized\n");
|
||||
|
||||
if (TextResolution.X == 0) TextResolution.X = 80;
|
||||
if (TextResolution.Y == 0) TextResolution.Y = 25;
|
||||
|
||||
return VgaAttachToConsoleInternal(&TextResolution);
|
||||
}
|
||||
|
||||
VOID VgaDetachFromConsole(BOOL ChangingMode)
|
||||
{
|
||||
ULONG dummyLength;
|
||||
PVOID dummyPtr;
|
||||
|
@ -519,6 +568,29 @@ static VOID VgaDetachFromConsole(VOID)
|
|||
(PCHAR*)&dummyPtr);
|
||||
|
||||
TextFramebuffer = NULL;
|
||||
|
||||
if (!ChangingMode)
|
||||
{
|
||||
SMALL_RECT ConRect;
|
||||
|
||||
/* Restore the old screen buffer */
|
||||
SetConsoleActiveScreenBuffer(TextConsoleBuffer);
|
||||
|
||||
/* Restore the original console size */
|
||||
ConRect.Left = 0;
|
||||
ConRect.Top = 0;
|
||||
ConRect.Right = ConRect.Left + OrgConsoleBufferInfo.srWindow.Right - OrgConsoleBufferInfo.srWindow.Left;
|
||||
ConRect.Bottom = ConRect.Top + OrgConsoleBufferInfo.srWindow.Bottom - OrgConsoleBufferInfo.srWindow.Top ;
|
||||
/*
|
||||
* See the following trick explanation in VgaAttachToConsoleInternal.
|
||||
*/
|
||||
SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize);
|
||||
SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect);
|
||||
SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize);
|
||||
|
||||
/* Restore the original cursor shape */
|
||||
SetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL IsConsoleHandle(HANDLE hHandle)
|
||||
|
@ -944,56 +1016,29 @@ static VOID VgaLeaveGraphicsMode(VOID)
|
|||
|
||||
static BOOL VgaEnterTextMode(PCOORD Resolution)
|
||||
{
|
||||
SMALL_RECT ConRect;
|
||||
|
||||
DPRINT1("VgaEnterTextMode\n");
|
||||
|
||||
/* Switch to the text buffer */
|
||||
SetConsoleActiveScreenBuffer(TextConsoleBuffer);
|
||||
|
||||
/* Resize the console */
|
||||
ConRect.Left = 0;
|
||||
ConRect.Top = ConsoleInfo.srWindow.Top;
|
||||
ConRect.Right = ConRect.Left + Resolution->X - 1;
|
||||
ConRect.Bottom = ConRect.Top + Resolution->Y - 1;
|
||||
/*
|
||||
* Use this trick to effectively resize the console buffer and window,
|
||||
* because:
|
||||
* - SetConsoleScreenBufferSize fails if the new console screen buffer size
|
||||
* is smaller than the current console window size, and:
|
||||
* - SetConsoleWindowInfo fails if the new console window size is larger
|
||||
* than the current console screen buffer size.
|
||||
*/
|
||||
SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
|
||||
SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect);
|
||||
SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
|
||||
/* Update the saved console information */
|
||||
GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo);
|
||||
|
||||
/* Adjust the text framebuffer if we changed resolution */
|
||||
/* Adjust the text framebuffer if we changed the resolution */
|
||||
if (TextResolution.X != Resolution->X ||
|
||||
TextResolution.Y != Resolution->Y)
|
||||
{
|
||||
WORD Offset;
|
||||
VgaDetachFromConsole(TRUE);
|
||||
|
||||
VgaDetachFromConsole();
|
||||
|
||||
/* VgaAttachToConsole sets TextResolution to the new resolution */
|
||||
if (!VgaAttachToConsole(Resolution))
|
||||
/*
|
||||
* VgaAttachToConsoleInternal sets TextResolution to the
|
||||
* new resolution and updates ConsoleInfo.
|
||||
*/
|
||||
if (!VgaAttachToConsoleInternal(Resolution))
|
||||
{
|
||||
DisplayMessage(L"An unexpected error occurred!\n");
|
||||
EmulatorTerminate();
|
||||
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;
|
||||
}
|
||||
else VgaUpdateCursorPosition();
|
||||
|
||||
/* The active framebuffer is now the text framebuffer */
|
||||
ConsoleFramebuffer = TextFramebuffer;
|
||||
|
@ -1825,11 +1870,13 @@ BOOLEAN VgaInitialize(HANDLE TextHandle)
|
|||
if (!IsConsoleHandle(TextHandle)) return FALSE;
|
||||
TextConsoleBuffer = TextHandle;
|
||||
|
||||
/* Save the console information */
|
||||
if (!GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo))
|
||||
/* Save the original cursor and console screen buffer information */
|
||||
if (!GetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo) ||
|
||||
!GetConsoleScreenBufferInfo(TextConsoleBuffer, &OrgConsoleBufferInfo))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
ConsoleInfo = OrgConsoleBufferInfo;
|
||||
|
||||
/* Initialize the VGA palette and fail if it isn't successfully created */
|
||||
if (!VgaInitializePalette()) return FALSE;
|
||||
|
@ -1873,7 +1920,7 @@ VOID VgaCleanup(VOID)
|
|||
VgaLeaveTextMode();
|
||||
}
|
||||
|
||||
VgaDetachFromConsole();
|
||||
VgaDetachFromConsole(FALSE);
|
||||
|
||||
CloseHandle(AnotherEvent);
|
||||
CloseHandle(EndEvent);
|
||||
|
|
|
@ -250,6 +250,9 @@ typedef struct _VGA_REGISTERS
|
|||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOL VgaAttachToConsole(VOID);
|
||||
VOID VgaDetachFromConsole(BOOL ChangeMode);
|
||||
|
||||
DWORD VgaGetVideoBaseAddress(VOID);
|
||||
DWORD VgaGetVideoLimitAddress(VOID);
|
||||
COORD VgaGetDisplayResolution(VOID);
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
static HANDLE ConsoleInput = INVALID_HANDLE_VALUE;
|
||||
static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
|
||||
static DWORD OrgConsoleInputMode, OrgConsoleOutputMode;
|
||||
static CONSOLE_CURSOR_INFO OrgConsoleCursorInfo;
|
||||
static CONSOLE_SCREEN_BUFFER_INFO OrgConsoleBufferInfo;
|
||||
static BOOLEAN AcceptCommands = TRUE;
|
||||
static HANDLE CommandThread = NULL;
|
||||
|
||||
|
@ -344,16 +342,6 @@ BOOL ConsoleInit(VOID)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Save the original cursor and console screen buffer information */
|
||||
if (!GetConsoleCursorInfo(ConsoleOutput, &OrgConsoleCursorInfo) ||
|
||||
!GetConsoleScreenBufferInfo(ConsoleOutput, &OrgConsoleBufferInfo))
|
||||
{
|
||||
CloseHandle(ConsoleOutput);
|
||||
CloseHandle(ConsoleInput);
|
||||
wprintf(L"FATAL: Cannot save console cursor/screen-buffer info\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Initialize the UI */
|
||||
ConsoleInitUI();
|
||||
|
||||
|
@ -362,26 +350,6 @@ BOOL ConsoleInit(VOID)
|
|||
|
||||
VOID ConsoleCleanup(VOID)
|
||||
{
|
||||
SMALL_RECT ConRect;
|
||||
|
||||
/* Restore the old screen buffer */
|
||||
SetConsoleActiveScreenBuffer(ConsoleOutput);
|
||||
|
||||
/* Restore the original console size */
|
||||
ConRect.Left = 0;
|
||||
ConRect.Top = 0;
|
||||
ConRect.Right = ConRect.Left + OrgConsoleBufferInfo.srWindow.Right - OrgConsoleBufferInfo.srWindow.Left;
|
||||
ConRect.Bottom = ConRect.Top + OrgConsoleBufferInfo.srWindow.Bottom - OrgConsoleBufferInfo.srWindow.Top ;
|
||||
/*
|
||||
* See the following trick explanation in vga.c:VgaEnterTextMode() .
|
||||
*/
|
||||
SetConsoleScreenBufferSize(ConsoleOutput, OrgConsoleBufferInfo.dwSize);
|
||||
SetConsoleWindowInfo(ConsoleOutput, TRUE, &ConRect);
|
||||
SetConsoleScreenBufferSize(ConsoleOutput, OrgConsoleBufferInfo.dwSize);
|
||||
|
||||
/* Restore the original cursor shape */
|
||||
SetConsoleCursorInfo(ConsoleOutput, &OrgConsoleCursorInfo);
|
||||
|
||||
/* Restore the original input and output console modes */
|
||||
SetConsoleMode(ConsoleOutput, OrgConsoleOutputMode);
|
||||
SetConsoleMode(ConsoleInput , OrgConsoleInputMode );
|
||||
|
@ -428,11 +396,7 @@ DWORD WINAPI CommandThreadProc(LPVOID Parameter)
|
|||
CommandInfo.Env = Env;
|
||||
CommandInfo.EnvLen = sizeof(Env);
|
||||
|
||||
if (First)
|
||||
{
|
||||
CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
|
||||
First = FALSE;
|
||||
}
|
||||
if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
|
||||
|
||||
/* Wait for the next available VDM */
|
||||
if (!GetNextVDMCommand(&CommandInfo)) break;
|
||||
|
@ -447,12 +411,23 @@ DWORD WINAPI CommandThreadProc(LPVOID Parameter)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Attach to the console */
|
||||
if (!First) VgaAttachToConsole();
|
||||
|
||||
/* Perform a screen refresh */
|
||||
VgaRefreshDisplay();
|
||||
|
||||
/* Start simulation */
|
||||
SetEvent(VdmTaskEvent);
|
||||
EmulatorSimulate();
|
||||
|
||||
/* Perform another screen refresh */
|
||||
VgaRefreshDisplay();
|
||||
|
||||
/* Detach from the console */
|
||||
VgaDetachFromConsole(FALSE);
|
||||
|
||||
First = FALSE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue