📄 svgac.c
字号:
/****************************************************************************
*
* SuperVGA Test Library
*
* Copyright (C) 1993 SciTech Software
* All rights reserved.
*
* Filename: $RCSfile: svgac.c $
* Version: $Revision: 1.3 $
*
* Language: ANSI C
* Environment: IBM PC (MSDOS)
*
* Description: Simple library to collect together the functions in the
* SuperVGA test library for use in other C programs. The
* support is reasonably low level, so you can do what you
* want. The set of routines in this source file are general
* SuperVGA routines and are independant of the video mode
* selected.
*
* MUST be compiled in the large model.
*
* $Id: svgac.c 1.3 1993/10/22 08:58:40 kjb release $
*
****************************************************************************/
#include <string.h>
#include <dos.h>
#include <stdlib.h>
#include "svga.h"
#include "vesavbe.h"
/*---------------------------- Global Variables ---------------------------*/
#define MAXMODES 50 /* Maximum modes available in list */
int maxx,maxy,memory;
long maxcolor,defcolor;
int maxpage,bytesperline;
uchar redMask,greenMask,blueMask;
int redPos,redAdjust;
int greenPos,greenAdjust;
int bluePos,blueAdjust;
bool twobanks = false,extendedflipping = false,widedac = false;
short modeList[MAXMODES];
char OEMString[80];
int oldMode; /* Old video mode number */
bool old50Lines; /* Was old mode 80x50? */
int curBank; /* Current read/write bank */
int bankAdjust; /* Bank granularity adjust factor */
long pagesize; /* Page size for current mode */
void *bankSwitch; /* Pointer to bank switch routine */
void *writeBank; /* Relocated write bank routine */
void *readBank; /* Relocated read bank routine */
void *pageFlip; /* Relocated page flip routine */
void (*putPixel)(int x,int y,long color);
void (*clear)(void);
/*----------------------------- Implementation ----------------------------*/
/* Declare all video mode dependent routines */
void _putPixel16(int x,int y,long color);
void _putPixel256(int x,int y,long color);
void _putPixel32k(int x,int y,long color);
void _putPixel64k(int x,int y,long color);
void _putPixel16m(int x,int y,long color);
void _clear16(void);
void _clear256(void);
void _clear32k(void);
void _clear64k(void);
void _clear16m(void);
PRIVATE bool checkVESAPageFlip(void)
/****************************************************************************
*
* Function: checkVESAPageFlip
* Returns: True if VBE supports page flipping.
*
* Description: Determines if the VESA VBE supports extended page
* flipping or not. Assume a suitable video mode has already
* been initialised.
*
****************************************************************************/
{
union REGS regs;
regs.x.ax = 0x4F07; /* Set display start service */
regs.x.bx = 0; /* BH := 0, BL := 0 (set display start) */
regs.x.cx = 0; /* Leftmost pixel in line */
regs.x.dx = 0; /* First displayed scanline */
int86(0x10,®s,®s);
if (regs.x.ax != 0x004F)
return false; /* Function failed, not page flip */
regs.x.ax = 0x4F07; /* Get display start service */
regs.x.bx = 1; /* BH := 0, BL := 1 (get display start) */
int86(0x10,®s,®s);
if (regs.x.ax != 0x004F)
return false; /* Function failed, not page flip */
if (regs.h.bh != 0)
return false;
if (regs.x.cx != 0)
return false;
if (regs.x.dx != 0)
return false;
return true;
}
bool checkWideDAC(void)
/****************************************************************************
*
* Function: checkWideDAC
* Returns: True if 8 bit wide DAC is supported.
*
* Description: Tests to see if the VBE BIOS supports an 8 bit wide
* DAC. This assumes the video card is in an appropriate
* video mode before being called.
*
****************************************************************************/
{
union REGS regs;
short bits;
regs.x.ax = 0x4F08; /* Set DAC service */
regs.x.bx = 0x0800; /* BH := 8, BL := 0 (set DAC width) */
int86(0x10,®s,®s);
if (regs.x.ax != 0x004F)
return false; /* Function failed, no wide dac */
if (regs.h.bh == 6)
return false;
regs.x.ax = 0x4F08;
regs.x.bx = 0x0001; /* Get DAC width (should now be 8) */
int86(0x10,®s,®s);
if (regs.x.ax != 0x004F)
return false;
bits = regs.h.bh;
regs.x.ax = 0x4F08;
regs.x.bx = 0x0600;
int86(0x10,®s,®s); /* Restore to 6 bit DAC */
if (regs.x.ax != 0x004F)
return false;
return (bits == 8);
}
PUBLIC int initSuperVGA(void)
/****************************************************************************
*
* Function: initSuperVGA
* Returns: VBE version number for the SuperVGA (0 if no SuperVGA).
*
* Description: Detects if a VESA VBE compliant SuperVGA is out there, and
* initialises the library if one is. The VBE version number
* is specified with the major version number in the high
* byte and the minor version number in the low byte. So
* version 1.2 is the number 0x102.
*
****************************************************************************/
{
VgaInfoBlock vgaInfo;
ModeInfoBlock modeInfo;
union REGS regs;
struct SREGS sregs;
short *p,i;
sregs.es = SEG(&vgaInfo);
regs.x.di = OFF(&vgaInfo);
regs.x.ax = 0x4F00;
int86x(0x10,®s,®s,&sregs); /* Get SuperVGA information */
if (regs.x.ax != 0x004F)
return false;
if (strncmp(vgaInfo.VESASignature,"VESA",4) != 0)
return false;
/* Copy relavent information from the mode block into our globals.
* Note that the video mode list _may_ be built in the information
* block that we have passed, so we _must_ copy this from here
* into our our storage if we want to continue to use it. Note
* that we filter out the mode 0x6A, which some BIOSes include as
* well as the 0x102 mode for 800x600x16.
*/
for (i = 0,p = vgaInfo.VideoModePtr; *p != -1; p++,i++) {
if (*p != 0x6A)
modeList[i] = *p;
}
modeList[i] = -1;
memory = vgaInfo.TotalMemory * 64;
strcpy(OEMString,vgaInfo.OEMStringPtr);
/* Determine if the board supports separate read/write banks and
* extended page flipping. Some VESA VBE's require the card to be
* in a graphics mode for these tests to work, so we find a suitable
* mode and use that.
*/
for (p = modeList; *p != -1; p++) {
sregs.es = SEG(&modeInfo);
regs.x.di = OFF(&modeInfo);
regs.x.ax = 0x4F01;
regs.x.cx = *p;
int86x(0x10,®s,®s,&sregs); /* Get SuperVGA mode info */
if (regs.x.ax == 0x004F &&
(modeInfo.MemoryModel == 3 || modeInfo.MemoryModel == 4)) {
modeInfo.WinBAttributes &= 0x7;
twobanks = (modeInfo.WinBAttributes == 0x3);
setSuperVGAMode(*p);
extendedflipping = checkVESAPageFlip();
widedac = checkWideDAC();
restoreMode();
break;
}
}
return vgaInfo.VESAVersion;
}
PRIVATE void computePageInfo(ModeInfoBlock *modeInfo,int *maxpage,
long *pagesize)
/****************************************************************************
*
* Function: computePageInfo
* Parameters: modeInfo - Pointer to valid mode information block
* maxpage - Number of display pages - 1
* pagesize - Size of each logical display page in bytes
*
* Description: Computes the number of image pages and size of each image
* page for a specified video mode.
*
****************************************************************************/
{
long memsize,size;
if (extendedflipping)
memsize = memory * 1024L;
else
memsize = 256 * 1024L; /* Use only 256k to compute pages */
size = (long)modeInfo->BytesPerScanLine * (long)modeInfo->YResolution;
if (modeInfo->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;
}
}
}
else
size = (size + 0xFFFFL) & 0xFFFF0000L;
if (modeInfo->MemoryModel == memPL)
memsize /= 4;
if (size <= memsize)
*maxpage = (memsize / size) - 1;
else
*maxpage = 0;
*pagesize = size;
}
PUBLIC bool getSuperVGAModeInfo(int mode,int *xres,int *yres,
int *bytesperline,int *bitsperpixel,int *memmodel,int *maxpage,
long *pagesize)
/****************************************************************************
*
* Function: getSuperVGAModeInfo
* Parameters: mode - Mode to get information about
* xres - Place to store x resolution
* yres - Place to store y resolution
* bytesperline - Bytes per scanline
* bitsperpixel - Place to store bits per pixel (2^n colors)
* memmodel - Memory model for mode (planar, packed etc)
* maxpage - Number of display pages - 1
* pagesize - Size of each logical display page in bytes
* Returns: True if mode number was valid, false if not.
*
* 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.
*
****************************************************************************/
{
ModeInfoBlock modeInfo;
union REGS regs;
struct SREGS sregs;
if (mode <= 0x13) {
/* This is a standard VGA mode, so fill in the required information
* ourselves.
*/
switch (mode) {
case 0x0D:
modeInfo.XResolution = 320;
modeInfo.YResolution = 200;
modeInfo.BytesPerScanLine = 40;
modeInfo.BitsPerPixel = 4;
modeInfo.MemoryModel = memPL;
break;
case 0x0E:
modeInfo.XResolution = 640;
modeInfo.YResolution = 200;
modeInfo.BytesPerScanLine = 80;
modeInfo.BitsPerPixel = 4;
modeInfo.MemoryModel = memPL;
break;
case 0x10:
modeInfo.XResolution = 640;
modeInfo.YResolution = 350;
modeInfo.BytesPerScanLine = 80;
modeInfo.BitsPerPixel = 4;
modeInfo.MemoryModel = memPL;
break;
case 0x12:
modeInfo.XResolution = 640;
modeInfo.YResolution = 480;
modeInfo.BytesPerScanLine = 80;
modeInfo.BitsPerPixel = 4;
modeInfo.MemoryModel = memPL;
break;
case 0x13:
modeInfo.XResolution = 320;
modeInfo.YResolution = 200;
modeInfo.BytesPerScanLine = 320;
modeInfo.BitsPerPixel = 8;
modeInfo.MemoryModel = memPK;
break;
default:
return false;
}
}
else {
/* This is a VESA mode, so call the BIOS to get information about
* it.
*/
sregs.es = SEG(&modeInfo);
regs.x.di = OFF(&modeInfo);
regs.x.ax = 0x4F01;
regs.x.cx = mode;
int86x(0x10,®s,®s,&sregs); /* Get mode information */
if (regs.x.ax != 0x004F)
return false;
if ((modeInfo.ModeAttributes & 0x1) == 0)
return false;
}
*xres = modeInfo.XResolution;
*yres = modeInfo.YResolution;
*bytesperline = modeInfo.BytesPerScanLine;
*memmodel = modeInfo.MemoryModel;
*bitsperpixel = modeInfo.BitsPerPixel;
if (*memmodel == memPK && *bitsperpixel > 8) {
/* Support old style definitions, which some BIOS'es still use :-( */
*memmodel = memRGB;
switch (*bitsperpixel) {
case 15:
redMask = 0x1F; redPos = 10; redAdjust = 3;
greenMask = 0x1F; greenPos = 5; greenAdjust = 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -