Author: hbelusca
Date: Sun Jan 5 21:26:33 2014
New Revision: 61542
URL:
http://svn.reactos.org/svn/reactos?rev=61542&view=rev
Log:
[NTVDM]
- Move console text buffer copy into VGA memory, to the BIOS (function
BiosCopyTextConsoleToVgaMemory), and do it just after the BIOS sets its default display
mode.
- Try to resize "correctly" the console to its original size when cleaning BIOS
(Part 2/2, see revision 61538). Still WIP.
- Code cleaning in vga.c
Modified:
branches/ntvdm/subsystems/ntvdm/bios.c
branches/ntvdm/subsystems/ntvdm/bios.h
branches/ntvdm/subsystems/ntvdm/vga.c
Modified: branches/ntvdm/subsystems/ntvdm/bios.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.c?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] Sun Jan 5 21:26:33 2014
@@ -264,9 +264,9 @@
&VideoMode_40x25_text, /* Mode 01h */ // 16 color
&VideoMode_80x25_text, /* Mode 02h */ // 16 color (mono)
&VideoMode_80x25_text, /* Mode 03h */ // 16 color
- &VideoMode_320x200_4color, /* Mode 04h */ // 4 color
- &VideoMode_320x200_4color, /* Mode 05h */ // same (m)
- &VideoMode_640x200_2color, /* Mode 06h */ // 640*200 2 color
+ &VideoMode_320x200_4color, /* Mode 04h */ // CGA 4 color
+ &VideoMode_320x200_4color, /* Mode 05h */ // CGA same (m)
+ &VideoMode_640x200_2color, /* Mode 06h */ // CGA 640*200 2 color
NULL, /* Mode 07h */ // MDA monochrome text 80*25
NULL, /* Mode 08h */ // PCjr
NULL, /* Mode 09h */ // PCjr
@@ -710,6 +710,138 @@
}
}
+static BOOLEAN BiosScrollWindow(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 */
+ BiosReadWindow(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)))
+ {
+ /* Fill the window */
+ for (i = 0; i < WindowSize; i++)
+ {
+ WindowData[i] = MAKEWORD(' ', FillAttribute);
+ }
+
+ goto Done;
+ }
+
+ switch (Direction)
+ {
+ case SCROLL_DIRECTION_UP:
+ {
+ RtlMoveMemory(WindowData,
+ &WindowData[WindowWidth * Amount],
+ (WindowSize - WindowWidth * Amount) * sizeof(WORD));
+
+ for (i = 0; i < Amount * WindowWidth; i++)
+ {
+ WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
+ }
+
+ break;
+ }
+
+ case SCROLL_DIRECTION_DOWN:
+ {
+ RtlMoveMemory(&WindowData[WindowWidth * Amount],
+ WindowData,
+ (WindowSize - WindowWidth * Amount) * sizeof(WORD));
+
+ for (i = 0; i < Amount * WindowWidth; i++)
+ {
+ WindowData[i] = MAKEWORD(' ', FillAttribute);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ // TODO: NOT IMPLEMENTED!
+ UNIMPLEMENTED;
+ }
+ }
+
+Done:
+ /* Write back the window data */
+ BiosWriteWindow(WindowData, Rectangle, Page);
+
+ /* Free the window buffer */
+ HeapFree(GetProcessHeap(), 0, WindowData);
+
+ return TRUE;
+}
+
+static VOID BiosCopyTextConsoleToVgaMemory(VOID)
+{
+ PCHAR_INFO CharBuffer;
+ COORD BufferSize = {Bda->ScreenColumns, Bda->ScreenRows + 1};
+ COORD Origin = { 0, 0 };
+ SMALL_RECT ScreenRect;
+
+ 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;
+
+ ScreenRect.Left = ScreenRect.Top = 0;
+ ScreenRect.Right = BufferSize.X;
+ ScreenRect.Bottom = BufferSize.Y;
+
+ /* Read the data from the console into the temporary buffer... */
+ ReadConsoleOutputA(BiosConsoleOutput,
+ CharBuffer,
+ BufferSize,
+ Origin,
+ &ScreenRect);
+
+ /* ... 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 */
+ VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) *
sizeof(WORD),
+ (LPVOID)&Character,
+ sizeof(WORD));
+ }
+ }
+}
+
static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers)
{
INT i;
@@ -850,14 +982,43 @@
VgaSetPalette(Palette, Size);
}
-/* PUBLIC FUNCTIONS ***********************************************************/
+static VOID BiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
+{
+ /* Make sure the selected video page is valid */
+ if (Page >= BIOS_MAX_PAGES) return;
+
+ /* Get the cursor location */
+ *Row = HIBYTE(Bda->CursorPosition[Page]);
+ *Column = LOBYTE(Bda->CursorPosition[Page]);
+}
+
+static VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
+{
+ /* Make sure the selected video page is valid */
+ if (Page >= BIOS_MAX_PAGES) return;
+
+ /* Update the position in the BDA */
+ Bda->CursorPosition[Page] = MAKEWORD(Column, Row);
+
+ /* Check if this is the current video page */
+ if (Page == Bda->VideoPage)
+ {
+ WORD Offset = Row * Bda->ScreenColumns + Column;
+
+ /* Modify the CRTC registers */
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
+ VgaWritePort(VGA_CRTC_DATA , LOBYTE(Offset));
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
+ VgaWritePort(VGA_CRTC_DATA , HIBYTE(Offset));
+ }
+}
BYTE BiosGetVideoMode(VOID)
{
return Bda->VideoMode;
}
-BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
+static BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
{
BYTE Page;
@@ -869,6 +1030,14 @@
if (!VgaSetRegisters(VgaMode)) return FALSE;
VgaChangePalette(ModeNumber);
+
+ /*
+ * IBM standard modes do not clear the screen if the
+ * high bit of AL is set (EGA or higher only).
+ * See Ralf Brown:
http://www.ctyme.com/intr/rb-0069.htm
+ * for more information.
+ */
+ if ((ModeNumber & 0x08) == 0) VgaClearMemory();
// Bda->CrtModeControl;
// Bda->CrtColorPaletteMask;
@@ -895,14 +1064,14 @@
Bda->ScreenColumns = Resolution.X;
Bda->ScreenRows = Resolution.Y - 1;
- /* Set cursor position for each page */
+ /* Set the cursor position for each page */
for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
BiosSetCursorPosition(0, 0, Page);
return TRUE;
}
-BOOLEAN BiosSetVideoPage(BYTE PageNumber)
+static BOOLEAN BiosSetVideoPage(BYTE PageNumber)
{
BYTE Row, Column;
@@ -932,8 +1101,719 @@
return TRUE;
}
+static VOID WINAPI BiosVideoService(LPWORD Stack)
+{
+ switch (getAH())
+ {
+ /* Set Video Mode */
+ case 0x00:
+ {
+ BiosSetVideoMode(getAL());
+ break;
+ }
+
+ /* Set Text-Mode Cursor Shape */
+ case 0x01:
+ {
+ /* Update the BDA */
+ Bda->CursorStartLine = getCH();
+ Bda->CursorEndLine = getCL();
+
+ /* Modify the CRTC registers */
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
+ VgaWritePort(VGA_CRTC_DATA , Bda->CursorStartLine);
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
+ VgaWritePort(VGA_CRTC_DATA , Bda->CursorEndLine);
+
+ break;
+ }
+
+ /* Set Cursor Position */
+ case 0x02:
+ {
+ BiosSetCursorPosition(getDH(), getDL(), getBH());
+ break;
+ }
+
+ /* Get Cursor Position */
+ case 0x03:
+ {
+ /* Make sure the selected video page exists */
+ if (getBH() >= BIOS_MAX_PAGES) break;
+
+ /* Return the result */
+ setAX(0);
+ setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine));
+ setDX(Bda->CursorPosition[getBH()]);
+ break;
+ }
+
+ /* Query Light Pen */
+ case 0x04:
+ {
+ /*
+ * On modern BIOSes, this function returns 0
+ * so that we can ignore the other registers.
+ */
+ setAX(0);
+ break;
+ }
+
+ /* Select Active Display Page */
+ case 0x05:
+ {
+ BiosSetVideoPage(getAL());
+ break;
+ }
+
+ /* Scroll Window Up/Down */
+ case 0x06:
+ case 0x07:
+ {
+ SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
+
+ /* Call the internal function */
+ BiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP
+ : SCROLL_DIRECTION_DOWN,
+ getAL(),
+ Rectangle,
+ Bda->VideoPage,
+ getBH());
+
+ break;
+ }
+
+ /* Read/Write Character From Cursor Position */
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ {
+ WORD CharacterData = MAKEWORD(getAL(), getBL());
+ BYTE Page = getBH();
+ DWORD Offset;
+
+ /* Check if the page exists */
+ if (Page >= BIOS_MAX_PAGES) break;
+
+ /* Find the offset of the character */
+ Offset = Page * Bda->VideoPageSize +
+ (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns +
+ LOBYTE(Bda->CursorPosition[Page])) * 2;
+
+ if (getAH() == 0x08)
+ {
+ /* Read from the video memory */
+ VgaReadMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
+ (LPVOID)&CharacterData,
+ sizeof(WORD));
+
+ /* Return the character in AX */
+ setAX(CharacterData);
+ }
+ else
+ {
+ /* Write to video memory */
+ VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
+ (LPVOID)&CharacterData,
+ (getBH() == 0x09) ? sizeof(WORD) : sizeof(BYTE));
+ }
+
+ break;
+ }
+
+ /* Teletype Output */
+ case 0x0E:
+ {
+ BiosPrintCharacter(getAL(), getBL(), getBH());
+ break;
+ }
+
+ /* Get Current Video Mode */
+ case 0x0F:
+ {
+ setAX(MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
+ setBX(MAKEWORD(getBL(), Bda->VideoPage));
+ break;
+ }
+
+ /* Palette Control */
+ case 0x10:
+ {
+ switch (getAL())
+ {
+ /* Set Single Palette Register */
+ case 0x00:
+ {
+ /* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, getBL());
+
+ /* Write the data */
+ VgaWritePort(VGA_AC_WRITE, getBH());
+
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
+ break;
+ }
+
+ /* Set Overscan Color */
+ case 0x01:
+ {
+ /* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+
+ /* Write the data */
+ VgaWritePort(VGA_AC_WRITE, getBH());
+
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
+ break;
+ }
+
+ /* Set All Palette Registers */
+ case 0x02:
+ {
+ INT i;
+ LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+ /* Set the palette registers */
+ for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
+ {
+ /* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, i);
+
+ /* Write the data */
+ VgaWritePort(VGA_AC_WRITE, Buffer[i]);
+ }
+
+ /* Set the overscan register */
+ VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+ VgaWritePort(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
+
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
+ break;
+ }
+
+ /* Get Single Palette Register */
+ case 0x07:
+ {
+ /* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, getBL());
+
+ /* Read the data */
+ setBH(VgaReadPort(VGA_AC_READ));
+
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
+ break;
+ }
+
+ /* Get Overscan Color */
+ case 0x08:
+ {
+ /* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+
+ /* Read the data */
+ setBH(VgaReadPort(VGA_AC_READ));
+
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
+ break;
+ }
+
+ /* Get All Palette Registers */
+ case 0x09:
+ {
+ INT i;
+ LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+ /* Get the palette registers */
+ for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
+ {
+ /* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, i);
+
+ /* Read the data */
+ Buffer[i] = VgaReadPort(VGA_AC_READ);
+ }
+
+ /* Get the overscan register */
+ VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+ Buffer[VGA_AC_PAL_F_REG + 1] = VgaReadPort(VGA_AC_READ);
+
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
+ break;
+ }
+
+ /* Set Individual DAC Register */
+ case 0x10:
+ {
+ /* Write the index */
+ // Certainly in BL and not in BX as said by Ralf Brown...
+ VgaWritePort(VGA_DAC_WRITE_INDEX, getBL());
+
+ /* Write the data in this order: Red, Green, Blue */
+ VgaWritePort(VGA_DAC_DATA, getDH());
+ VgaWritePort(VGA_DAC_DATA, getCH());
+ VgaWritePort(VGA_DAC_DATA, getCL());
+
+ break;
+ }
+
+ /* Set Block of DAC Registers */
+ case 0x12:
+ {
+ INT i;
+ LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+ /* Write the index */
+ // Certainly in BL and not in BX as said by Ralf Brown...
+ VgaWritePort(VGA_DAC_WRITE_INDEX, getBL());
+
+ for (i = 0; i < getCX(); i++)
+ {
+ /* Write the data in this order: Red, Green, Blue */
+ VgaWritePort(VGA_DAC_DATA, *Buffer++);
+ VgaWritePort(VGA_DAC_DATA, *Buffer++);
+ VgaWritePort(VGA_DAC_DATA, *Buffer++);
+ }
+
+ break;
+ }
+
+ /* Get Individual DAC Register */
+ case 0x15:
+ {
+ /* Write the index */
+ VgaWritePort(VGA_DAC_READ_INDEX, getBL());
+
+ /* Read the data in this order: Red, Green, Blue */
+ setDH(VgaReadPort(VGA_DAC_DATA));
+ setCH(VgaReadPort(VGA_DAC_DATA));
+ setCL(VgaReadPort(VGA_DAC_DATA));
+
+ break;
+ }
+
+ /* Get Block of DAC Registers */
+ case 0x17:
+ {
+ INT i;
+ LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+ /* Write the index */
+ // Certainly in BL and not in BX as said by Ralf Brown...
+ VgaWritePort(VGA_DAC_READ_INDEX, getBL());
+
+ for (i = 0; i < getCX(); i++)
+ {
+ /* Write the data in this order: Red, Green, Blue */
+ *Buffer++ = VgaReadPort(VGA_DAC_DATA);
+ *Buffer++ = VgaReadPort(VGA_DAC_DATA);
+ *Buffer++ = VgaReadPort(VGA_DAC_DATA);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT
IMPLEMENTED\n",
+ getAL());
+ break;
+ }
+ }
+
+ break;
+ }
+
+ /* Scroll Window */
+ case 0x12:
+ {
+ SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
+
+ /* Call the internal function */
+ BiosScrollWindow(getBL(),
+ getAL(),
+ Rectangle,
+ Bda->VideoPage,
+ DEFAULT_ATTRIBUTE);
+
+ break;
+ }
+
+ /* Display combination code */
+ case 0x1A:
+ {
+ switch(getAL())
+ {
+ case 0x00: /* Get Display combiantion code */
+ setAX(MAKEWORD(0x1A, 0x1A));
+ setBX(MAKEWORD(0x08, 0x00)); /* VGA w/ color analog display */
+ break;
+ case 0x01: /* Set Display combination code */
+ DPRINT1("Set Display combination code - Unsupported\n");
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ default:
+ {
+ DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n",
+ getAH());
+ }
+ }
+}
+
+static VOID WINAPI BiosEquipmentService(LPWORD Stack)
+{
+ /* Return the equipment list */
+ setAX(Bda->EquipmentList);
+}
+
+static VOID WINAPI BiosGetMemorySize(LPWORD Stack)
+{
+ /* Return the conventional memory size in kB, typically 640 kB */
+ setAX(Bda->MemorySize);
+}
+
+static VOID WINAPI BiosMiscService(LPWORD Stack)
+{
+ switch (getAH())
+ {
+ /* Copy Extended Memory */
+ case 0x87:
+ {
+ DWORD Count = (DWORD)getCX() * 2;
+ PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(),
getSI());
+ DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) +
(Gdt[2].BaseHigh << 24);
+ DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16);
+ DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) +
(Gdt[3].BaseHigh << 24);
+ DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16);
+
+ /* Check for flags */
+ if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF;
+ if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF;
+
+ if ((Count > SourceLimit) || (Count > DestLimit))
+ {
+ setAX(0x80);
+ Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+
+ break;
+ }
+
+ /* Copy */
+ RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase),
+ (PVOID)((ULONG_PTR)BaseAddress + SourceBase),
+ Count);
+
+ setAX(ERROR_SUCCESS);
+ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+ break;
+ }
+
+ /* Get Extended Memory Size */
+ case 0x88:
+ {
+ /* Return the number of KB of RAM after 1 MB */
+ setAX((MAX_ADDRESS - 0x100000) / 1024);
+
+ /* Clear CF */
+ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+
+ break;
+ }
+
+ default:
+ {
+ DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
+ getAH());
+ }
+ }
+}
+
+static VOID WINAPI BiosKeyboardService(LPWORD Stack)
+{
+ switch (getAH())
+ {
+ /* Wait for keystroke and read */
+ case 0x00:
+ /* Wait for extended keystroke and read */
+ case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h
+ {
+ /* Read the character (and wait if necessary) */
+ setAX(BiosGetCharacter());
+ break;
+ }
+
+ /* Get keystroke status */
+ case 0x01:
+ /* Get extended keystroke status */
+ case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h
+ {
+ WORD Data = BiosPeekCharacter();
+
+ if (Data != 0xFFFF)
+ {
+ /* There is a character, clear ZF and return it */
+ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
+ setAX(Data);
+ }
+ else
+ {
+ /* No character, set ZF */
+ Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
+ }
+
+ break;
+ }
+
+ /* Get shift status */
+ case 0x02:
+ {
+ /* Return the lower byte of the keyboard shift status word */
+ setAL(LOBYTE(Bda->KeybdShiftFlags));
+ break;
+ }
+
+ /* Reserved */
+ case 0x04:
+ {
+ DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n");
+ break;
+ }
+
+ /* Push keystroke */
+ case 0x05:
+ {
+ /* Return 0 if success, 1 if failure */
+ setAL(BiosKbdBufferPush(getCX()) == FALSE);
+ break;
+ }
+
+ /* Get extended shift status */
+ case 0x12:
+ {
+ /*
+ * Be careful! The returned word is similar to Bda->KeybdShiftFlags
+ * but the high byte is organized differently:
+ * the bytes 2 and 3 of the high byte are not the same...
+ */
+ WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
+
+ /* Return the extended keyboard shift status word */
+ setAX(KeybdShiftFlags);
+ break;
+ }
+
+ default:
+ {
+ DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n",
+ getAH());
+ }
+ }
+}
+
+static VOID WINAPI BiosTimeService(LPWORD Stack)
+{
+ switch (getAH())
+ {
+ case 0x00:
+ {
+ /* Set AL to 1 if midnight had passed, 0 otherwise */
+ setAL(Bda->MidnightPassed ? 0x01 : 0x00);
+
+ /* Return the tick count in CX:DX */
+ setCX(HIWORD(Bda->TickCounter));
+ setDX(LOWORD(Bda->TickCounter));
+
+ /* Reset the midnight flag */
+ Bda->MidnightPassed = FALSE;
+
+ break;
+ }
+
+ case 0x01:
+ {
+ /* Set the tick count to CX:DX */
+ Bda->TickCounter = MAKELONG(getDX(), getCX());
+
+ /* Reset the midnight flag */
+ Bda->MidnightPassed = FALSE;
+
+ break;
+ }
+
+ default:
+ {
+ DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
+ getAH());
+ }
+ }
+}
+
+static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
+{
+ /* Increase the system tick count */
+ Bda->TickCounter++;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+WORD BiosPeekCharacter(VOID)
+{
+ WORD CharacterData = 0;
+
+ /* Get the key from the queue, but don't remove it */
+ if (BiosKbdBufferTop(&CharacterData)) return CharacterData;
+ else return 0xFFFF;
+}
+
+WORD BiosGetCharacter(VOID)
+{
+ WORD CharacterData = 0;
+
+ /* Check if there is a key available */
+ if (BiosKbdBufferTop(&CharacterData))
+ {
+ /* A key was available, remove it from the queue */
+ BiosKbdBufferPop();
+ }
+ else
+ {
+ /* No key available. Set the handler CF to repeat the BOP */
+ setCF(1);
+ // CharacterData = 0xFFFF;
+ }
+
+ return CharacterData;
+}
+
+VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
+{
+ WORD CharData = MAKEWORD(Character, Attribute);
+ BYTE Row, Column;
+
+ /* Make sure the page exists */
+ if (Page >= BIOS_MAX_PAGES) return;
+
+ /* Get the cursor location */
+ BiosGetCursorPosition(&Row, &Column, Page);
+
+ if (Character == '\a')
+ {
+ /* Bell control character */
+ // NOTE: We may use what the terminal emulator offers to us...
+ Beep(800, 200);
+ return;
+ }
+ else if (Character == '\b')
+ {
+ /* Backspace control character */
+ if (Column > 0)
+ {
+ Column--;
+ }
+ else if (Row > 0)
+ {
+ Column = Bda->ScreenColumns - 1;
+ Row--;
+ }
+
+ /* Erase the existing character */
+ CharData = MAKEWORD(' ', Attribute);
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(TEXT_VIDEO_SEG,
+ Page * Bda->VideoPageSize +
+ (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
+ (LPVOID)&CharData,
+ sizeof(WORD));
+ }
+ else if (Character == '\t')
+ {
+ /* Horizontal Tabulation control character */
+ do
+ {
+ // Taken from DOSBox
+ BiosPrintCharacter(' ', Attribute, Page);
+ BiosGetCursorPosition(&Row, &Column, Page);
+ } while (Column % 8);
+ }
+ else if (Character == '\n')
+ {
+ /* Line Feed control character */
+ Row++;
+ }
+ else if (Character == '\r')
+ {
+ /* Carriage Return control character */
+ Column = 0;
+ }
+ else
+ {
+ /* Default character */
+
+ /* Write the character */
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(TEXT_VIDEO_SEG,
+ Page * Bda->VideoPageSize +
+ (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
+ (LPVOID)&CharData,
+ sizeof(WORD));
+
+ /* Advance the cursor */
+ Column++;
+ }
+
+ /* Check if it passed the end of the row */
+ if (Column >= Bda->ScreenColumns)
+ {
+ /* Return to the first column and go to the next line */
+ Column = 0;
+ Row++;
+ }
+
+ /* Scroll the screen up if needed */
+ if (Row > Bda->ScreenRows)
+ {
+ /* The screen must be scrolled up */
+ SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
+
+ BiosScrollWindow(SCROLL_DIRECTION_UP,
+ 1,
+ Rectangle,
+ Page,
+ DEFAULT_ATTRIBUTE);
+
+ Row--;
+ }
+
+ /* Set the cursor position */
+ BiosSetCursorPosition(Row, Column, Page);
+}
+
BOOLEAN BiosInitialize(VOID)
{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
/* Initialize the BDA */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
@@ -999,7 +1879,7 @@
return FALSE;
}
- /* Save the console screen buffer information */
+ /* Save the original console screen buffer information */
if (!GetConsoleScreenBufferInfo(BiosConsoleOutput, &BiosSavedBufferInfo))
{
CloseHandle(BiosConsoleOutput);
@@ -1015,10 +1895,17 @@
return FALSE;
}
- /* Update the cursor position */
- BiosSetCursorPosition(BiosSavedBufferInfo.dwCursorPosition.Y,
- BiosSavedBufferInfo.dwCursorPosition.X,
- 0);
+ /* Set the default video mode */
+ BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
+
+ /* Copy console data into VGA memory */
+ BiosCopyTextConsoleToVgaMemory();
+
+ /* Update the cursor position for the current page (page 0) */
+ GetConsoleScreenBufferInfo(BiosConsoleOutput, &ConsoleInfo);
+ BiosSetCursorPosition(ConsoleInfo.dwCursorPosition.Y,
+ ConsoleInfo.dwCursorPosition.X,
+ Bda->VideoPage);
/* Set the console input mode */
SetConsoleMode(BiosConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
@@ -1055,841 +1942,31 @@
VOID BiosCleanup(VOID)
{
+ SMALL_RECT ConRect;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
PS2Cleanup();
/* Restore the old screen buffer */
SetConsoleActiveScreenBuffer(BiosConsoleOutput);
- /* Restore the screen buffer size */
+ /* Restore the original console size */
+ GetConsoleScreenBufferInfo(BiosConsoleOutput, &ConsoleInfo);
+ ConRect.Left = 0; // BiosSavedBufferInfo.srWindow.Left;
+ // ConRect.Top = ConsoleInfo.dwCursorPosition.Y /
(BiosSavedBufferInfo.srWindow.Bottom - BiosSavedBufferInfo.srWindow.Top + 1);
+ // ConRect.Top *= (BiosSavedBufferInfo.srWindow.Bottom -
BiosSavedBufferInfo.srWindow.Top + 1);
+ ConRect.Top = ConsoleInfo.dwCursorPosition.Y;
+ ConRect.Right = ConRect.Left + BiosSavedBufferInfo.srWindow.Right -
BiosSavedBufferInfo.srWindow.Left;
+ ConRect.Bottom = ConRect.Top + (BiosSavedBufferInfo.srWindow.Bottom -
BiosSavedBufferInfo.srWindow.Top);
+ /* See the following trick explanation in vga.c:VgaEnterTextMode() */
+ SetConsoleScreenBufferSize(BiosConsoleOutput, BiosSavedBufferInfo.dwSize);
+ SetConsoleWindowInfo(BiosConsoleOutput, TRUE, &ConRect);
+ // SetConsoleWindowInfo(BiosConsoleOutput, TRUE, &BiosSavedBufferInfo.srWindow);
SetConsoleScreenBufferSize(BiosConsoleOutput, BiosSavedBufferInfo.dwSize);
/* Close the console handles */
if (BiosConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleOutput);
if (BiosConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleInput);
-}
-
-WORD BiosPeekCharacter(VOID)
-{
- WORD CharacterData = 0;
-
- /* Get the key from the queue, but don't remove it */
- if (BiosKbdBufferTop(&CharacterData)) return CharacterData;
- else return 0xFFFF;
-}
-
-WORD BiosGetCharacter(VOID)
-{
- WORD CharacterData = 0;
-
- /* Check if there is a key available */
- if (BiosKbdBufferTop(&CharacterData))
- {
- /* A key was available, remove it from the queue */
- BiosKbdBufferPop();
- }
- else
- {
- /* No key available. Set the handler CF to repeat the BOP */
- setCF(1);
- // CharacterData = 0xFFFF;
- }
-
- return CharacterData;
-}
-
-VOID BiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
-{
- /* Make sure the selected video page is valid */
- if (Page >= BIOS_MAX_PAGES) return;
-
- /* Get the cursor location */
- *Row = HIBYTE(Bda->CursorPosition[Page]);
- *Column = LOBYTE(Bda->CursorPosition[Page]);
-}
-
-VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
-{
- /* Make sure the selected video page is valid */
- if (Page >= BIOS_MAX_PAGES) return;
-
- /* Update the position in the BDA */
- Bda->CursorPosition[Page] = MAKEWORD(Column, Row);
-
- /* Check if this is the current video page */
- if (Page == Bda->VideoPage)
- {
- WORD Offset = Row * Bda->ScreenColumns + Column;
-
- /* Modify the CRTC registers */
- VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
- VgaWritePort(VGA_CRTC_DATA , LOBYTE(Offset));
- VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
- VgaWritePort(VGA_CRTC_DATA , HIBYTE(Offset));
- }
-}
-
-BOOLEAN BiosScrollWindow(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 */
- BiosReadWindow(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)))
- {
- /* Fill the window */
- for (i = 0; i < WindowSize; i++)
- {
- WindowData[i] = MAKEWORD(' ', FillAttribute);
- }
-
- goto Done;
- }
-
- switch (Direction)
- {
- case SCROLL_DIRECTION_UP:
- {
- RtlMoveMemory(WindowData,
- &WindowData[WindowWidth * Amount],
- (WindowSize - WindowWidth * Amount) * sizeof(WORD));
-
- for (i = 0; i < Amount * WindowWidth; i++)
- {
- WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
- }
-
- break;
- }
-
- case SCROLL_DIRECTION_DOWN:
- {
- RtlMoveMemory(&WindowData[WindowWidth * Amount],
- WindowData,
- (WindowSize - WindowWidth * Amount) * sizeof(WORD));
-
- for (i = 0; i < Amount * WindowWidth; i++)
- {
- WindowData[i] = MAKEWORD(' ', FillAttribute);
- }
-
- break;
- }
-
- default:
- {
- // TODO: NOT IMPLEMENTED!
- UNIMPLEMENTED;
- }
- }
-
-Done:
- /* Write back the window data */
- BiosWriteWindow(WindowData, Rectangle, Page);
-
- /* Free the window buffer */
- HeapFree(GetProcessHeap(), 0, WindowData);
-
- return TRUE;
-}
-
-VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
-{
- WORD CharData = MAKEWORD(Character, Attribute);
- BYTE Row, Column;
-
- /* Make sure the page exists */
- if (Page >= BIOS_MAX_PAGES) return;
-
- /* Get the cursor location */
- BiosGetCursorPosition(&Row, &Column, Page);
-
- if (Character == '\a')
- {
- /* Bell control character */
- // NOTE: We may use what the terminal emulator offers to us...
- Beep(800, 200);
- return;
- }
- else if (Character == '\b')
- {
- /* Backspace control character */
- if (Column > 0)
- {
- Column--;
- }
- else if (Row > 0)
- {
- Column = Bda->ScreenColumns - 1;
- Row--;
- }
-
- /* Erase the existing character */
- CharData = MAKEWORD(' ', Attribute);
- EmulatorWriteMemory(&EmulatorContext,
- TO_LINEAR(TEXT_VIDEO_SEG,
- Page * Bda->VideoPageSize +
- (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
- (LPVOID)&CharData,
- sizeof(WORD));
- }
- else if (Character == '\t')
- {
- /* Horizontal Tabulation control character */
- do
- {
- // Taken from DOSBox
- BiosPrintCharacter(' ', Attribute, Page);
- BiosGetCursorPosition(&Row, &Column, Page);
- } while (Column % 8);
- }
- else if (Character == '\n')
- {
- /* Line Feed control character */
- Row++;
- }
- else if (Character == '\r')
- {
- /* Carriage Return control character */
- Column = 0;
- }
- else
- {
- /* Default character */
-
- /* Write the character */
- EmulatorWriteMemory(&EmulatorContext,
- TO_LINEAR(TEXT_VIDEO_SEG,
- Page * Bda->VideoPageSize +
- (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
- (LPVOID)&CharData,
- sizeof(WORD));
-
- /* Advance the cursor */
- Column++;
- }
-
- /* Check if it passed the end of the row */
- if (Column >= Bda->ScreenColumns)
- {
- /* Return to the first column and go to the next line */
- Column = 0;
- Row++;
- }
-
- /* Scroll the screen up if needed */
- if (Row > Bda->ScreenRows)
- {
- /* The screen must be scrolled up */
- SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
-
- BiosScrollWindow(SCROLL_DIRECTION_UP,
- 1,
- Rectangle,
- Page,
- DEFAULT_ATTRIBUTE);
-
- Row--;
- }
-
- /* Set the cursor position */
- BiosSetCursorPosition(Row, Column, Page);
-}
-
-VOID WINAPI BiosVideoService(LPWORD Stack)
-{
- switch (getAH())
- {
- /* Set Video Mode */
- case 0x00:
- {
- BiosSetVideoMode(getAL());
- VgaClearMemory();
- break;
- }
-
- /* Set Text-Mode Cursor Shape */
- case 0x01:
- {
- /* Update the BDA */
- Bda->CursorStartLine = getCH();
- Bda->CursorEndLine = getCL();
-
- /* Modify the CRTC registers */
- VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
- VgaWritePort(VGA_CRTC_DATA , Bda->CursorStartLine);
- VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
- VgaWritePort(VGA_CRTC_DATA , Bda->CursorEndLine);
-
- break;
- }
-
- /* Set Cursor Position */
- case 0x02:
- {
- BiosSetCursorPosition(getDH(), getDL(), getBH());
- break;
- }
-
- /* Get Cursor Position */
- case 0x03:
- {
- /* Make sure the selected video page exists */
- if (getBH() >= BIOS_MAX_PAGES) break;
-
- /* Return the result */
- setAX(0);
- setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine));
- setDX(Bda->CursorPosition[getBH()]);
- break;
- }
-
- /* Query Light Pen */
- case 0x04:
- {
- /*
- * On modern BIOSes, this function returns 0
- * so that we can ignore the other registers.
- */
- setAX(0);
- break;
- }
-
- /* Select Active Display Page */
- case 0x05:
- {
- BiosSetVideoPage(getAL());
- break;
- }
-
- /* Scroll Window Up/Down */
- case 0x06:
- case 0x07:
- {
- SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
-
- /* Call the internal function */
- BiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP
- : SCROLL_DIRECTION_DOWN,
- getAL(),
- Rectangle,
- Bda->VideoPage,
- getBH());
-
- break;
- }
-
- /* Read/Write Character From Cursor Position */
- case 0x08:
- case 0x09:
- case 0x0A:
- {
- WORD CharacterData = MAKEWORD(getAL(), getBL());
- BYTE Page = getBH();
- DWORD Offset;
-
- /* Check if the page exists */
- if (Page >= BIOS_MAX_PAGES) break;
-
- /* Find the offset of the character */
- Offset = Page * Bda->VideoPageSize +
- (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns +
- LOBYTE(Bda->CursorPosition[Page])) * 2;
-
- if (getAH() == 0x08)
- {
- /* Read from the video memory */
- VgaReadMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
- (LPVOID)&CharacterData,
- sizeof(WORD));
-
- /* Return the character in AX */
- setAX(CharacterData);
- }
- else
- {
- /* Write to video memory */
- VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
- (LPVOID)&CharacterData,
- (getBH() == 0x09) ? sizeof(WORD) : sizeof(BYTE));
- }
-
- break;
- }
-
- /* Teletype Output */
- case 0x0E:
- {
- BiosPrintCharacter(getAL(), getBL(), getBH());
- break;
- }
-
- /* Get Current Video Mode */
- case 0x0F:
- {
- setAX(MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
- setBX(MAKEWORD(getBL(), Bda->VideoPage));
- break;
- }
-
- /* Palette Control */
- case 0x10:
- {
- switch (getAL())
- {
- /* Set Single Palette Register */
- case 0x00:
- {
- /* Write the index */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, getBL());
-
- /* Write the data */
- VgaWritePort(VGA_AC_WRITE, getBH());
-
- /* Enable screen and disable palette access */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, 0x20);
- break;
- }
-
- /* Set Overscan Color */
- case 0x01:
- {
- /* Write the index */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
-
- /* Write the data */
- VgaWritePort(VGA_AC_WRITE, getBH());
-
- /* Enable screen and disable palette access */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, 0x20);
- break;
- }
-
- /* Set All Palette Registers */
- case 0x02:
- {
- INT i;
- LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
-
- /* Set the palette registers */
- for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
- {
- /* Write the index */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, i);
-
- /* Write the data */
- VgaWritePort(VGA_AC_WRITE, Buffer[i]);
- }
-
- /* Set the overscan register */
- VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
- VgaWritePort(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
-
- /* Enable screen and disable palette access */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, 0x20);
- break;
- }
-
- /* Get Single Palette Register */
- case 0x07:
- {
- /* Write the index */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, getBL());
-
- /* Read the data */
- setBH(VgaReadPort(VGA_AC_READ));
-
- /* Enable screen and disable palette access */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, 0x20);
- break;
- }
-
- /* Get Overscan Color */
- case 0x08:
- {
- /* Write the index */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
-
- /* Read the data */
- setBH(VgaReadPort(VGA_AC_READ));
-
- /* Enable screen and disable palette access */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, 0x20);
- break;
- }
-
- /* Get All Palette Registers */
- case 0x09:
- {
- INT i;
- LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
-
- /* Get the palette registers */
- for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
- {
- /* Write the index */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, i);
-
- /* Read the data */
- Buffer[i] = VgaReadPort(VGA_AC_READ);
- }
-
- /* Get the overscan register */
- VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
- Buffer[VGA_AC_PAL_F_REG + 1] = VgaReadPort(VGA_AC_READ);
-
- /* Enable screen and disable palette access */
- VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index
state
- VgaWritePort(VGA_AC_INDEX, 0x20);
- break;
- }
-
- /* Set Individual DAC Register */
- case 0x10:
- {
- /* Write the index */
- // Certainly in BL and not in BX as said by Ralf Brown...
- VgaWritePort(VGA_DAC_WRITE_INDEX, getBL());
-
- /* Write the data in this order: Red, Green, Blue */
- VgaWritePort(VGA_DAC_DATA, getDH());
- VgaWritePort(VGA_DAC_DATA, getCH());
- VgaWritePort(VGA_DAC_DATA, getCL());
-
- break;
- }
-
- /* Set Block of DAC Registers */
- case 0x12:
- {
- INT i;
- LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
-
- /* Write the index */
- // Certainly in BL and not in BX as said by Ralf Brown...
- VgaWritePort(VGA_DAC_WRITE_INDEX, getBL());
-
- for (i = 0; i < getCX(); i++)
- {
- /* Write the data in this order: Red, Green, Blue */
- VgaWritePort(VGA_DAC_DATA, *Buffer++);
- VgaWritePort(VGA_DAC_DATA, *Buffer++);
- VgaWritePort(VGA_DAC_DATA, *Buffer++);
- }
-
- break;
- }
-
- /* Get Individual DAC Register */
- case 0x15:
- {
- /* Write the index */
- VgaWritePort(VGA_DAC_READ_INDEX, getBL());
-
- /* Read the data in this order: Red, Green, Blue */
- setDH(VgaReadPort(VGA_DAC_DATA));
- setCH(VgaReadPort(VGA_DAC_DATA));
- setCL(VgaReadPort(VGA_DAC_DATA));
-
- break;
- }
-
- /* Get Block of DAC Registers */
- case 0x17:
- {
- INT i;
- LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
-
- /* Write the index */
- // Certainly in BL and not in BX as said by Ralf Brown...
- VgaWritePort(VGA_DAC_READ_INDEX, getBL());
-
- for (i = 0; i < getCX(); i++)
- {
- /* Write the data in this order: Red, Green, Blue */
- *Buffer++ = VgaReadPort(VGA_DAC_DATA);
- *Buffer++ = VgaReadPort(VGA_DAC_DATA);
- *Buffer++ = VgaReadPort(VGA_DAC_DATA);
- }
-
- break;
- }
-
- default:
- {
- DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT
IMPLEMENTED\n",
- getAL());
- break;
- }
- }
-
- break;
- }
-
- /* Scroll Window */
- case 0x12:
- {
- SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
-
- /* Call the internal function */
- BiosScrollWindow(getBL(),
- getAL(),
- Rectangle,
- Bda->VideoPage,
- DEFAULT_ATTRIBUTE);
-
- break;
- }
-
- /* Display combination code */
- case 0x1A:
- {
- switch(getAL())
- {
- case 0x00: /* Get Display combiantion code */
- setAX(MAKEWORD(0x1A, 0x1A));
- setBX(MAKEWORD(0x08, 0x00)); /* VGA w/ color analog display */
- break;
- case 0x01: /* Set Display combination code */
- DPRINT1("Set Display combination code - Unsupported\n");
- break;
- default:
- break;
- }
- break;
- }
-
- default:
- {
- DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n",
- getAH());
- }
- }
-}
-
-VOID WINAPI BiosEquipmentService(LPWORD Stack)
-{
- /* Return the equipment list */
- setAX(Bda->EquipmentList);
-}
-
-VOID WINAPI BiosGetMemorySize(LPWORD Stack)
-{
- /* Return the conventional memory size in kB, typically 640 kB */
- setAX(Bda->MemorySize);
-}
-
-VOID WINAPI BiosMiscService(LPWORD Stack)
-{
- switch (getAH())
- {
- /* Copy Extended Memory */
- case 0x87:
- {
- DWORD Count = (DWORD)getCX() * 2;
- PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(),
getSI());
- DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) +
(Gdt[2].BaseHigh << 24);
- DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16);
- DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) +
(Gdt[3].BaseHigh << 24);
- DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16);
-
- /* Check for flags */
- if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF;
- if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF;
-
- if ((Count > SourceLimit) || (Count > DestLimit))
- {
- setAX(0x80);
- Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
-
- break;
- }
-
- /* Copy */
- RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase),
- (PVOID)((ULONG_PTR)BaseAddress + SourceBase),
- Count);
-
- setAX(ERROR_SUCCESS);
- Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
- break;
- }
-
- /* Get Extended Memory Size */
- case 0x88:
- {
- /* Return the number of KB of RAM after 1 MB */
- setAX((MAX_ADDRESS - 0x100000) / 1024);
-
- /* Clear CF */
- Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
-
- break;
- }
-
- default:
- {
- DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
- getAH());
- }
- }
-}
-
-VOID WINAPI BiosKeyboardService(LPWORD Stack)
-{
- switch (getAH())
- {
- /* Wait for keystroke and read */
- case 0x00:
- /* Wait for extended keystroke and read */
- case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h
- {
- /* Read the character (and wait if necessary) */
- setAX(BiosGetCharacter());
- break;
- }
-
- /* Get keystroke status */
- case 0x01:
- /* Get extended keystroke status */
- case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h
- {
- WORD Data = BiosPeekCharacter();
-
- if (Data != 0xFFFF)
- {
- /* There is a character, clear ZF and return it */
- Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
- setAX(Data);
- }
- else
- {
- /* No character, set ZF */
- Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
- }
-
- break;
- }
-
- /* Get shift status */
- case 0x02:
- {
- /* Return the lower byte of the keyboard shift status word */
- setAL(LOBYTE(Bda->KeybdShiftFlags));
- break;
- }
-
- /* Reserved */
- case 0x04:
- {
- DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n");
- break;
- }
-
- /* Push keystroke */
- case 0x05:
- {
- /* Return 0 if success, 1 if failure */
- setAL(BiosKbdBufferPush(getCX()) == FALSE);
- break;
- }
-
- /* Get extended shift status */
- case 0x12:
- {
- /*
- * Be careful! The returned word is similar to Bda->KeybdShiftFlags
- * but the high byte is organized differently:
- * the bytes 2 and 3 of the high byte are not the same...
- */
- WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
-
- /* Return the extended keyboard shift status word */
- setAX(KeybdShiftFlags);
- break;
- }
-
- default:
- {
- DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n",
- getAH());
- }
- }
-}
-
-VOID WINAPI BiosTimeService(LPWORD Stack)
-{
- switch (getAH())
- {
- case 0x00:
- {
- /* Set AL to 1 if midnight had passed, 0 otherwise */
- setAL(Bda->MidnightPassed ? 0x01 : 0x00);
-
- /* Return the tick count in CX:DX */
- setCX(HIWORD(Bda->TickCounter));
- setDX(LOWORD(Bda->TickCounter));
-
- /* Reset the midnight flag */
- Bda->MidnightPassed = FALSE;
-
- break;
- }
-
- case 0x01:
- {
- /* Set the tick count to CX:DX */
- Bda->TickCounter = MAKELONG(getDX(), getCX());
-
- /* Reset the midnight flag */
- Bda->MidnightPassed = FALSE;
-
- break;
- }
-
- default:
- {
- DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
- getAH());
- }
- }
-}
-
-VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
-{
- /* Increase the system tick count */
- Bda->TickCounter++;
}
VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack)
Modified: branches/ntvdm/subsystems/ntvdm/bios.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.h?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] Sun Jan 5 21:26:33 2014
@@ -151,31 +151,12 @@
extern PBIOS_DATA_AREA Bda;
+WORD BiosPeekCharacter(VOID);
+WORD BiosGetCharacter(VOID);
+VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page);
+
BOOLEAN BiosInitialize(VOID);
VOID BiosCleanup(VOID);
-BYTE BiosGetVideoMode(VOID);
-BOOLEAN BiosSetVideoMode(BYTE ModeNumber);
-WORD BiosPeekCharacter(VOID);
-WORD BiosGetCharacter(VOID);
-VOID BiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page);
-VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page);
-VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page);
-BOOLEAN BiosScrollWindow(
- INT Direction,
- DWORD Amount,
- SMALL_RECT Rectangle,
- BYTE Page,
- BYTE FillAttribute
-);
-
-VOID WINAPI BiosVideoService(LPWORD Stack);
-VOID WINAPI BiosEquipmentService(LPWORD Stack);
-VOID WINAPI BiosGetMemorySize(LPWORD Stack);
-VOID WINAPI BiosMiscService(LPWORD Stack);
-VOID WINAPI BiosKeyboardService(LPWORD Stack);
-VOID WINAPI BiosTimeService(LPWORD Stack);
-VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack);
-
VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack);
#endif // _BIOS_H_
Modified: branches/ntvdm/subsystems/ntvdm/vga.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/vga.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/vga.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/vga.c [iso-8859-1] Sun Jan 5 21:26:33 2014
@@ -171,8 +171,7 @@
#endif
-static HANDLE VgaSavedConsoleHandle = NULL;
-static CONSOLE_SCREEN_BUFFER_INFO VgaSavedConsoleInfo;
+static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
static BYTE VgaMemory[VGA_NUM_BANKS * VGA_BANK_SIZE];
static LPVOID ConsoleFramebuffer = NULL;
@@ -234,15 +233,16 @@
/* Double-word addressing */
return 4; // sizeof(DWORD)
}
-
- if (VgaCrtcRegisters[VGA_CRTC_MODE_CONTROL_REG] & VGA_CRTC_MODE_CONTROL_BYTE)
+ else if (VgaCrtcRegisters[VGA_CRTC_MODE_CONTROL_REG] &
VGA_CRTC_MODE_CONTROL_BYTE)
{
/* Byte addressing */
return 1; // sizeof(BYTE)
}
-
- /* Word addressing */
- return 2; // sizeof(WORD)
+ else
+ {
+ /* Word addressing */
+ return 2; // sizeof(WORD)
+ }
}
static inline DWORD VgaTranslateReadAddress(DWORD Address)
@@ -611,8 +611,8 @@
/* Release the console framebuffer mutex */
ReleaseMutex(ConsoleMutex);
- /* Switch back to the default console buffer */
- // SetConsoleActiveScreenBuffer(VgaSavedConsoleHandle);
+ /* Switch back to the default console text buffer */
+ // SetConsoleActiveScreenBuffer(TextConsoleBuffer);
/* Cleanup the video data */
CloseHandle(ConsoleMutex);
@@ -630,8 +630,8 @@
SetConsoleActiveScreenBuffer(TextConsoleBuffer);
/* Resize the console */
- ConRect.Left = 0; // VgaSavedConsoleInfo.srWindow.Left;
- ConRect.Top = VgaSavedConsoleInfo.srWindow.Top;
+ ConRect.Left = 0; // ConsoleInfo.srWindow.Left;
+ ConRect.Top = ConsoleInfo.srWindow.Top;
ConRect.Right = ConRect.Left + Resolution->X - 1;
ConRect.Bottom = ConRect.Top + Resolution->Y - 1;
/*
@@ -646,7 +646,7 @@
SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect);
SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
/* Update the saved console information */
- GetConsoleScreenBufferInfo(TextConsoleBuffer, &VgaSavedConsoleInfo);
+ GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo);
/* Allocate a framebuffer */
ConsoleFramebuffer = HeapAlloc(GetProcessHeap(),
@@ -689,9 +689,6 @@
static VOID VgaChangeMode(VOID)
{
COORD Resolution = VgaGetDisplayResolution();
-
- /* Reset the mode change flag */
- // ModeChanged = FALSE;
if (ScreenMode == GRAPHICS_MODE)
{
@@ -929,7 +926,9 @@
else
{
/* Text mode */
+ DWORD CurrentAddr;
PCHAR_INFO CharBuffer = (PCHAR_INFO)ConsoleFramebuffer;
+ CHAR_INFO CharInfo;
/* Loop through the scanlines */
for (i = 0; i < Resolution.Y; i++)
@@ -937,8 +936,7 @@
/* Loop through the characters */
for (j = 0; j < Resolution.X; j++)
{
- DWORD CurrentAddr = LOWORD((Address + j) * AddressSize);
- CHAR_INFO CharInfo;
+ CurrentAddr = LOWORD((Address + j) * AddressSize);
/* Plane 0 holds the character itself */
CharInfo.Char.AsciiChar = VgaMemory[CurrentAddr];
@@ -976,7 +974,7 @@
VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG]);
/* Just return if we are not in text mode */
- if ((VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) != 0) return;
+ if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) return;
if (CursorStart < CursorEnd)
{
@@ -1078,14 +1076,14 @@
if (!ModeChanged && !CursorMoved && !PaletteChanged &&
!NeedsUpdate)
return;
+ /* Change the display mode */
+ if (ModeChanged) VgaChangeMode();
+
+ /* Change the text cursor location */
+ if (CursorMoved) VgaUpdateTextCursor();
+
/* Retrieve the current resolution */
Resolution = VgaGetDisplayResolution();
-
- /* Change the display mode */
- if (ModeChanged) VgaChangeMode();
-
- /* Change the text cursor location */
- if (CursorMoved) VgaUpdateTextCursor();
if (PaletteChanged)
{
@@ -1492,21 +1490,12 @@
BOOLEAN VgaInitialize(HANDLE TextHandle)
{
- INT i, j;
- COORD Resolution;
- DWORD AddressSize;
- DWORD ScanlineSize;
- COORD Origin = { 0, 0 };
- SMALL_RECT ScreenRect;
- PCHAR_INFO CharBuffer;
- DWORD Address = 0;
- DWORD CurrentAddr;
+ /* Save the default text-mode console output handle */
+ if (TextHandle == INVALID_HANDLE_VALUE) return FALSE;
+ TextConsoleBuffer = TextHandle;
/* Save the console information */
- if (TextHandle == INVALID_HANDLE_VALUE) return FALSE;
- VgaSavedConsoleHandle = TextHandle;
- if (!GetConsoleScreenBufferInfo(VgaSavedConsoleHandle,
- &VgaSavedConsoleInfo))
+ if (!GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo))
{
return FALSE;
}
@@ -1515,8 +1504,8 @@
if (!VgaInitializePalette()) return FALSE;
/***/ VgaResetPalette(); /***/
- /* Save the default text-mode console output handle */
- TextConsoleBuffer = TextHandle;
+ /* Switch to the text buffer */
+ SetConsoleActiveScreenBuffer(TextConsoleBuffer);
/* Clear the VGA memory */
VgaClearMemory();
@@ -1536,45 +1525,6 @@
RegisterIoPort(0x3CE, VgaReadPort, VgaWritePort); // VGA_GC_INDEX
RegisterIoPort(0x3CF, VgaReadPort, VgaWritePort); // VGA_GC_DATA
- /* Set the default video mode */
- BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
- VgaChangeMode();
-
- /* Get the data */
- Resolution = VgaGetDisplayResolution();
- CharBuffer = (PCHAR_INFO)ConsoleFramebuffer;
- AddressSize = VgaGetAddressSize();
- ScreenRect.Left = ScreenRect.Top = 0;
- ScreenRect.Right = Resolution.X;
- ScreenRect.Bottom = Resolution.Y;
- ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
-
- /* Read the data from the console into the framebuffer */
- ReadConsoleOutputA(TextConsoleBuffer,
- CharBuffer,
- Resolution,
- Origin,
- &ScreenRect);
-
- /* Loop through the scanlines */
- for (i = 0; i < Resolution.Y; i++)
- {
- /* Loop through the characters */
- for (j = 0; j < Resolution.X; j++)
- {
- CurrentAddr = LOWORD((Address + j) * AddressSize);
-
- /* Store the character in plane 0 */
- VgaMemory[CurrentAddr] = CharBuffer[i * Resolution.X + j].Char.AsciiChar;
-
- /* Store the attribute in plane 1 */
- VgaMemory[CurrentAddr + VGA_BANK_SIZE] = (BYTE)CharBuffer[i * Resolution.X +
j].Attributes;
- }
-
- /* Move to the next scanline */
- Address += ScanlineSize;
- }
-
/* Return success */
return TRUE;
}