📄 svgac.c
字号:
blueMask = 0x1F; bluePos = 0; blueAdjust = 3;
break;
case 16:
redMask = 0x1F; redPos = 11; redAdjust = 3;
greenMask = 0x3F; greenPos = 5; greenAdjust = 2;
blueMask = 0x1F; bluePos = 0; blueAdjust = 3;
break;
case 24:
redMask = 0xFF; redPos = 16; redAdjust = 0;
greenMask = 0xFF; greenPos = 8; greenAdjust = 0;
blueMask = 0xFF; bluePos = 0; blueAdjust = 0;
break;
}
}
else if (*memmodel == memRGB) {
/* Convert the 32k direct color modes of VBE 1.2+ BIOSes to
* be recognised as 15 bits per pixel modes.
*/
if (*bitsperpixel == 16 && modeInfo.RsvdMaskSize == 1)
*bitsperpixel = 15;
/* Save direct color info mask positions etc */
redMask = (0xFF >> (redAdjust = 8 - modeInfo.RedMaskSize));
redPos = modeInfo.RedFieldPosition;
greenMask = (0xFF >> (greenAdjust = 8 - modeInfo.GreenMaskSize));
greenPos = modeInfo.GreenFieldPosition;
blueMask = (0xFF >> (blueAdjust = 8 - modeInfo.BlueMaskSize));
bluePos = modeInfo.BlueFieldPosition;
}
if (mode == 0x13 && !extendedflipping)
*maxpage = 0;
else
computePageInfo(&modeInfo,maxpage,pagesize);
return true;
}
typedef struct {
short writeBankLen;
void *writeBank;
short readBankLen;
void *readBank;
short newPageLen;
void *newPage;
} PMInfoBlock;
PUBLIC bool setSuperVGAMode(int mode)
/****************************************************************************
*
* Function: setSuperVGAMode
* Parameters: mode - SuperVGA video mode to set.
* Returns: True if the mode was set, false if not.
*
* Description: Attempts to set the specified video mode. This routine
* assumes that the library and SuperVGA have been initialised
* with the initSuperVGA() routine first.
*
****************************************************************************/
{
ModeInfoBlock modeInfo;
PMInfoBlock *pmInfo = (PMInfoBlock*)&modeInfo;
union REGS regs;
struct SREGS sregs;
int bitsperpixel,memmodel;
regs.x.ax = 0x0F00;
int86(0x10,®s,®s);
oldMode = regs.x.ax & 0x7F; /* Save old video mode */
old50Lines = false; /* Default to 25 line mode */
if (oldMode == 0x3) {
regs.x.ax = 0x1130;
regs.x.bx = 0;
regs.x.dx = 0;
int86(0x10,®s,®s);
old50Lines = (regs.h.dl == 49);
}
regs.x.ax = 0x4F02;
regs.x.bx = mode;
int86(0x10,®s,®s); /* Set the video mode */
if (regs.x.ax != 0x004F)
return false;
getSuperVGAModeInfo(mode,&maxx,&maxy,&bytesperline,&bitsperpixel,
&memmodel,&maxpage,&pagesize);
maxx--; maxy--;
/* Now set up the vectors to the correct routines for the video
* mode type.
*/
switch (bitsperpixel) {
case 4:
putPixel = _putPixel16;
clear = _clear16;
maxcolor = defcolor = 15;
break;
case 8:
putPixel = _putPixel256;
clear = _clear256;
maxcolor = 255;
defcolor = 15;
break;
case 15:
putPixel = _putPixel32k;
clear = _clear32k;
maxcolor = defcolor = 0x7FFF;
break;
case 16:
putPixel = _putPixel64k;
clear = _clear64k;
maxcolor = defcolor = 0xFFFF;
break;
case 24:
putPixel = _putPixel16m;
clear = _clear16m;
maxcolor = defcolor = 0xFFFFFF;
break;
}
if (mode <= 0x13) {
/* This is a normal VGA style mode, so we need to determine the
* correct information for bank switching from the BIOS
*/
if (mode == 0x13)
mode = 0x101;
else
mode = 0x102;
}
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 */
bankAdjust = 64 / modeInfo.WinGranularity;
curBank = -1;
bankSwitch = modeInfo.WinFuncPtr;
/* Now set up the vectors to the appropriate bank switching routines.
* If the Universal VESA VBE is installed, we can move the bank
* switching routines from there into our own code space for speed
* (especially under protected mode).
*/
sregs.es = SEG(&modeInfo);
regs.x.di = OFF(&modeInfo);
regs.x.ax = 0x4F01;
regs.x.cx = -1;
int86x(0x10,®s,®s,&sregs); /* Get mode information */
writeBank = readBank = pageFlip = NULL;
if (regs.x.ax == 0x004F && regs.x.cx == 0xCABD) {
/* The Universal VESA VBE is there and functioning, so copy the
* routines onto the heap and execute from there.
*/
writeBank = malloc(pmInfo->writeBankLen);
memcpy(writeBank,pmInfo->writeBank,pmInfo->writeBankLen);
if (pmInfo->readBankLen > 0) {
readBank = malloc(pmInfo->readBankLen);
memcpy(readBank,pmInfo->readBank,pmInfo->readBankLen);
}
pageFlip = malloc(pmInfo->newPageLen);
memcpy(pageFlip,pmInfo->newPage,pmInfo->newPageLen);
}
return true;
}
PUBLIC void restoreMode(void)
/****************************************************************************
*
* Function: restoreMode
*
* Description: Restore the previous video mode in use before the SuperVGA
* mode was set. This routine will also restore the 50 line
* display mode if this mode was previously set.
*
****************************************************************************/
{
union REGS regs;
regs.x.ax = oldMode;
int86(0x10,®s,®s); /* Set the old video mode */
if (old50Lines) {
regs.x.ax = 0x1112;
regs.x.bx = 0;
int86(0x10,®s,®s); /* Restore 50 line mode */
}
}
void setSuperVGADisplayStart(int x,int y)
/****************************************************************************
*
* Function: setDisplayStart
* Parameters: x,y - Position of the first pixel to display
*
* Description: Sets the new starting display position to implement
* hardware scrolling.
*
****************************************************************************/
{
union REGS regs;
if (extendedflipping) {
regs.x.ax = 0x4F07;
regs.x.bx = 0x0000;
regs.x.cx = x;
regs.x.dx = y;
int86(0x10,®s,®s);
}
}
long rgbColor(uchar r,uchar g,uchar b)
/****************************************************************************
*
* Function: rgbColor
*
* Returns: Value representing the color. The value is converted from
* 24 bit RGB space into the appropriate color for the
* video mode.
*
****************************************************************************/
{
return ((long)((r >> redAdjust) & redMask) << redPos)
| ((long)((g >> greenAdjust) & greenMask) << greenPos)
| ((long)((b >> blueAdjust) & blueMask) << bluePos);
}
PUBLIC void line(int x1,int y1,int x2,int y2,long color)
/****************************************************************************
*
* Function: line
* Parameters: x1,y1 - First endpoint of line
* x2,y2 - Second endpoint of line
* color - Color to draw the line in
*
* Description: Scan convert a line segment using the MidPoint Digital
* Differential Analyser algorithm.
*
****************************************************************************/
{
int d; /* Decision variable */
int dx,dy; /* Dx and Dy values for the line */
int Eincr,NEincr; /* Decision variable increments */
int yincr; /* Increment for y values */
int t; /* Counters etc. */
dx = ABS(x2 - x1);
dy = ABS(y2 - y1);
if (dy <= dx) {
/* We have a line with a slope between -1 and 1
*
* Ensure that we are always scan converting the line from left to
* right to ensure that we produce the same line from P1 to P0 as the
* line from P0 to P1.
*/
if (x2 < x1) {
t = x2; x2 = x1; x1 = t; /* Swap X coordinates */
t = y2; y2 = y1; y1 = t; /* Swap Y coordinates */
}
if (y2 > y1)
yincr = 1;
else
yincr = -1;
d = 2*dy - dx; /* Initial decision variable value */
Eincr = 2*dy; /* Increment to move to E pixel */
NEincr = 2*(dy - dx); /* Increment to move to NE pixel */
putPixel(x1,y1,color); /* Draw the first point at (x1,y1) */
/* Incrementally determine the positions of the remaining pixels
*/
for (x1++; x1 <= x2; x1++) {
if (d < 0) {
d += Eincr; /* Choose the Eastern Pixel */
}
else {
d += NEincr; /* Choose the North Eastern Pixel */
y1 += yincr; /* (or SE pixel for dx/dy < 0!) */
}
putPixel(x1,y1,color); /* Draw the point */
}
}
else {
/* We have a line with a slope between -1 and 1 (ie: includes
* vertical lines). We must swap our x and y coordinates for this.
*
* Ensure that we are always scan converting the line from left to
* right to ensure that we produce the same line from P1 to P0 as the
* line from P0 to P1.
*/
if (y2 < y1) {
t = x2; x2 = x1; x1 = t; /* Swap X coordinates */
t = y2; y2 = y1; y1 = t; /* Swap Y coordinates */
}
if (x2 > x1)
yincr = 1;
else
yincr = -1;
d = 2*dx - dy; /* Initial decision variable value */
Eincr = 2*dx; /* Increment to move to E pixel */
NEincr = 2*(dx - dy); /* Increment to move to NE pixel */
putPixel(x1,y1,color); /* Draw the first point at (x1,y1) */
/* Incrementally determine the positions of the remaining pixels
*/
for (y1++; y1 <= y2; y1++) {
if (d < 0) {
d += Eincr; /* Choose the Eastern Pixel */
}
else {
d += NEincr; /* Choose the North Eastern Pixel */
x1 += yincr; /* (or SE pixel for dx/dy < 0!) */
}
putPixel(x1,y1,color); /* Draw the point */
}
}
}
PUBLIC void writeText(int x,int y,uchar *str,long color)
/****************************************************************************
*
* Function: writeText
* Parameters: x,y - Position to begin drawing string at
* str - String to draw
*
* Description: Draws a string using the BIOS 8x16 video font by plotting
* each pixel in the characters individually. This should
* work for all video modes.
*
****************************************************************************/
{
uchar byte;
int i,j,k,length,ch;
uchar *font;
font = getFontVec();
length = strlen(str);
for (k = 0; k < length; k++) {
ch = str[k];
for (j = 0; j < 16; j++) {
byte = *(font + ch * 16 + j);
for (i = 0; i < 8; i++) {
if ((byte & 0x80) != 0)
putPixel(x+i,y+j,color);
byte <<= 1;
}
}
x += 8;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -