📄 vesavbe.c
字号:
/****************************************************************************** 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 10static 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 REALMODEstatic 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 REALMODEstatic 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;}#endifint 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -