vesavbe.c
来自「适合KS8695X」· C语言 代码 · 共 1,215 行 · 第 1/3 页
C
1,215 行
* pixelClock - Desired pixel clock
* Returns: Closest pixel clock to desired clock (-1 if not supported)
*
* Description: Calls the VBE/Core 3.0 interface to determine the closest
* pixel clock to the requested value. The BIOS will always
* search for a pixel clock that is no more than 1% below the
* requested clock or somewhere higher than the clock. If the
* clock is higher note that it may well be many Mhz higher
* that requested and the application will have to check that
* the returned value is suitable for it's needs. This function
* returns the actual pixel clock that will be programmed by
* the hardware.
*
* Note that if the pixel clock will be used with a linear
* framebuffer mode, make sure you pass in the linear
* framebuffer flag to this function.
*
* NOTE: Requires VBE/Core 3.0
*
****************************************************************************/
{
RMREGS regs;
if (state->VBEVersion >= 0x300) {
regs.x.ax = 0x4F0B;
regs.h.bl = 0x00;
regs.e.ecx = pixelClock;
regs.x.dx = mode;
PM_int86(0x10,®s,®s);
if (regs.x.ax == VBE_SUCCESS)
return regs.e.ecx;
}
return -1;
}
ibool VBEAPI VBE_setDACWidth(int width)
/****************************************************************************
*
* Function: VBE_setDACWidth
* Parameters: width - Width to set the DAC to
* Returns: True on success, false on failure
*
****************************************************************************/
{
RMREGS regs;
regs.x.ax = 0x4F08;
regs.h.bl = 0x00;
regs.h.bh = width;
PM_int86(0x10,®s,®s);
return regs.x.ax == VBE_SUCCESS;
}
int VBEAPI VBE_getDACWidth(void)
/****************************************************************************
*
* Function: VBE_getDACWidth
* Returns: Current width of the palette DAC
*
****************************************************************************/
{
RMREGS regs;
regs.x.ax = 0x4F08;
regs.h.bl = 0x01;
PM_int86(0x10,®s,®s);
if (regs.x.ax != VBE_SUCCESS)
return -1;
return regs.h.bh;
}
ibool VBEAPI VBE_setPalette(int start,int num,VBE_palette *pal,ibool waitVRT)
/****************************************************************************
*
* Function: VBE_setPalette
* Parameters: start - Starting palette index to program
* num - Number of palette indexes to program
* pal - Palette buffer containing values
* waitVRT - Wait for vertical retrace flag
* Returns: True on success, false on failure
*
* Description: Sets a block of palette registers by calling the VBE 2.0
* BIOS. This function will fail on VBE 1.2 implementations.
*
****************************************************************************/
{
RMREGS regs;
regs.x.ax = 0x4F09;
regs.h.bl = waitVRT ? 0x80 : 0x00;
regs.x.cx = num;
regs.x.dx = start;
VBE_callESDI(®s, pal, sizeof(VBE_palette) * num);
return regs.x.ax == VBE_SUCCESS;
}
void * VBEAPI VBE_getBankedPointer(VBE_modeInfo *modeInfo)
/****************************************************************************
*
* Function: VBE_getBankedPointer
* Parameters: modeInfo - Mode info block for video mode
* Returns: Selector to the linear framebuffer (0 on failure)
*
* Description: Returns a near pointer to the VGA framebuffer area.
*
****************************************************************************/
{
/* We just map the pointer every time, since the pointer will always
* be in real mode memory, so we wont actually be mapping any real
* memory.
*
* NOTE: We cannot currently map a near pointer to the banked frame
* buffer for Watcom Win386, so we create a 16:16 far pointer to
* the video memory. All the assembler code will render to the
* video memory by loading the selector rather than using a
* near pointer.
*/
ulong seg = (ushort)modeInfo->WinASegment;
if (seg != 0) {
if (seg == 0xA000)
return (void*)PM_getA0000Pointer();
else
return (void*)PM_mapPhysicalAddr(seg << 4,0xFFFF,true);
}
return NULL;
}
#ifndef REALMODE
void * VBEAPI VBE_getLinearPointer(VBE_modeInfo *modeInfo)
/****************************************************************************
*
* Function: VBE_getLinearPointer
* Parameters: modeInfo - Mode info block for video mode
* Returns: Selector to the linear framebuffer (0 on failure)
*
* Description: Returns a near pointer to the linear framebuffer for the video
* mode.
*
****************************************************************************/
{
static ulong physPtr[MAX_LIN_PTRS] = {0};
static void *linPtr[MAX_LIN_PTRS] = {0};
static int numPtrs = 0;
int i;
/* Search for an already mapped pointer */
for (i = 0; i < numPtrs; i++) {
if (physPtr[i] == modeInfo->PhysBasePtr)
return linPtr[i];
}
if (numPtrs < MAX_LIN_PTRS) {
physPtr[numPtrs] = modeInfo->PhysBasePtr;
linPtr[numPtrs] = PM_mapPhysicalAddr(modeInfo->PhysBasePtr,(state->VBEMemory * 1024L)-1,true);
return linPtr[numPtrs++];
}
return NULL;
}
static void InitPMCode(void)
/****************************************************************************
*
* Function: InitPMCode - 32 bit protected mode version
*
* Description: Finds the address of and relocates the protected mode
* code block from the VBE 2.0 into a local memory block. The
* memory block is allocated with malloc() and must be freed
* with VBE_freePMCode() after graphics processing is complete.
*
* Note that this buffer _must_ be recopied after each mode set,
* as the routines will change depending on the underlying
* video mode.
*
****************************************************************************/
{
RMREGS regs;
RMSREGS sregs;
uchar *code;
int pmLen;
if (!state->pmInfo && state->VBEVersion >= 0x200) {
regs.x.ax = 0x4F0A;
regs.x.bx = 0;
PM_int86x(0x10,®s,®s,&sregs);
if (regs.x.ax != VBE_SUCCESS)
return;
if (VBE_shared)
state->pmInfo = PM_mallocShared(regs.x.cx);
else
state->pmInfo = PM_malloc(regs.x.cx);
if (state->pmInfo == NULL)
return;
state->pmInfo32 = state->pmInfo;
pmLen = regs.x.cx;
/* Relocate the block into our local data segment */
code = PM_mapRealPointer(sregs.es,regs.x.di);
memcpy(state->pmInfo,code,pmLen);
/* Now do a sanity check on the information we recieve to ensure
* that is is correct. Some BIOS return totally bogus information
* in here (Matrox is one)! Under DOS this works OK, but under OS/2
* we are screwed.
*/
if (state->pmInfo->setWindow >= pmLen ||
state->pmInfo->setDisplayStart >= pmLen ||
state->pmInfo->setPalette >= pmLen ||
state->pmInfo->IOPrivInfo >= pmLen) {
if (VBE_shared)
PM_freeShared(state->pmInfo);
else
PM_free(state->pmInfo);
state->pmInfo32 = state->pmInfo = NULL;
return;
}
/* Read the IO priveledge info and determine if we need to
* pass a selector to MMIO registers to the bank switch code.
* Since we no longer support selector allocation, we no longer
* support this mechanism so we disable the protected mode
* interface in this case.
*/
if (state->pmInfo->IOPrivInfo && !state->MMIOSel) {
ushort *p = (ushort*)((uchar*)state->pmInfo + state->pmInfo->IOPrivInfo);
while (*p != 0xFFFF)
p++;
p++;
if (*p != 0xFFFF)
VBE_freePMCode();
}
}
}
void * VBEAPI VBE_getSetBank(void)
/****************************************************************************
*
* Function: VBE_getSetBank
* Returns: Pointer to the 32 VBE 2.0 bit bank switching routine.
*
****************************************************************************/
{
if (state->VBEVersion >= 0x200) {
InitPMCode();
if (state->pmInfo)
return (uchar*)state->pmInfo + state->pmInfo->setWindow;
}
return NULL;
}
void * VBEAPI VBE_getSetDisplayStart(void)
/****************************************************************************
*
* Function: VBE_getSetDisplayStart
* Returns: Pointer to the 32 VBE 2.0 bit CRT start address routine.
*
****************************************************************************/
{
if (state->VBEVersion >= 0x200) {
InitPMCode();
if (state->pmInfo)
return (uchar*)state->pmInfo + state->pmInfo->setDisplayStart;
}
return NULL;
}
void * VBEAPI VBE_getSetPalette(void)
/****************************************************************************
*
* Function: VBE_getSetPalette
* Returns: Pointer to the 32 VBE 2.0 bit palette programming routine.
*
****************************************************************************/
{
if (state->VBEVersion >= 0x200) {
InitPMCode();
if (state->pmInfo)
return (uchar*)state->pmInfo + state->pmInfo->setPalette;
}
return NULL;
}
void VBEAPI VBE_freePMCode(void)
/****************************************************************************
*
* Function: VBE_freePMCode
*
* Description: This routine frees the protected mode code blocks that
* we copied from the VBE 2.0 interface. This routine must
* be after you have finished graphics processing to free up
* the memory occupied by the routines. This is necessary
* because the PM info memory block must be re-copied after
* every video mode set from the VBE 2.0 implementation.
*
****************************************************************************/
{
if (state->pmInfo) {
if (VBE_shared)
PM_freeShared(state->pmInfo);
else
PM_free(state->pmInfo);
state->pmInfo = NULL;
state->pmInfo32 = NULL;
}
}
void VBEAPI VBE_sharePMCode(void)
/****************************************************************************
*
* Function: VBE_sharePMCode
*
* Description: Enables internal sharing of the PM code buffer for OS/2.
*
****************************************************************************/
{
VBE_shared = true;
}
/* Set of code stubs used to build the final bank switch code */
#define VBE20_adjustOffset 7
static uchar VBE20A_bankFunc32_Start[] = {
0x53,0x51, /* push ebx,ecx */
0x8B,0xD0, /* mov edx,eax */
0x33,0xDB, /* xor ebx,ebx */
0xB1,0x00, /* mov cl,0 */
0xD2,0xE2, /* shl dl,cl */
};
static uchar VBE20_bankFunc32_End[] = {
0x59,0x5B, /* pop ecx,ebx */
};
static uchar bankFunc32[100];
#define copy(p,b,a) memcpy(b,a,sizeof(a)); (p) = (b) + sizeof(a)
ibool VBEAPI VBE_getBankFunc32(int *codeLen,void **bankFunc,int dualBanks,
int bankAdjust)
/****************************************************************************
*
* Function: VBE_getBankFunc32
* Parameters: codeLen - Place to store length of code
* bankFunc - Place to store pointer to bank switch code
* dualBanks - True if dual banks are in effect
* bankAdjust - Bank shift adjustment factor
* Returns: True on success, false if not compatible.
*
* Description: Creates a local 32 bit bank switch function from the
* VBE 2.0 bank switch code that is compatible with the
* virtual flat framebuffer devices (does not have a return
* instruction at the end and takes the bank number in EAX
* not EDX). Note that this 32 bit code cannot include int 10h
* instructions, so we can only do this if we have VBE 2.0
* or later.
*
* Note that we need to know the length of the 32 bit
* bank switch function, which the standard VBE 2.0 spec
* does not provide. In order to support this we have
* extended the VBE 2.0 state->pmInfo structure in UniVBE 5.2 in a
* way to support this, and we hope that this will become
* a VBE 2.0 ammendment.
*
* Note also that we cannot run the linear framebuffer
* emulation code with bank switching routines that require
* a selector to the memory mapped registers passed in ES.
*
****************************************************************************/
{
int len;
uchar *code;
uchar *p;
InitPMCode();
if (state->VBEVersion >= 0x200 && state->pmInfo32 && !state->MMIOSel) {
code = (uchar*)state->pmInfo32 + state->pmInfo32->setWindow;
if (state->pmInfo32->extensionSig == VBE20_EXT_SIG)
len = state->pmInfo32->setWindowLen-1;
else {
/* We are running on a system without the UniVBE 5.2 extension.
* We do as best we can by scanning through the code for the
* ret function to determine the length. This is not foolproof,
* but is the best we can do.
*/
p = code;
while (*p != 0xC3)
p++;
len = p - code;
}
if ((len + sizeof(VBE20A_bankFunc32_Start) + sizeof(VBE20_bankFunc32_End)) > sizeof(bankFunc32))
PM_fatalError("32-bit bank switch function too long!");
copy(p,bankFunc32,VBE20A_bankFunc32_Start);
memcpy(p,code,len);
p += len;
copy(p,p,VBE20_bankFunc32_End);
*codeLen = p - bankFunc32;
bankFunc32[VBE20_adjustOffset] = (uchar)bankAdjust;
*bankFunc = bankFunc32;
return true;
}
return false;
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?