Author: aandrejevic
Date: Sun Jul 3 19:06:33 2016
New Revision: 71803
URL:
http://svn.reactos.org/svn/reactos?rev=71803&view=rev
Log:
[NTVDM]
Implement getting/setting the current VESA video mode.
Reset the extended SVGA registers when switching to a standard VGA mode.
Modified:
trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c
trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.h
trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c
trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c [iso-8859-1] Sun Jul 3 19:06:33
2016
@@ -15,6 +15,8 @@
#include "emulator.h"
#include "cpu/cpu.h"
+#include "bios32p.h"
+#include "hardware/video/svga.h"
#include "vbe.h"
@@ -38,7 +40,7 @@
{ 0x11, 0x11, NULL /* TODO */, NULL /* VGA */ },
{ 0x12, 0x12, NULL /* TODO */, NULL /* VGA */ },
{ 0x13, 0x13, NULL /* TODO */, NULL /* VGA */ },
- { 0x14, 0xFFFF, NULL /* TODO */, NULL /* TODO */ },
+ { 0x14, 0xFFFF, NULL /* TODO */, NULL },
{ 0x54, 0x10A, NULL /* TODO */, NULL /* TODO */ },
{ 0x55, 0x109, NULL /* TODO */, NULL /* TODO */ },
{ 0x58, 0x102, NULL /* TODO */, NULL /* TODO */ },
@@ -56,16 +58,222 @@
{ 0x6C, 0x106, NULL /* TODO */, NULL /* TODO */ },
{ 0x6D, 0x107, NULL /* TODO */, NULL /* TODO */ },
{ 0x71, 0x112, NULL /* TODO */, NULL /* TODO */ },
- { 0x72, 0xFFFF, NULL /* TODO */, NULL /* TODO */ },
- { 0x73, 0xFFFF, NULL /* TODO */, NULL /* TODO */ },
+ { 0x72, 0xFFFF, NULL /* TODO */, NULL },
+ { 0x73, 0xFFFF, NULL /* TODO */, NULL },
{ 0x74, 0x117, NULL /* TODO */, NULL /* TODO */ },
{ 0x75, 0x11A, NULL /* TODO */, NULL /* TODO */ },
- { 0x76, 0xFFFF, NULL /* TODO */, NULL /* TODO */ },
+ { 0x76, 0xFFFF, NULL /* TODO */, NULL },
{ 0x78, 0x115, NULL /* TODO */, NULL /* TODO */ },
{ 0x79, 0x118, NULL /* TODO */, NULL /* TODO */ },
};
+/* PRIVATE FUNCTIONS **********************************************************/
+
+PCVBE_MODE VbeGetModeByNumber(WORD Number)
+{
+ INT i;
+
+ Number &= 0x1FF;
+
+ /* Find the mode */
+ for (i = 0; i < VBE_MODE_COUNT; i++)
+ {
+ if ((!(Number & 0x100) && (Number == Modes[i].Number))
+ || ((Number & 0x100) && (Number== Modes[i].VesaNumber)))
+ {
+ return &Modes[i];
+ }
+ }
+
+ return NULL;
+}
+
+/* This function is based on VgaSetRegisters in vidbios.c */
+static VOID VbeSetExtendedRegisters(PSVGA_REGISTERS Registers)
+{
+ UINT i;
+
+ /* Disable interrupts */
+ BOOLEAN Interrupts = getIF();
+ setIF(0);
+
+ /*
+ * Set the CRT base address according to the selected mode,
+ * monochrome or color. The following macros:
+ * VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then
+ * used to access the correct VGA I/O ports.
+ */
+ Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR
+ : VGA_CRTC_INDEX_MONO;
+ /* Bit 1 indicates whether display is color (0) or monochrome (1) */
+ Bda->VGAOptions = (Bda->VGAOptions & 0xFD) | (!(Registers->Misc
& 0x01) << 1);
+ Bda->CrtModeControl = (Bda->CrtModeControl & 0xFB) | (!(Registers->Misc
& 0x01) << 1);
+
+ /* Update blink bit in BDA */
+ if (Registers->Attribute[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_BLINK)
+ Bda->CrtModeControl |= (1 << 5);
+ else
+ Bda->CrtModeControl &= ~(1 << 5);
+
+ /* Turn the video off */
+ IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_CLOCK_REG);
+ IOWriteB(VGA_SEQ_DATA , IOReadB(VGA_SEQ_DATA) | VGA_SEQ_CLOCK_SD);
+
+ /* Write the misc register */
+ IOWriteB(VGA_MISC_WRITE, Registers->Misc);
+
+ /* Synchronous reset on */
+ IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
+ IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_AR );
+
+ /* Write the sequencer registers */
+ for (i = 1; i < SVGA_SEQ_MAX_REG; i++)
+ {
+ if (i != VGA_SEQ_MAX_REG && i != SVGA_SEQ_UNLOCK_REG)
+ {
+ IOWriteB(VGA_SEQ_INDEX, i);
+ IOWriteB(VGA_SEQ_DATA , Registers->Sequencer[i]);
+ }
+ }
+
+ /* Synchronous reset off */
+ IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
+ IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR);
+
+ /* Unlock CRTC registers 0-7 */
+ IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
+ IOWriteB(VGA_CRTC_DATA , IOReadB(VGA_CRTC_DATA) | 0x80);
+ IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
+ IOWriteB(VGA_CRTC_DATA , IOReadB(VGA_CRTC_DATA) & ~0x80);
+ // Make sure they remain unlocked
+ Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
+ Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
+
+ /* Write the CRTC registers */
+ for (i = 0; i < SVGA_CRTC_MAX_REG; i++)
+ {
+ if ((i < SVGA_CRTC_UNUSED0_REG || i > SVGA_CRTC_UNUSED6_REG) && i
!= SVGA_CRTC_UNUSED7_REG)
+ {
+ IOWriteB(VGA_CRTC_INDEX, i);
+ IOWriteB(VGA_CRTC_DATA , Registers->CRT[i]);
+ }
+ }
+
+ /* Write the GC registers */
+ for (i = 0; i < SVGA_GC_MAX_REG; i++)
+ {
+ if (i != SVGA_GC_UNUSED0_REG && i != SVGA_GC_UNUSED11_REG
+ && (i < SVGA_GC_UNUSED1_REG || i > SVGA_GC_UNUSED10_REG))
+ {
+ IOWriteB(VGA_GC_INDEX, i);
+ IOWriteB(VGA_GC_DATA , Registers->Graphics[i]);
+ }
+ }
+
+ /* Write the AC registers */
+ for (i = 0; i < VGA_AC_MAX_REG; i++)
+ {
+ /* Write the index */
+ IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+ IOWriteB(VGA_AC_INDEX, i);
+
+ /* Write the data */
+ IOWriteB(VGA_AC_WRITE, Registers->Attribute[i]);
+ }
+
+ /* Perform 4 dummy reads from the DAC mask to access the hidden register */
+ for (i = 0; i < 4; i++) IOReadB(VGA_DAC_MASK);
+
+ /* Set the hidden register */
+ IOWriteB(VGA_DAC_MASK, Registers->Hidden);
+
+ /* Set the PEL mask */
+ IOWriteB(VGA_DAC_MASK, 0xFF);
+
+ /* Enable screen and disable palette access */
+ IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
+ IOWriteB(VGA_AC_INDEX, 0x20);
+
+ /* Turn the video on */
+ IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_CLOCK_REG);
+ IOWriteB(VGA_SEQ_DATA , IOReadB(VGA_SEQ_DATA) & ~VGA_SEQ_CLOCK_SD);
+
+ /* Restore interrupts */
+ setIF(Interrupts);
+}
+
+
/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN WINAPI VbeSetExtendedVideoMode(BYTE ModeNumber)
+{
+ PCVBE_MODE Mode = VbeGetModeByNumber(ModeNumber);
+
+ /* At this point, Mode->Registers shouldn't be NULL unless the mode is
unimplemented */
+ if (Mode->Registers == NULL)
+ {
+ DPRINT1("Extended video mode %02X still UNIMPLEMENTED.\n",
ModeNumber);
+ return FALSE;
+ }
+
+ /* Set the registers */
+ VbeSetExtendedRegisters(Mode->Registers);
+
+ /* Update the current video mode in the BDA */
+ Bda->VideoMode = ModeNumber;
+
+ return TRUE;
+}
+
+VOID WINAPI VbeResetExtendedRegisters(VOID)
+{
+ BYTE i;
+
+ /* Disable interrupts */
+ BOOLEAN Interrupts = getIF();
+ setIF(0);
+
+ /* Reset the extended sequencer registers */
+ for (i = SVGA_SEQ_EXT_MODE_REG; i < SVGA_SEQ_MAX_REG; i++)
+ {
+ if (i != VGA_SEQ_MAX_REG && i != SVGA_SEQ_UNLOCK_REG)
+ {
+ IOWriteB(VGA_SEQ_INDEX, i);
+ IOWriteB(VGA_SEQ_DATA, 0x00);
+ }
+ }
+
+ /* Reset the extended CRTC registers */
+ for (i = SVGA_CRTC_INTERLACE_END_REG; i < SVGA_CRTC_MAX_REG; i++)
+ {
+ if ((i < SVGA_CRTC_UNUSED0_REG || i > SVGA_CRTC_UNUSED6_REG) && i
!= SVGA_CRTC_UNUSED7_REG)
+ {
+ IOWriteB(VGA_CRTC_INDEX, i);
+ IOWriteB(VGA_CRTC_DATA, 0x00);
+ }
+ }
+
+ /* Reset the extended GC registers */
+ for (i = SVGA_GC_OFFSET_0_REG; i < SVGA_GC_MAX_REG; i++)
+ {
+ if (i != SVGA_GC_UNUSED0_REG && i != SVGA_GC_UNUSED11_REG
+ && (i < SVGA_GC_UNUSED1_REG || i > SVGA_GC_UNUSED10_REG))
+ {
+ IOWriteB(VGA_GC_INDEX, i);
+ IOWriteB(VGA_GC_DATA, 0x00);
+ }
+ }
+
+ /*
+ * And finally, reset the hidden register. This requires 4 dummy reads from
+ * the DAC mask register.
+ */
+ for (i = 0; i < 4; i++) IOReadB(VGA_DAC_MASK);
+ IOWriteB(VGA_DAC_MASK, 0x00);
+
+ /* Restore interrupts */
+ setIF(Interrupts);
+}
VOID WINAPI VbeService(LPWORD Stack)
{
@@ -117,36 +325,30 @@
/* Get VBE Mode Information */
case 0x01:
{
- WORD ModeNumber = getCX() & 0x1FF;
+ PCVBE_MODE Mode = VbeGetModeByNumber(getCX());
PWORD Data = NULL;
/* Function recognized */
setAL(0x4F);
- /* Find the mode */
- for (i = 0; i < VBE_MODE_COUNT; i++)
- {
- if ((!(ModeNumber & 0x100) && (ModeNumber ==
Modes[i].Number))
- || ((ModeNumber & 0x100) && (ModeNumber ==
Modes[i].VesaNumber)))
- {
- Data = (PWORD)Modes[i].Info;
-
- if (Data == NULL)
- {
- DPRINT1("WARNING: The mode information for mode %02X (%03X)
is missing!\n",
- Modes[i].Number,
- Modes[i].VesaNumber);
- }
- }
- }
-
- if (Data == NULL)
+ if (Mode == NULL)
{
/* Mode not found */
setAH(1);
break;
}
+ Data = (PWORD)Mode->Info;
+ if (Data == NULL)
+ {
+ DPRINT1("WARNING: The mode information for mode %02X (%03X) is
missing!\n",
+ Mode->Number,
+ Mode->VesaNumber);
+
+ setAH(1);
+ break;
+ }
+
/* Clear the buffer */
for (i = 0; i < 128; i++)
{
@@ -160,6 +362,52 @@
}
setAH(0);
+ break;
+ }
+
+ /* Set VBE Mode */
+ case 0x02:
+ {
+ PCVBE_MODE Mode = VbeGetModeByNumber(getBX());
+
+ if (Mode->Registers == NULL)
+ {
+ /* Call the VGA BIOS */
+ setAH(0x00);
+ setAL(Mode->Number);
+ Int32Call(&BiosContext, BIOS_VIDEO_INTERRUPT);
+
+ setAL(0x4F);
+ setAH(Bda->VideoMode == Mode->Number);
+ }
+ else
+ {
+ /* This is an extended video mode */
+ setAL(0x4F);
+ setAH(VbeSetExtendedVideoMode(Mode->Number));
+ }
+
+ break;
+ }
+
+ /* Get Current VBE Mode */
+ case 0x03:
+ {
+ PCVBE_MODE Mode = VbeGetModeByNumber(Bda->VideoMode);
+
+ setAL(0x4F);
+
+ if (Mode)
+ {
+ setBX(Mode->VesaNumber != 0xFFFF
+ ? Mode->VesaNumber : Mode->Number);
+ setAH(0);
+ }
+ else
+ {
+ setAH(1);
+ }
+
break;
}
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.h [iso-8859-1] Sun Jul 3 19:06:33
2016
@@ -100,9 +100,13 @@
PSVGA_REGISTERS Registers; // NULL means "forward to VGABIOS"
} VBE_MODE, *PVBE_MODE;
+typedef const struct _VBE_MODE *PCVBE_MODE;
+
/* FUNCTIONS ******************************************************************/
VOID WINAPI VbeService(LPWORD Stack);
+VOID WINAPI VbeResetExtendedRegisters(VOID);
+BOOLEAN WINAPI VbeSetExtendedVideoMode(BYTE ModeNumber);
BOOLEAN VbeInitialize(VOID);
#endif // _VBE_H_
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c [iso-8859-1] Sun Jul 3 19:06:33
2016
@@ -35,16 +35,6 @@
/**/
#include "../console/video.h"
/**/
-
-/* MACROS *********************************************************************/
-
-//
-// These macros are defined for ease-of-use of some VGA I/O ports
-// whose addresses depend whether we are in Monochrome or Colour mode.
-//
-#define VGA_INSTAT1_READ Bda->CrtBasePort + 6 // VGA_INSTAT1_READ_MONO or
VGA_INSTAT1_READ_COLOR
-#define VGA_CRTC_INDEX Bda->CrtBasePort // VGA_CRTC_INDEX_MONO or
VGA_CRTC_INDEX_COLOR
-#define VGA_CRTC_DATA Bda->CrtBasePort + 1 // VGA_CRTC_DATA_MONO or
VGA_CRTC_DATA_COLOR
/* PRIVATE VARIABLES **********************************************************/
@@ -2470,16 +2460,25 @@
/* Retrieve the real mode number and check its validity */
ModeNumber &= 0x7F;
// if (ModeNumber >= ARRAYSIZE(VideoModes))
+
+ DPRINT1("Switching to mode %02Xh (%02Xh) %s clearing the screen; VgaRegisters =
0x%p\n",
+ ModeNumber, OrgModeNumber, (DoNotClear ? "without" :
"and"), VideoModes[ModeNumber].VgaRegisters);
+
if (ModeNumber > BIOS_MAX_VIDEO_MODE)
{
- DPRINT1("VidBiosSetVideoMode -- Mode %02Xh invalid\n", ModeNumber);
- return FALSE;
+ /* This could be an extended video mode, so call the VBE BIOS */
+ return VbeSetExtendedVideoMode(ModeNumber);
}
- DPRINT1("Switching to mode %02Xh (%02Xh) %s clearing the screen; VgaRegisters =
0x%p\n",
- ModeNumber, OrgModeNumber, (DoNotClear ? "without" :
"and"), VideoModes[ModeNumber].VgaRegisters);
-
if (!VgaSetRegisters(VideoModes[ModeNumber].VgaRegisters)) return FALSE;
+ if (VbeInitialized && Bda->VideoMode > BIOS_MAX_VIDEO_MODE)
+ {
+ /*
+ * Since we're switching from an extended video mode to a standard VGA
+ * mode, tell the VBE BIOS to reset the extended registers.
+ */
+ VbeResetExtendedRegisters();
+ }
VgaChangePalette(ModeNumber);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h [iso-8859-1] Sun Jul 3 19:06:33
2016
@@ -104,6 +104,16 @@
#pragma pack(pop)
+/* MACROS *********************************************************************/
+
+//
+// These macros are defined for ease-of-use of some VGA I/O ports
+// whose addresses depend whether we are in Monochrome or Colour mode.
+//
+#define VGA_INSTAT1_READ Bda->CrtBasePort + 6 // VGA_INSTAT1_READ_MONO or
VGA_INSTAT1_READ_COLOR
+#define VGA_CRTC_INDEX Bda->CrtBasePort // VGA_CRTC_INDEX_MONO or
VGA_CRTC_INDEX_COLOR
+#define VGA_CRTC_DATA Bda->CrtBasePort + 1 // VGA_CRTC_DATA_MONO or
VGA_CRTC_DATA_COLOR
+
/* FUNCTIONS ******************************************************************/
VOID WINAPI VidBiosVideoService(LPWORD Stack);