vesavbe.c
来自「适合KS8695X」· C语言 代码 · 共 1,215 行 · 第 1/3 页
C
1,215 行
/****************************************************************************
*
* The SuperVGA Kit - UniVBE Software Development Kit
*
* ========================================================================
*
* The contents of this file are subject to the SciTech MGL Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.scitechsoft.com/mgl-license.txt
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
*
* The Initial Developer of the Original Code is SciTech Software, Inc.
* All Rights Reserved.
*
* ========================================================================
*
* Language: ANSI C
* Environment: IBM PC Real Mode and 16/32 bit Protected Mode.
*
* Description: Module to implement a C callable interface to the standard
* VESA VBE routines. You should rip out this module and use it
* directly in your own applications, or you can use the
* high level SDK functions.
*
* MUST be compiled in the LARGE or FLAT models.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vesavbe.h"
#include "pmapi.h"
#include "drvlib/os/os.h"
/*---------------------------- Global Variables ---------------------------*/
#define VBE_SUCCESS 0x004F
#define MAX_LIN_PTRS 10
static uint VESABuf_len = 1024;/* Length of the VESABuf buffer */
static ibool haveRiva128; /* True if we have a Riva128 */
static VBE_state defState = {0}; /* Default state buffer */
static VBE_state *state = &defState; /* Pointer to current buffer */
static int VBE_shared = 0;
#ifndef REALMODE
static char localBuf[512]; /* Global PM string translate buf */
#define MAX_LOCAL_BUF &localBuf[511]
#endif
/*----------------------------- Implementation ----------------------------*/
/* static function in WinDirect for passing 32-bit registers to BIOS */
int PMAPI WD_int386(int intno, RMREGS *in, RMREGS *out);
void VBEAPI VBE_init(void)
/****************************************************************************
*
* Function: VBE_init
*
* Description: Initialises the VBE transfer buffer in real mode DC.memory.
* This routine is called by the VESAVBE module every time
* it needs to use the transfer buffer, so we simply allocate
* it once and then return.
*
****************************************************************************/
{
if (!state->VESABuf_ptr) {
/* Allocate a global buffer for communicating with the VESA VBE */
if ((state->VESABuf_ptr = PM_getVESABuf(&VESABuf_len, &state->VESABuf_rseg, &state->VESABuf_roff)) == NULL)
PM_fatalError("VESAVBE.C: Real mode memory allocation failed!");
}
}
void * VBEAPI VBE_getRMBuf(uint *len,uint *rseg,uint *roff)
/****************************************************************************
*
* Function: VBE_getRMBuf
*
* Description: This function returns the location and length of the real
* mode memory buffer for calling real mode functions.
*
****************************************************************************/
{
*len = VESABuf_len;
*rseg = state->VESABuf_rseg;
*roff = state->VESABuf_roff;
return state->VESABuf_ptr;
}
void VBEAPI VBE_setStateBuffer(VBE_state *s)
/****************************************************************************
*
* Function: VBE_setStateBuffer
*
* Description: This functions sets the internal state buffer for the
* VBE module to the passed in buffer. By default the internal
* global buffer is used, but you must use separate buffers
* for each device in a multi-controller environment.
*
****************************************************************************/
{
state = s;
}
void VBEAPI VBE_callESDI(RMREGS *regs, void *buffer, int size)
/****************************************************************************
*
* Function: VBE_callESDI
* Parameters: regs - Registers to load when calling VBE
* buffer - Buffer to copy VBE info block to
* size - Size of buffer to fill
*
* Description: Calls the VESA VBE and passes in a buffer for the VBE to
* store information in, which is then copied into the users
* buffer space. This works in protected mode as the buffer
* passed to the VESA VBE is allocated in conventional
* memory, and is then copied into the users memory block.
*
****************************************************************************/
{
RMSREGS sregs;
if (!state->VESABuf_ptr)
PM_fatalError("You *MUST* call VBE_init() before you can call the VESAVBE.C module!");
sregs.es = (ushort)state->VESABuf_rseg;
regs->x.di = (ushort)state->VESABuf_roff;
memcpy(state->VESABuf_ptr, buffer, size);
PM_int86x(0x10, regs, regs, &sregs);
memcpy(buffer, state->VESABuf_ptr, size);
}
#ifndef REALMODE
static char *VBE_copyStrToLocal(char *p,char *realPtr,char *max)
/****************************************************************************
*
* Function: VBE_copyStrToLocal
* Parameters: p - Flat model buffer to copy to
* realPtr - Real mode pointer to copy
* Returns: Pointer to the next byte after string
*
* Description: Copies the string from the real mode location pointed to
* by 'realPtr' into the flat model buffer pointed to by
* 'p'. We return a pointer to the next byte past the copied
* string.
*
****************************************************************************/
{
uchar *v;
v = PM_mapRealPointer((uint)((ulong)realPtr >> 16), (uint)((ulong)realPtr & 0xFFFF));
while (*v != 0 && p < max)
*p++ = *v++;
*p++ = 0;
return p;
}
static void VBE_copyShortToLocal(ushort *p,ushort *realPtr)
/****************************************************************************
*
* Function: VBE_copyShortToLocal
* Parameters: p - Flat model buffer to copy to
* realPtr - Real mode pointer to copy
*
* Description: Copies the mode table from real mode memory to the flat
* model buffer.
*
****************************************************************************/
{
ushort *v;
v = PM_mapRealPointer((uint)((ulong)realPtr >> 16),(uint)((ulong)realPtr & 0xFFFF));
while (*v != 0xFFFF)
*p++ = *v++;
*p = 0xFFFF;
}
#endif
int VBEAPI VBE_detectEXT(VBE_vgaInfo *vgaInfo,ibool forceUniVBE)
/****************************************************************************
*
* Function: VBE_detect
* Parameters: vgaInfo - Place to store the VGA information block
* Returns: VBE version number, or 0 if not detected.
*
* Description: Detects if a VESA VBE is out there and functioning
* correctly. If we detect a VBE interface we return the
* VGAInfoBlock returned by the VBE and the VBE version number.
*
****************************************************************************/
{
RMREGS regs;
regs.x.ax = 0x4F00; /* Get SuperVGA information */
if (forceUniVBE) {
regs.x.bx = 0x1234;
regs.x.cx = 0x4321;
}
else {
regs.x.bx = 0;
regs.x.cx = 0;
}
strncpy(vgaInfo->VESASignature,"VBE2",4);
VBE_callESDI(®s, vgaInfo, sizeof(*vgaInfo));
if (regs.x.ax != VBE_SUCCESS)
return 0;
if (strncmp(vgaInfo->VESASignature,"VESA",4) != 0)
return 0;
/* Check for bogus BIOSes that return a VBE version number that is
* not correct, and fix it up. We also check the OemVendorNamePtr for a
* valid value, and if it is invalid then we also reset to VBE 1.2.
*/
if (vgaInfo->VESAVersion >= 0x200 && vgaInfo->OemVendorNamePtr == 0)
vgaInfo->VESAVersion = 0x102;
#ifndef REALMODE
/* Relocate all the indirect information (mode tables, OEM strings
* etc) from the low 1Mb memory region into a static buffer in
* our default data segment. We do this to insulate the application
* from mapping the strings from real mode to protected mode.
*/
{
char *p,*p2;
p2 = VBE_copyStrToLocal(localBuf,vgaInfo->OemStringPtr,MAX_LOCAL_BUF);
vgaInfo->OemStringPtr = localBuf;
if (vgaInfo->VESAVersion >= 0x200) {
p = VBE_copyStrToLocal(p2,vgaInfo->OemVendorNamePtr,MAX_LOCAL_BUF);
vgaInfo->OemVendorNamePtr = p2;
p2 = VBE_copyStrToLocal(p,vgaInfo->OemProductNamePtr,MAX_LOCAL_BUF);
vgaInfo->OemProductNamePtr = p;
p = VBE_copyStrToLocal(p2,vgaInfo->OemProductRevPtr,MAX_LOCAL_BUF);
vgaInfo->OemProductRevPtr = p2;
VBE_copyShortToLocal((ushort*)p,vgaInfo->VideoModePtr);
vgaInfo->VideoModePtr = (ushort*)p;
}
else {
VBE_copyShortToLocal((ushort*)p2,vgaInfo->VideoModePtr);
vgaInfo->VideoModePtr = (ushort*)p2;
}
}
#endif
state->VBEMemory = vgaInfo->TotalMemory * 64;
/* Check for Riva128 based cards since they have broken triple buffering
* and stereo support.
*/
haveRiva128 = false;
if (vgaInfo->VESAVersion >= 0x300 &&
(strstr(vgaInfo->OemStringPtr,"NVidia") != NULL ||
strstr(vgaInfo->OemStringPtr,"Riva") != NULL)) {
haveRiva128 = true;
}
/* Check for Matrox G400 cards which claim to be VBE 3.0
* compliant yet they don't implement the refresh rate control
* functions.
*/
if (vgaInfo->VESAVersion >= 0x300 && (strcmp(vgaInfo->OemProductNamePtr,"Matrox G400") == 0))
vgaInfo->VESAVersion = 0x200;
return (state->VBEVersion = vgaInfo->VESAVersion);
}
int VBEAPI VBE_detect(VBE_vgaInfo *vgaInfo)
/****************************************************************************
*
* Function: VBE_detect
* Parameters: vgaInfo - Place to store the VGA information block
* Returns: VBE version number, or 0 if not detected.
*
* Description: Detects if a VESA VBE is out there and functioning
* correctly. If we detect a VBE interface we return the
* VGAInfoBlock returned by the VBE and the VBE version number.
*
****************************************************************************/
{
return VBE_detectEXT(vgaInfo,false);
}
ibool VBEAPI VBE_getModeInfo(int mode,VBE_modeInfo *modeInfo)
/****************************************************************************
*
* Function: VBE_getModeInfo
* Parameters: mode - VBE mode to get information for
* modeInfo - Place to store VBE mode information
* Returns: True on success, false if function failed.
*
* Description: Obtains information about a specific video mode from the
* VBE. You should use this function to find the video mode
* you wish to set, as the new VBE 2.0 mode numbers may be
* completely arbitrary.
*
****************************************************************************/
{
RMREGS regs;
int bits;
regs.x.ax = 0x4F01; /* Get mode information */
regs.x.cx = (ushort)mode;
VBE_callESDI(®s, modeInfo, sizeof(*modeInfo));
if (regs.x.ax != VBE_SUCCESS)
return false;
if ((modeInfo->ModeAttributes & vbeMdAvailable) == 0)
return false;
/* Map out triple buffer and stereo flags for NVidia Riva128
* chips.
*/
if (haveRiva128) {
modeInfo->ModeAttributes &= ~vbeMdTripleBuf;
modeInfo->ModeAttributes &= ~vbeMdStereo;
}
/* Support old style RGB definitions for VBE 1.1 BIOSes */
bits = modeInfo->BitsPerPixel;
if (modeInfo->MemoryModel == vbeMemPK && bits > 8) {
modeInfo->MemoryModel = vbeMemRGB;
switch (bits) {
case 15:
modeInfo->RedMaskSize = 5;
modeInfo->RedFieldPosition = 10;
modeInfo->GreenMaskSize = 5;
modeInfo->GreenFieldPosition = 5;
modeInfo->BlueMaskSize = 5;
modeInfo->BlueFieldPosition = 0;
modeInfo->RsvdMaskSize = 1;
modeInfo->RsvdFieldPosition = 15;
break;
case 16:
modeInfo->RedMaskSize = 5;
modeInfo->RedFieldPosition = 11;
modeInfo->GreenMaskSize = 5;
modeInfo->GreenFieldPosition = 5;
modeInfo->BlueMaskSize = 5;
modeInfo->BlueFieldPosition = 0;
modeInfo->RsvdMaskSize = 0;
modeInfo->RsvdFieldPosition = 0;
break;
case 24:
modeInfo->RedMaskSize = 8;
modeInfo->RedFieldPosition = 16;
modeInfo->GreenMaskSize = 8;
modeInfo->GreenFieldPosition = 8;
modeInfo->BlueMaskSize = 8;
modeInfo->BlueFieldPosition = 0;
modeInfo->RsvdMaskSize = 0;
modeInfo->RsvdFieldPosition = 0;
break;
}
}
/* Convert the 32k direct color modes of VBE 1.2+ BIOSes to
* be recognised as 15 bits per pixel modes.
*/
if (bits == 16 && modeInfo->RsvdMaskSize == 1)
modeInfo->BitsPerPixel = 15;
/* Fix up bogus BIOS'es that report incorrect reserved pixel masks
* for 32K color modes. Quite a number of BIOS'es have this problem,
* and this affects our OS/2 drivers in VBE fallback mode.
*/
if (bits == 15 && (modeInfo->RsvdMaskSize != 1 || modeInfo->RsvdFieldPosition != 15)) {
modeInfo->RsvdMaskSize = 1;
modeInfo->RsvdFieldPosition = 15;
}
return true;
}
long VBEAPI VBE_getPageSize(VBE_modeInfo *mi)
/****************************************************************************
*
* Function: VBE_getPageSize
* Parameters: mi - Pointer to mode information block
* Returns: Caculated page size in bytes rounded to correct boundary
*
* Description: Computes the page size in bytes for the specified mode
* information block, rounded up to the appropriate boundary
* (8k, 16k, 32k or 64k). Pages >= 64k in size are always
* rounded to the nearest 64k boundary (so the start of a
* page is always bank aligned).
*
****************************************************************************/
{
long size;
size = (long)mi->BytesPerScanLine * (long)mi->YResolution;
if (mi->BitsPerPixel == 4) {
/* We have a 16 color video mode, so round up the page size to
* 8k, 16k, 32k or 64k boundaries depending on how large it is.
*/
size = (size + 0x1FFFL) & 0xFFFFE000L;
if (size != 0x2000) {
size = (size + 0x3FFFL) & 0xFFFFC000L;
if (size != 0x4000) {
size = (size + 0x7FFFL) & 0xFFFF8000L;
if (size != 0x8000)
size = (size + 0xFFFFL) & 0xFFFF0000L;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?