mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
[NTVDM]
Implement getting/setting the current VESA video mode. Reset the extended SVGA registers when switching to a standard VGA mode. svn path=/trunk/; revision=71803
This commit is contained in:
@@ -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 @@ static const VBE_MODE Modes[VBE_MODE_COUNT] = {
|
||||
{ 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,17 +58,223 @@ static const VBE_MODE Modes[VBE_MODE_COUNT] = {
|
||||
{ 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)
|
||||
{
|
||||
INT i;
|
||||
@@ -117,36 +325,30 @@ VOID WINAPI VbeService(LPWORD Stack)
|
||||
/* 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++)
|
||||
{
|
||||
@@ -163,6 +365,52 @@ VOID WINAPI VbeService(LPWORD Stack)
|
||||
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;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DPRINT1("VESA BIOS Extensions function %02Xh NOT IMPLEMENTED!\n", getAL());
|
||||
|
||||
@@ -100,9 +100,13 @@ typedef struct _VBE_MODE
|
||||
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_
|
||||
|
||||
@@ -36,16 +36,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 @@ static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber)
|
||||
/* Retrieve the real mode number and check its validity */
|
||||
ModeNumber &= 0x7F;
|
||||
// if (ModeNumber >= ARRAYSIZE(VideoModes))
|
||||
if (ModeNumber > BIOS_MAX_VIDEO_MODE)
|
||||
{
|
||||
DPRINT1("VidBiosSetVideoMode -- Mode %02Xh invalid\n", ModeNumber);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* This could be an extended video mode, so call the VBE BIOS */
|
||||
return VbeSetExtendedVideoMode(ModeNumber);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -104,6 +104,16 @@ typedef struct _VGA_DYNAMIC_FUNC_TABLE
|
||||
|
||||
#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);
|
||||
|
||||
Reference in New Issue
Block a user