#include "emulator.h"
#include "vga.h"
+#include "../bios/vidbios.h"
#include "io.h"
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
/* PRIVATE FUNCTIONS **********************************************************/
static inline DWORD VgaGetAddressSize(VOID);
+static VOID VgaUpdateTextCursor(VOID);
+
+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);
-static BOOL VgaAttachToConsole(PCOORD Resolution)
+ VidBiosSyncCursorPosition();
+ VgaUpdateTextCursor();
+}
+
+static BOOL VgaAttachToConsoleInternal(PCOORD Resolution)
{
BOOL Success;
ULONG Length = 0;
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;
/*
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... */
CharBuff,
TextResolution,
Origin,
- &ScreenRect); // &ConRect);
+ &ConRect);
/* ... and copy the framebuffer into the VGA memory */
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;
(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)
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;
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;
VgaLeaveTextMode();
}
- VgaDetachFromConsole();
+ VgaDetachFromConsole(FALSE);
CloseHandle(AnotherEvent);
CloseHandle(EndEvent);