/* PRIVATE FUNCTIONS **********************************************************/
-static VOID VidBiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
+static BOOLEAN VidBiosScrollWindow(SCROLL_DIRECTION Direction,
+ DWORD Amount,
+ SMALL_RECT Rectangle,
+ BYTE Page,
+ BYTE FillAttribute)
{
INT i, j;
- INT Counter = 0;
- WORD Character;
DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+ WORD FillCharacter = MAKEWORD(' ', FillAttribute);
- for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
- {
- for (j = Rectangle.Left; j <= Rectangle.Right; j++)
- {
- /* Read from video memory */
- EmulatorReadMemory(&EmulatorContext,
- VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
- (LPVOID)&Character,
- sizeof(WORD));
+ WORD WindowWidth, WindowHeight;
- /* Write the data to the buffer in row order */
- Buffer[Counter++] = Character;
- }
- }
-}
-
-static VOID VidBiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
-{
- INT i, j;
- INT Counter = 0;
- WORD Character;
- DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+ /* Fixup the rectangle if needed */
+ Rectangle.Left = min(max(Rectangle.Left , 0), Bda->ScreenColumns - 1);
+ Rectangle.Right = min(max(Rectangle.Right , 0), Bda->ScreenColumns - 1);
+ Rectangle.Top = min(max(Rectangle.Top , 0), Bda->ScreenRows);
+ Rectangle.Bottom = min(max(Rectangle.Bottom, 0), Bda->ScreenRows);
- for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
- {
- for (j = Rectangle.Left; j <= Rectangle.Right; j++)
- {
- Character = Buffer[Counter++];
-
- /* Write to video memory */
- EmulatorWriteMemory(&EmulatorContext,
- VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
- (LPVOID)&Character,
- sizeof(WORD));
- }
- }
-}
+ WindowWidth = Rectangle.Right - Rectangle.Left + 1;
+ WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
-static BOOLEAN VidBiosScrollWindow(INT Direction,
- DWORD Amount,
- SMALL_RECT Rectangle,
- BYTE Page,
- BYTE FillAttribute)
-{
- DWORD i;
- LPWORD WindowData;
- WORD WindowWidth = Rectangle.Right - Rectangle.Left + 1;
- WORD WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
- DWORD WindowSize = WindowWidth * WindowHeight;
-
- /* Allocate a buffer for the window */
- WindowData = (LPWORD)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- WindowSize * sizeof(WORD));
- if (WindowData == NULL) return FALSE;
-
- /* Read the window data */
- VidBiosReadWindow(WindowData, Rectangle, Page);
-
- if ((Amount == 0)
- || (((Direction == SCROLL_DIRECTION_UP)
- || (Direction == SCROLL_DIRECTION_DOWN))
- && (Amount >= WindowHeight))
- || (((Direction == SCROLL_DIRECTION_LEFT)
- || (Direction == SCROLL_DIRECTION_RIGHT))
- && (Amount >= WindowWidth)))
+ /* Amount == 0 means we clear all the rectangle */
+ if ((Amount == 0) ||
+ (((Direction == SCROLL_UP ) || (Direction == SCROLL_DOWN )) && (Amount >= WindowHeight)) ||
+ (((Direction == SCROLL_LEFT) || (Direction == SCROLL_RIGHT)) && (Amount >= WindowWidth )))
{
- /* Fill the window */
- for (i = 0; i < WindowSize; i++)
+ /* Fill the rectangle */
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
{
- WindowData[i] = MAKEWORD(' ', FillAttribute);
+ for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
}
- goto Done;
+ return TRUE;
}
switch (Direction)
{
- case SCROLL_DIRECTION_UP:
+ case SCROLL_UP:
{
- RtlMoveMemory(WindowData,
- &WindowData[WindowWidth * Amount],
- (WindowSize - WindowWidth * Amount) * sizeof(WORD));
+ /* Move text lines up */
+ for (i = Rectangle.Top + Amount; i <= Rectangle.Bottom; i++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + ((i - Amount) * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD),
+ REAL_TO_PHYS(VideoAddress + ( i * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD)),
+ (Rectangle.Right - Rectangle.Left + 1) * sizeof(WORD));
+ }
- for (i = 0; i < Amount * WindowWidth; i++)
+ /* Fill the bottom of the rectangle */
+ for (i = Rectangle.Bottom - Amount + 1; i <= Rectangle.Bottom; i++)
{
- WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
+ for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
}
break;
}
- case SCROLL_DIRECTION_DOWN:
+ case SCROLL_DOWN:
{
- RtlMoveMemory(&WindowData[WindowWidth * Amount],
- WindowData,
- (WindowSize - WindowWidth * Amount) * sizeof(WORD));
+ /* Move text lines down */
+ for (i = Rectangle.Bottom - Amount; i >= Rectangle.Top; i--)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + ((i + Amount) * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD),
+ REAL_TO_PHYS(VideoAddress + ( i * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD)),
+ (Rectangle.Right - Rectangle.Left + 1) * sizeof(WORD));
+ }
- for (i = 0; i < Amount * WindowWidth; i++)
+ /* Fill the top of the rectangle */
+ for (i = Rectangle.Top; i <= Rectangle.Top + Amount - 1; i++)
{
- WindowData[i] = MAKEWORD(' ', FillAttribute);
+ for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
}
break;
}
- default:
+ case SCROLL_LEFT:
{
- // TODO: NOT IMPLEMENTED!
- UNIMPLEMENTED;
+ /* Move text lines left */
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left ) * sizeof(WORD),
+ REAL_TO_PHYS(VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left + Amount) * sizeof(WORD)),
+ (Rectangle.Right - Rectangle.Left - Amount + 1) * sizeof(WORD));
+ }
+
+ /* Fill the right of the rectangle */
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+ {
+ for (j = Rectangle.Right - Amount + 1; j <= Rectangle.Right; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
+ }
+
+ break;
}
- }
-Done:
- /* Write back the window data */
- VidBiosWriteWindow(WindowData, Rectangle, Page);
+ case SCROLL_RIGHT:
+ {
+ /* Move text lines right */
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left + Amount) * sizeof(WORD),
+ REAL_TO_PHYS(VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left ) * sizeof(WORD)),
+ (Rectangle.Right - Rectangle.Left - Amount + 1) * sizeof(WORD));
+ }
+
+ /* Fill the left of the rectangle */
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+ {
+ for (j = Rectangle.Left; j <= Rectangle.Left + Amount - 1; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
+ }
- /* Free the window buffer */
- HeapFree(GetProcessHeap(), 0, WindowData);
+ break;
+ }
+ }
return TRUE;
}
// FIXME: We need to reset the fonts and the font vectors. (INT 1Fh and 43h).
+ // HACK: We clear here all the text memory. TODO: Do it better!
+ if (!DoNotClear && ((ModeNumber >= 0x00 && ModeNumber <= 0x03) || (ModeNumber == 0x07)))
+ {
+ INT i, j;
+ DWORD VideoAddress;
+ WORD FillCharacter = MAKEWORD(' ', DEFAULT_ATTRIBUTE);
+
+ for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
+ {
+ VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+
+ for (i = 0; i <= Bda->ScreenRows; i++)
+ {
+ for (j = 0; j <= Bda->ScreenColumns - 1; j++)
+ {
+ /* Write to video memory */
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
+ }
+ }
+ }
+
/* Refresh display */
VgaRefreshDisplay();
{
/* The screen must be scrolled up */
SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
-
- VidBiosScrollWindow(SCROLL_DIRECTION_UP,
- 1,
- Rectangle,
- Page,
- DEFAULT_ATTRIBUTE);
-
+ VidBiosScrollWindow(SCROLL_UP, 1, Rectangle, Page, DEFAULT_ATTRIBUTE/*Attribute*/);
Row--;
}
{
SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
- /* Call the internal function */
- VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP
- : SCROLL_DIRECTION_DOWN,
- getAL(),
- Rectangle,
- Bda->VideoPage,
- getBH());
+ VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_UP : SCROLL_DOWN,
+ getAL(), Rectangle, Bda->VideoPage, getBH());
break;
}