/**************************************************************************** * * The SuperVGA Kit - UniVBE Software Development Kit * * Copyright (C) 1996 SciTech Software * All rights reserved. * * Filename: $Workfile: svgasdk.c $ * Version: $Revision: 1.33 $ * * Language: ANSI C * Environment: IBM PC (MSDOS) Real Mode and 16/32 bit Protected Mode. * * 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 or FLAT models. * * $Date: 04 Nov 1996 12:18:58 $ $Author: AlanR $ * ****************************************************************************/ #include #include #include #include #include "pmpro.h" #include "svga.h" #include "wdirect.h" /* If we are compiling for either 32 bit protected mode or 16 bit Windows, * then we can use the VBE 2.0 protected mode functions and linear * framebuffer code, and also VBE/AF Accelerator Functions. */ #if defined(PM386) || defined(__WINDOWS16__) || defined(TESTING_PM) #define USE_VBE20 #endif #if !defined(__16BIT__) || defined(TESTING_PM) #define USE_VBEAF #endif /*---------------------------- Global Variables ---------------------------*/ #define MAXMODES 100 /* Maximum modes available in list */ #define DC _SV_devCtx /* Macro to access global structure */ PUBLIC SV_devCtx _ASMAPI _SV_devCtx = {0}; #ifdef USE_VBEAF PRIVATE AF_devCtx *loadedDC = NULL; /* DC of loaded VBE/AF driver */ #endif PRIVATE uint VESABuf_len = 1024; /* Length of VESABuf */ PRIVATE uint VESABuf_sel = 0; /* Selector for VESABuf */ PRIVATE uint VESABuf_off; /* Offset for VESABuf */ PRIVATE uint VESABuf_rseg; /* Real mode segment of VESABuf */ PRIVATE uint VESABuf_roff; /* Real mode offset of VESABuf */ PRIVATE ushort _SV_modeList[MAXMODES]; PRIVATE char _SV_OEMString[80]; PRIVATE bool _SV_old50Lines; /* Was old mode 80x50? */ PRIVATE bool _SV_convertPal; /* True to convert palette entries */ PUBLIC int _ASMAPI _SV_bankShift;/* Bank granularity adjust factor */ PUBLIC long _ASMAPI _SV_pagesize; /* Page size for current mode */ PUBLIC void * _ASMAPI _SV_setBankRM;/* Pointer to direct VBE bank code*/ PUBLIC void * _ASMAPI _SV_setBankPtr;/* Pointer to bank switch code */ #ifdef __WINDOWS__ PRIVATE HWND hwndMain = NULL; /* Main window for application */ #endif void _ASMAPI _VBE_setBankA(void); /* VBE setBank routine single bank */ void _ASMAPI _VBE_setBankAB(void); /* VBE setBank routine dual banks */ #ifdef USE_VBE20 void _ASMAPI _VBE20_setBankA(void); /* VBE 2.0 setBank single bank */ void _ASMAPI _VBE20_setBankAB(void); /* VBE 2.0 setBank dual banks */ void _ASMAPI _VBE20_setBankA_ES(void); /* VBE 2.0 setBank for MMIO */ void _ASMAPI _VBE20_setBankAB_ES(void); /* VBE 2.0 setBank for MMIO */ PUBLIC void * _ASMAPI _SV_setBank20 = NULL;/* Pointer to set bank routine*/ PUBLIC void * _ASMAPI _SV_setCRT20 = NULL;/* Pointer to set CRT routine*/ PUBLIC void * _ASMAPI _SV_setPal20 = NULL;/* Pointer to set palette rtn*/ extern short _ASMAPI VBE_MMIOSel; /* Selector to MMIO registers */ #endif #ifdef USE_VBEAF void SVAPI _VBEAF_setBank(void); /* VBE/AF setBank function */ #endif extern uchar _ASMAPI font8x16[]; /* Bitmap font definition */ extern SV_palette _ASMAPI VGA8_defPal[]; /*----------------------------- Implementation ----------------------------*/ /* Declare all banked framebuffer routines */ void _ASMAPI _SV_setActivePage(int page); void _ASMAPI _SV_setVisualPage(int page,bool waitVRT); void _ASMAPI _VGA_setPalette(int start,int num,SV_palette *pal,bool waitVRT); void _ASMAPI _VBE20_setPalette(int start,int num,SV_palette *pal,bool waitVRT); void _ASMAPI _SV_clear16(ulong color); void _ASMAPI _SV_clear256(ulong color); void _ASMAPI _SV_clear32k(ulong color); void _ASMAPI _SV_clear16m(ulong color); void _ASMAPI _SV_clear4G(ulong color); void _ASMAPI _SV_putPixel16(int x,int y,ulong color); void _ASMAPI _SV_putPixel256(int x,int y,ulong color); void _ASMAPI _SV_putPixel32k(int x,int y,ulong color); void _ASMAPI _SV_putPixel16m(int x,int y,ulong color); void _ASMAPI _SV_putPixel4G(int x,int y,ulong color); void _ASMAPI _SV_line16(int x1,int y1,int x2,int y2,ulong color); void _ASMAPI _SV_line256(int x1,int y1,int x2,int y2,ulong color); void _ASMAPI _SV_line32k(int x1,int y1,int x2,int y2,ulong color); void _ASMAPI _SV_line16m(int x1,int y1,int x2,int y2,ulong color); void _ASMAPI _SV_line4G(int x1,int y1,int x2,int y2,ulong color); /* Declare all the linear framebuffer routines */ #ifdef USE_VBE20 #ifdef __WINDOWS16__ void _ASMAPI linsdk_enable32(void); #endif void _ASMAPI _SV_setActivePageLin(int page); void _ASMAPI _SV_clear256Lin(ulong color); void _ASMAPI _SV_clear32kLin(ulong color); void _ASMAPI _SV_clear16mLin(ulong color); void _ASMAPI _SV_clear4GLin(ulong color); void _ASMAPI _SV_putPixel256Lin(int x,int y,ulong color); void _ASMAPI _SV_putPixel32kLin(int x,int y,ulong color); void _ASMAPI _SV_putPixel16mLin(int x,int y,ulong color); void _ASMAPI _SV_putPixel4GLin(int x,int y,ulong color); void _ASMAPI _SV_line256Lin(int x1,int y1,int x2,int y2,ulong color); void _ASMAPI _SV_line32kLin(int x1,int y1,int x2,int y2,ulong color); void _ASMAPI _SV_line16mLin(int x1,int y1,int x2,int y2,ulong color); void _ASMAPI _SV_line4GLin(int x1,int y1,int x2,int y2,ulong color); #endif /* Declare all VBE/AF specific functions */ #ifdef USE_VBEAF void _ASMAPI _SV_setActivePageAF(int page); void _ASMAPI _SV_setActivePageLinAF(int page); void _ASMAPI _SV_setVisualPageAF(int page,bool waitVRT); void _ASMAPI _SV_beginDirectAccessAFSLOW(void); void _ASMAPI _SV_endDirectAccessAFSLOW(void); void _ASMAPI _SV_beginPixelAFSLOW(void); void _ASMAPI _SV_endPixelAFSLOW(void); void _ASMAPI _SV_beginLineAFSLOW(void); void _ASMAPI _SV_endLineAFSLOW(void); void _ASMAPI _SV_beginDirectAccessAF(void); void _ASMAPI _SV_endDirectAccessAF(void); void _ASMAPI _SV_beginPixelAF(void); void _ASMAPI _SV_endPixelAF(void); void _ASMAPI _SV_beginLineAF(void); void _ASMAPI _SV_endLineAF(void); void _ASMAPI _SV_clearAF(ulong color); void _ASMAPI _SV_putPixelAF(int x,int y,ulong color); void _ASMAPI _SV_lineFastAF(int x1,int y1,int x2,int y2,ulong color); void _ASMAPI _SV_softLineAF(int x1,int y1,int x2,int y2,ulong color); #endif /*----------------------------- Implementation ----------------------------*/ #pragma warn -par PRIVATE void ExitVBEBuf(void) { if (VESABuf_sel) PM_freeRealSeg(VESABuf_sel,VESABuf_off); VESABuf_sel = 0; } void SVAPI SV_initRMBuf(void) /**************************************************************************** * * Function: SV_initRMBuf * * 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 (!VESABuf_sel) { /* Allocate a global buffer for communicating with the VESA VBE */ if (!PM_allocRealSeg(VESABuf_len, &VESABuf_sel, &VESABuf_off, &VESABuf_rseg, &VESABuf_roff)) exit(1); VBE_init(VESABuf_len,VESABuf_sel,VESABuf_off,VESABuf_rseg,VESABuf_roff); atexit(ExitVBEBuf); } } void SV_nop(void) {} PRIVATE SV_devCtx *InitVBE(void) /**************************************************************************** * * Function: InitVBE * Returns: Pointer to device context block or 0 if no SuperVGA. * * Description: Performs initialisation for VBE based devices. * ****************************************************************************/ { VBE_vgaInfo vgaInfo; VBE_modeInfo modeInfo; int i; ushort *p,tmodeList[MAXMODES]; SV_initRMBuf(); if ((DC.VBEVersion = VBE_detect(&vgaInfo)) == 0) return NULL; /* Copy relevent 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 != 0xFFFF && i < MAXMODES); p++) { if (*p >= 0x100) tmodeList[i++] = *p; } tmodeList[i] = -1; /* Now build our global list of available video modes, filtering out * those modes that are not available or not graphics modes. A VBE * implementation may put modes in the mode list that are not available * on the current hardware configuration, so we need to check for this. */ DC.haveMultiBuffer = false; DC.haveVirtualScroll = false; DC.linearAddr = 0; for (i = 0,p = tmodeList; (*p != 0xFFFF && i < MAXMODES); p++) { if (!VBE_getModeInfo(*p,&modeInfo)) continue; if ((modeInfo.ModeAttributes & vbeMdGraphMode) == 0) continue; if (!DC.linearAddr && (modeInfo.ModeAttributes & vbeMdLinear)) DC.linearAddr = modeInfo.PhysBasePtr; if (modeInfo.NumberOfImagePages > 0) { /* If we have any graphics mode reports that it has more than * 1 display page available, then we assume double buffering * and virtual scrolling are available. Note that under VBE * 1.2 and 2.0 these are one and the same, but under VBE/AF * you can have cards that do double buffering but not virtual * scrolling (and vice versa). */ DC.haveMultiBuffer = true; DC.haveVirtualScroll = true; } DC.modeList[i++] = *p; } DC.modeList[i] = -1; DC.memory = vgaInfo.TotalMemory * 64; DC.haveWideDAC = ((int)vgaInfo.Capabilities & vbe8BitDAC) != 0; strcpy(DC.OEMString,vgaInfo.OemStringPtr); #ifndef REALMODE if (DC.VBEVersion >= 0x200 && VF_available()) { int codeLen; void *bankFunc; DC.haveVirtualBuffer = VBE_getBankFunc32(&codeLen,&bankFunc,0,0); } else DC.haveVirtualBuffer = false; #endif #ifdef __WINDOWS16__ linsdk_enable32(); /* Enable 32 bit linear framebuffer module */ #endif return &DC; } PUBLIC SV_devCtx * SVAPI SV_init(bool useVBEAF) /**************************************************************************** * * Function: SV_init * Parameters: useVBEAF - True to use the VBE/AF driver if found * Returns: Pointer to device context block, or NULL if SVGA not found. * * 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. * * If we detect VBE/AF Accelerator Functions support, we * initialise the library to use VBE/AF rather than VBE 1.2/2.0 * and return a DC.VBEVersion number of 2.0. It is up to the * application program to then check the DC.AFDC pointer to * determine if VBE/AF is available or not. * ****************************************************************************/ { /* Initialise global pointers in global device context block */ DC.modeList = _SV_modeList; DC.OEMString = _SV_OEMString; #ifdef USE_VBEAF DC.AFDC = NULL; #endif if (useVBEAF) { #ifdef USE_VBEAF int i; short *p; AF_modeInfo modeInfo; if (loadedDC) DC.AFDC = loadedDC; else DC.AFDC = loadedDC = AF_loadDriver(NULL); if (DC.AFDC) { /* Copy list of available modes */ for (i = 0,p = DC.AFDC->AvailableModes; (*p != -1 && i < MAXMODES); p++) { if (AF_getVideoModeInfo(DC.AFDC,*p,&modeInfo) != 0) continue; DC.modeList[i++] = *p; } DC.modeList[i] = -1; /* Obtain configuration information from driver */ DC.haveMultiBuffer = (DC.AFDC->Attributes & afHaveMultiBuffer); DC.haveVirtualScroll = (DC.AFDC->Attributes & afHaveVirtualScroll); DC.haveWideDAC = (DC.AFDC->Attributes & afHave8BitDAC); DC.haveAccel2D = (DC.AFDC->Attributes & afHaveAccel2D); DC.haveHWCursor = (DC.AFDC->Attributes & afHaveHWCursor); DC.linearAddr = DC.AFDC->LinearBasePtr; DC.memory = DC.AFDC->TotalMemory; strcpy(DC.OEMString,DC.AFDC->OemVendorName); DC.haveVirtualBuffer = (DC.AFDC->SetBank32 != NULL); #ifdef __WINDOWS16__ linsdk_enable32(); #endif DC.VBEVersion = 0x200; return &DC; } #endif } return InitVBE(); } PUBLIC void SVAPI SV_exit(void) /**************************************************************************** * * Function: SV_exit * * Description: Clean up correctly for the SuperVGA Kit. Needed for * DLL versions when running under Windows 3.1 to properly * clean up after the DLL (exit functions dont seem to work). * ****************************************************************************/ { ExitVBEBuf(); } PUBLIC bool SVAPI SV_getModeInfo(ushort mode,SV_modeInfo *modeInfo) /**************************************************************************** * * Function: SV_getModeInfo * Parameters: mode - Mode number for the mode * modeInfo - Place to store the mode information * Returns: True if for valid mode, false if invalid. * * Description: Obtains mode information for the specified mode number. * Note that we either call the VBE BIOS or the VBE/AF driver * for this information, massaging the information returned * into our common buffer format. * ****************************************************************************/ { /* Mask off any extra flags from the mode number before we pass it * onto the BIOS. We also ignore any non-VBE modes. */ if ((mode &= 0x1FF) < 0x100) return false; if (DC.AFDC) { #ifdef USE_VBEAF AF_modeInfo miAF; if (AF_getVideoModeInfo(DC.AFDC,mode,&miAF) != 0) return false; modeInfo->Attributes = miAF.Attributes; modeInfo->XResolution = miAF.XResolution; modeInfo->YResolution = miAF.YResolution; modeInfo->BitsPerPixel = miAF.BitsPerPixel; modeInfo->BytesPerScanLine = miAF.BytesPerScanLine; modeInfo->NumberOfPages = miAF.MaxBuffers; modeInfo->RedMaskSize = miAF.RedMaskSize; modeInfo->RedFieldPosition = miAF.RedFieldPosition; modeInfo->GreenMaskSize = miAF.GreenMaskSize; modeInfo->GreenFieldPosition = miAF.GreenFieldPosition; modeInfo->BlueMaskSize = miAF.BlueMaskSize; modeInfo->BlueFieldPosition = miAF.BlueFieldPosition; modeInfo->RsvdMaskSize = miAF.RsvdMaskSize; modeInfo->RsvdFieldPosition = miAF.RsvdFieldPosition; if (miAF.LinBytesPerScanLine != 0) { /* VBE/AF 1.1 spec and later */ modeInfo->LinBytesPerScanLine = miAF.LinBytesPerScanLine; modeInfo->BnkNumberOfPages = miAF.BnkMaxBuffers; modeInfo->LinNumberOfPages = miAF.LinMaxBuffers; modeInfo->LinRedMaskSize = miAF.LinRedMaskSize; modeInfo->LinRedFieldPosition = miAF.LinRedFieldPosition; modeInfo->LinGreenMaskSize = miAF.LinGreenMaskSize; modeInfo->LinGreenFieldPosition = miAF.LinGreenFieldPosition; modeInfo->LinBlueMaskSize = miAF.LinBlueMaskSize; modeInfo->LinBlueFieldPosition = miAF.LinBlueFieldPosition; modeInfo->LinRsvdMaskSize = miAF.LinRsvdMaskSize; modeInfo->LinRsvdFieldPosition = miAF.LinRsvdFieldPosition; } else { /* Older version of the VBE/AF spec so use banked values */ modeInfo->LinBytesPerScanLine = miAF.BytesPerScanLine; modeInfo->BnkNumberOfPages = miAF.MaxBuffers; modeInfo->LinNumberOfPages = miAF.MaxBuffers; modeInfo->LinRedMaskSize = miAF.RedMaskSize; modeInfo->LinRedFieldPosition = miAF.RedFieldPosition; modeInfo->LinGreenMaskSize = miAF.GreenMaskSize; modeInfo->LinGreenFieldPosition = miAF.GreenFieldPosition; modeInfo->LinBlueMaskSize = miAF.BlueMaskSize; modeInfo->LinBlueFieldPosition = miAF.BlueFieldPosition; modeInfo->LinRsvdMaskSize = miAF.RsvdMaskSize; modeInfo->LinRsvdFieldPosition = miAF.RsvdFieldPosition; } #endif } else { VBE_modeInfo miVBE; if (!VBE_getModeInfo(mode,&miVBE)) return false; if (!(miVBE.ModeAttributes & vbeMdGraphMode)) return false; modeInfo->XResolution = miVBE.XResolution; modeInfo->YResolution = miVBE.YResolution; modeInfo->BitsPerPixel = miVBE.BitsPerPixel; modeInfo->BytesPerScanLine = miVBE.BytesPerScanLine; modeInfo->NumberOfPages = miVBE.NumberOfImagePages+1; modeInfo->RedMaskSize = miVBE.RedMaskSize; modeInfo->RedFieldPosition = miVBE.RedFieldPosition; modeInfo->GreenMaskSize = miVBE.GreenMaskSize; modeInfo->GreenFieldPosition = miVBE.GreenFieldPosition; modeInfo->BlueMaskSize = miVBE.BlueMaskSize; modeInfo->BlueFieldPosition = miVBE.BlueFieldPosition; modeInfo->RsvdMaskSize = miVBE.RsvdMaskSize; modeInfo->RsvdFieldPosition = miVBE.RsvdFieldPosition; /* Fill in Attributes field depending on what the controller can * support. */ modeInfo->Attributes = svIsVBEMode; if (modeInfo->NumberOfPages > 1) { modeInfo->Attributes |= svHaveMultiBuffer; modeInfo->Attributes |= svHaveVirtualScroll; } if (!(miVBE.ModeAttributes & vbeMdNonBanked)) modeInfo->Attributes |= svHaveBankedBuffer; if (miVBE.ModeAttributes & vbeMdLinear) modeInfo->Attributes |= svHaveLinearBuffer; if (miVBE.ModeAttributes & vbeMdNonVGA) modeInfo->Attributes |= svNonVGAMode; if (miVBE.LinBytesPerScanLine != 0) { /* VBE 2.1 and later extra information for properly handling * the linear framebuffer modes. */ modeInfo->LinBytesPerScanLine = miVBE.LinBytesPerScanLine; modeInfo->BnkNumberOfPages = miVBE.BnkNumberOfImagePages+1; modeInfo->LinNumberOfPages = miVBE.LinNumberOfImagePages+1; modeInfo->LinRedMaskSize = miVBE.LinRedMaskSize; modeInfo->LinRedFieldPosition = miVBE.LinRedFieldPosition; modeInfo->LinGreenMaskSize = miVBE.LinGreenMaskSize; modeInfo->LinGreenFieldPosition = miVBE.LinGreenFieldPosition; modeInfo->LinBlueMaskSize = miVBE.LinBlueMaskSize; modeInfo->LinBlueFieldPosition = miVBE.LinBlueFieldPosition; modeInfo->LinRsvdMaskSize = miVBE.LinRsvdMaskSize; modeInfo->LinRsvdFieldPosition = miVBE.LinRsvdFieldPosition; } else { /* Older VBE 2.0 version of the spec, so use the values * for the banked modes. */ modeInfo->LinBytesPerScanLine = miVBE.BytesPerScanLine; modeInfo->BnkNumberOfPages = miVBE.NumberOfImagePages+1; modeInfo->LinNumberOfPages = miVBE.NumberOfImagePages+1; modeInfo->LinRedMaskSize = miVBE.RedMaskSize; modeInfo->LinRedFieldPosition = miVBE.RedFieldPosition; modeInfo->LinGreenMaskSize = miVBE.GreenMaskSize; modeInfo->LinGreenFieldPosition = miVBE.GreenFieldPosition; modeInfo->LinBlueMaskSize = miVBE.BlueMaskSize; modeInfo->LinBlueFieldPosition = miVBE.BlueFieldPosition; modeInfo->LinRsvdMaskSize = miVBE.RsvdMaskSize; modeInfo->LinRsvdFieldPosition = miVBE.RsvdFieldPosition; } } modeInfo->Mode = mode; return true; } PUBLIC int SVAPI SV_getModeName(char *buf,SV_modeInfo *mi,ushort mode,bool useLinear) /**************************************************************************** * * Function: SV_getModeName * Parameters: buf - Buffer to put mode name into * mi - Pointer to VBE mode info block * mode - Mode number for the mode * useLinear - True if we should the linear buffer if available * Returns: Mode number to set mode with (with appropriate flags added) * * Description: Puts the name of the video mode in a standard format into * the string buffer, and returns the mode number to be used * to set the video mode. * ****************************************************************************/ { char buf1[80],buf2[80]; int bankedAndLinear,attr = mi->Attributes; /* Ignore linear only modes if linear buffering not available */ if (!(attr & svHaveBankedBuffer) && !useLinear) return 0; /* Build the name of the mode */ if (useLinear) { if ((attr & svHaveBankedBuffer) && (attr & svHaveLinearBuffer)) { sprintf(buf2,", Banked+Linear"); bankedAndLinear = true; } else if (attr & svHaveLinearBuffer) { sprintf(buf2,", Linear Only"); bankedAndLinear = false; } else { sprintf(buf2,", Banked Only"); bankedAndLinear = false; } #ifdef USE_VBE20 /* Use the linear framebuffer mode if available */ if (attr & svHaveLinearBuffer) mode |= svLinearBuffer; #endif } else { sprintf(buf2,", Banked Only"); bankedAndLinear = false; } if (bankedAndLinear && (mi->BnkNumberOfPages != mi->LinNumberOfPages)) sprintf(buf1,"%2d/%d", mi->BnkNumberOfPages, mi->LinNumberOfPages); else sprintf(buf1,"%2d", mi->NumberOfPages); sprintf(buf,"%4d x %4d %d bit (%s page%s",mi->XResolution,mi->YResolution, mi->BitsPerPixel,buf1,buf2); if (attr & svHaveAccel2D) strcat(buf,", Accelerated"); if (attr & svNonVGAMode) strcat(buf,", NonVGA)"); else strcat(buf,")"); return mode; } PRIVATE bool SetModeVBE(ushort mode,bool use8BitDAC,bool useVirtualBuffer, bool setPalette) /**************************************************************************** * * Function: SetModeVBE * Parameters: mode - SuperVGA video mode to set. * use8BitDAC - True to set up the 8 bit DAC mode * 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 SV_init() routine first. * ****************************************************************************/ { VBE_modeInfo modeInfo; RMREGS regs; int imode = mode & svModeMask; int cntMode = VBE_getVideoMode(); if (imode < 0x100 && imode != 0x13) return false; if (imode != cntMode && cntMode <= 3) { _SV_old50Lines = false; /* Default to 25 line mode */ if (cntMode == 0x3) { regs.x.ax = 0x1130; regs.x.bx = 0; regs.x.dx = 0; PM_int86(0x10,®s,®s); _SV_old50Lines = (regs.h.dl == 49); } } if (!VBE_setVideoMode(mode)) /* Set the video mode */ return false; /* Initialise global variables for current video mode dimensions */ if (imode == 0x13) { /* Special case for VGA mode 13h */ DC.maxx = 319; DC.maxy = 199; DC.bytesperline = 320; DC.bitsperpixel = 8; DC.maxpage = 0; _SV_pagesize = 0x10000L; _SV_bankShift = 0; DC.isNonVGA = false; } else { VBE_getModeInfo(imode,&modeInfo); DC.maxx = modeInfo.XResolution-1; DC.maxy = modeInfo.YResolution-1; DC.bitsperpixel = modeInfo.BitsPerPixel; if (modeInfo.LinBytesPerScanLine != 0) { /* VBE 2.1 extensions for linear buffer info */ DC.bytesperline = modeInfo.LinBytesPerScanLine; if (mode & vbeLinearBuffer) DC.maxpage = modeInfo.LinNumberOfImagePages; else DC.maxpage = modeInfo.BnkNumberOfImagePages; } else { DC.bytesperline = modeInfo.BytesPerScanLine; DC.maxpage = modeInfo.NumberOfImagePages; } _SV_pagesize = VBE_getPageSize(&modeInfo); _SV_bankShift = 0; while ((64 >> _SV_bankShift) != modeInfo.WinGranularity) _SV_bankShift++; /* If the controller is reported as NonVGA, then we must use the * provided VBE 2.0 palette programming functions. Otherwise we * can simply program the VGA palette registers directly. */ DC.isNonVGA = ((modeInfo.ModeAttributes & vbeMdNonVGA) != 0); } DC.curBank = -1; /* Emulate RGB modes using a 3 3 2 palette arrangement by default */ DC.redMask = 0x7; DC.redPos = 5; DC.redAdjust = 5; DC.greenMask = 0x7; DC.greenPos = 2; DC.greenAdjust = 5; DC.blueMask = 0x3; DC.bluePos = 0; DC.blueAdjust = 6; if (imode != 0x13 && modeInfo.MemoryModel == vbeMemRGB) { /* Save direct color info mask positions etc */ if ((mode & vbeLinearBuffer) && modeInfo.LinBytesPerScanLine != 0) { /* VBE 2.1 extended linear mode color format information */ DC.redMask = (0xFF >> (DC.redAdjust = 8 - modeInfo.LinRedMaskSize)); DC.redPos = modeInfo.LinRedFieldPosition; DC.greenMask = (0xFF >> (DC.greenAdjust = 8 - modeInfo.LinGreenMaskSize)); DC.greenPos = modeInfo.LinGreenFieldPosition; DC.blueMask = (0xFF >> (DC.blueAdjust = 8 - modeInfo.LinBlueMaskSize)); DC.bluePos = modeInfo.LinBlueFieldPosition; } else { /* Banked color format information */ DC.redMask = (0xFF >> (DC.redAdjust = 8 - modeInfo.RedMaskSize)); DC.redPos = modeInfo.RedFieldPosition; DC.greenMask = (0xFF >> (DC.greenAdjust = 8 - modeInfo.GreenMaskSize)); DC.greenPos = modeInfo.GreenFieldPosition; DC.blueMask = (0xFF >> (DC.blueAdjust = 8 - modeInfo.BlueMaskSize)); DC.bluePos = modeInfo.BlueFieldPosition; } } /* Get pointer to video memory */ if (imode == 0x13) { #ifdef __WIN386__ ushort sel = PM_createSelector(0xA0000L,0xFFFF); if (!sel) { SV_restoreMode(); exit(1); } DC.videoMem = (void*)((ulong)sel << 16); #else if ((DC.videoMem = PM_mapPhysicalAddr(0xA0000L,0xFFFF)) == NULL) { SV_restoreMode(); exit(1); } #endif } else { if ((DC.videoMem = VBE_getBankedPointer(&modeInfo)) == NULL) { SV_restoreMode(); exit(1); } } DC.virtualBuffer = false; DC.setActivePage = _SV_setActivePage; DC.setVisualPage = _SV_setVisualPage; #ifdef USE_VBE20 VBE_freePMCode(); _SV_setBank20 = VBE_getSetBank(); _SV_setCRT20 = VBE_getSetDisplayStart(); _SV_setPal20 = VBE_getSetPalette(); if ((mode & vbeLinearBuffer) && imode != 0x13) { #ifdef PM386 if ((DC.videoMem = VBE_getLinearPointer(&modeInfo)) == NULL) { SV_restoreMode(); exit(1); } #else uint videoSel = VBE_getLinearSelector(&modeInfo); if (!videoSel) { SV_restoreMode(); exit(1); } DC.videoMem = MK_FP(videoSel,0); #endif DC.setActivePage = _SV_setActivePageLin; } else if (DC.haveVirtualBuffer && useVirtualBuffer && DC.bitsperpixel > 4) { /* See if we can use the VFlat virtual linear framebuffer. This * does however require VBE 2.0 and the virtual flat linear * framebuffer device support. */ void *bankFunc,*p; int codeLen; VBE_getBankFunc32(&codeLen,&bankFunc,0,_SV_bankShift); VF_exit(); if ((p = VF_init((ulong)modeInfo.WinASegment << 4,modeInfo.WinSize, codeLen,bankFunc)) != NULL) { DC.videoMem = p; DC.setActivePage = _SV_setActivePageLin; DC.virtualBuffer = true; mode |= vbeLinearBuffer; } } #endif /* Set up a pointer to the appopriate bank switching code to use */ _SV_setBankPtr = (void*)SV_nop; if (imode != 0x13) { if ((modeInfo.WinAAttributes & 0x7) != 0x7) { #ifdef USE_VBE20 if (_SV_setBank20) { if (VBE_MMIOSel) _SV_setBankPtr = _VBE20_setBankAB_ES; else _SV_setBankPtr = _VBE20_setBankAB; } else #endif _SV_setBankPtr = _VBE_setBankAB; } else { #ifdef USE_VBE20 if (_SV_setBank20) { if (VBE_MMIOSel) _SV_setBankPtr = _VBE20_setBankA_ES; else _SV_setBankPtr = _VBE20_setBankA; } else #endif _SV_setBankPtr = _VBE_setBankA; } #ifdef REALMODE _SV_setBankRM = (void *)modeInfo.WinFuncPtr; #else _SV_setBankRM = NULL; #endif } /* Now set up the vectors to the correct routines for the video * mode type. */ switch (DC.bitsperpixel) { case 4: DC.clear = _SV_clear16; DC.putPixel = _SV_putPixel16; DC.line = _SV_line16; DC.maxcolor = DC.defcolor = 15; DC.bytesperpixel = 1; break; case 8: DC.clear = _SV_clear256; DC.putPixel = _SV_putPixel256; DC.line = _SV_line256; DC.maxcolor = 255; DC.defcolor = 15; DC.bytesperpixel = 1; #ifdef USE_VBE20 if (mode & vbeLinearBuffer) { DC.clear = _SV_clear256Lin; DC.putPixel = _SV_putPixel256Lin; DC.line = _SV_line256Lin; } #endif break; case 15: case 16: DC.clear = _SV_clear32k; DC.putPixel = _SV_putPixel32k; DC.line = _SV_line32k; DC.maxcolor = DC.defcolor = SV_rgbColor(0xFF,0xFF,0xFF); DC.bytesperpixel = 2; #ifdef USE_VBE20 if (mode & vbeLinearBuffer) { DC.clear = _SV_clear32kLin; DC.putPixel = _SV_putPixel32kLin; DC.line = _SV_line32kLin; } #endif break; case 24: DC.clear = _SV_clear16m; DC.putPixel = _SV_putPixel16m; DC.line = _SV_line16m; DC.maxcolor = DC.defcolor = SV_rgbColor(0xFF,0xFF,0xFF); DC.bytesperpixel = 3; #ifdef USE_VBE20 if (mode & vbeLinearBuffer) { DC.clear = _SV_clear16mLin; DC.putPixel = _SV_putPixel16mLin; DC.line = _SV_line16mLin; } #endif break; case 32: DC.clear = _SV_clear4G; DC.putPixel = _SV_putPixel4G; DC.line = _SV_line4G; DC.maxcolor = DC.defcolor = SV_rgbColor(0xFF,0xFF,0xFF); DC.bytesperpixel = 4; #ifdef USE_VBE20 if (mode & vbeLinearBuffer) { DC.clear = _SV_clear4GLin; DC.putPixel = _SV_putPixel4GLin; DC.line = _SV_line4GLin; } #endif break; } DC.beginDirectAccess = (void*)SV_nop; DC.endDirectAccess = (void*)SV_nop; DC.beginPixel = (void*)SV_nop; DC.putPixelFast = DC.putPixel; DC.endPixel = (void*)SV_nop; DC.beginLine = (void*)SV_nop; DC.lineFast = DC.line; DC.endLine = (void*)SV_nop; PM_saveDS(); if (DC.bitsperpixel == 8) { /* Program the default VGA palette */ _SV_convertPal = true; if (use8BitDAC && VBE_setDACWidth(8)) _SV_convertPal = false; if (setPalette) SV_setPalette(0,256,VGA8_defPal,-1); else { SV_palette tmp[256]; memset(tmp,0,sizeof(tmp)); SV_setPalette(0,256,tmp,-1); } } DC.setActivePage(0); DC.setVisualPage(0,false); if ((mode & svDontClear) == 0) SV_clear(0); return true; } #ifdef USE_VBEAF PRIVATE bool SetModeAF(ushort mode,int virtualX,int virtualY, bool useVirtualBuffer,int numBuffers,bool setPalette) /**************************************************************************** * * Function: SetModeAF * Parameters: mode - SuperVGA video mode to set. * Returns: True if the mode was set, false if not. * * Description: * ****************************************************************************/ { AF_modeInfo modeInfo; AF_int32 bpl = -1; int cntMode,imode = mode & svModeMask; RMREGS regs; /* Grab information about the current video mode */ if (imode < 0x100) return false; regs.h.ah = 0x0F; PM_int86(0x10,®s,®s); cntMode = regs.h.al & 0x7F; if (imode != cntMode && cntMode <= 3) { _SV_old50Lines = false; /* Default to 25 line mode */ if (cntMode == 0x3) { regs.x.ax = 0x1130; regs.x.bx = 0; regs.x.dx = 0; PM_int86(0x10,®s,®s); _SV_old50Lines = (regs.h.dl == 49); } } /* Turn off the double buffer flag if the user requested double * buffering but only one pages is available. If we dont do this, the * VBE/AF mode set code will fail the mode set. */ AF_getVideoModeInfo(DC.AFDC,imode,&modeInfo); if (!(modeInfo.Attributes & afHaveMultiBuffer)) mode &= ~svMultiBuffer; /* Set the video mode - note that we dont clear the video memory as * we need to save and restore the video memory if we are running * under Windows to fix problems with buggy Windows drivers that cache * bitmaps in offscreen memory, but dont bother to save/restore them * across a DOS box. */ if (mode & afVirtualScroll) { if (AF_setVirtualVideoMode(DC.AFDC,mode,virtualX,virtualY,&bpl, numBuffers) != 0) return false; } else { if (AF_setVideoMode(DC.AFDC,mode,&bpl,numBuffers) != 0) return false; } /* Initialise global variables for current video mode dimensions */ DC.bytesperline = bpl; DC.maxx = DC.AFDC->BufferEndX; DC.maxy = DC.AFDC->BufferEndY; DC.bitsperpixel = modeInfo.BitsPerPixel; if (modeInfo.LinBytesPerScanLine != 0) { if (mode & vbeLinearBuffer) DC.maxpage = modeInfo.LinMaxBuffers-1; else DC.maxpage = modeInfo.BnkMaxBuffers-1; } else { DC.maxpage = modeInfo.MaxBuffers-1; } _SV_pagesize = 0; _SV_bankShift = 0; DC.curBank = -1; /* Save direct color info mask positions etc. We emulate 8 bit RGB modes * using a 3 3 2 palette arrangement by default */ DC.redMask = 0x7; DC.redPos = 5; DC.redAdjust = 5; DC.greenMask = 0x7; DC.greenPos = 2; DC.greenAdjust = 5; DC.blueMask = 0x3; DC.bluePos = 0; DC.blueAdjust = 6; if (DC.bitsperpixel > 8) { if ((mode & vbeLinearBuffer) && modeInfo.LinBytesPerScanLine != 0) { DC.redMask = (0xFF >> (DC.redAdjust = 8 - modeInfo.LinRedMaskSize)); DC.redPos = modeInfo.LinRedFieldPosition; DC.greenMask = (0xFF >> (DC.greenAdjust = 8 - modeInfo.LinGreenMaskSize)); DC.greenPos = modeInfo.LinGreenFieldPosition; DC.blueMask = (0xFF >> (DC.blueAdjust = 8 - modeInfo.LinBlueMaskSize)); DC.bluePos = modeInfo.LinBlueFieldPosition; } else { DC.redMask = (0xFF >> (DC.redAdjust = 8 - modeInfo.RedMaskSize)); DC.redPos = modeInfo.RedFieldPosition; DC.greenMask = (0xFF >> (DC.greenAdjust = 8 - modeInfo.GreenMaskSize)); DC.greenPos = modeInfo.GreenFieldPosition; DC.blueMask = (0xFF >> (DC.blueAdjust = 8 - modeInfo.BlueMaskSize)); DC.bluePos = modeInfo.BlueFieldPosition; } } /* Set up a pointer to the appopriate bank switching code to use */ DC.virtualBuffer = false; _SV_setBankPtr = _VBEAF_setBank; DC.videoMem = DC.AFDC->BankedMem; DC.setActivePage = _SV_setActivePageAF; DC.setVisualPage = _SV_setVisualPageAF; if (mode & svLinearBuffer) { DC.videoMem = DC.AFDC->LinearMem; DC.setActivePage = _SV_setActivePageLinAF; } else if (DC.haveVirtualBuffer && useVirtualBuffer && DC.AFDC->SetBank32) { /* See if we can use the VFlat virtual linear framebuffer */ void *bankFunc,*p; int codeLen; AF_getBankFunc32(DC.AFDC,&codeLen,&bankFunc); VF_exit(); if ((p = VF_init(DC.AFDC->BankedBasePtr,DC.AFDC->BankSize, codeLen,bankFunc)) != NULL) { DC.videoMem = p; DC.setActivePage = _SV_setActivePageLinAF; DC.virtualBuffer = true; mode |= svLinearBuffer; } } /* Now set up the vectors to the correct routines for the video * mode type. */ switch (DC.bitsperpixel) { case 8: DC.clear = _SV_clear256; DC.putPixel = _SV_putPixel256; DC.line = _SV_line256; DC.maxcolor = 255; DC.defcolor = 15; DC.bytesperpixel = 1; if (mode & svLinearBuffer) { DC.clear = _SV_clear256Lin; DC.putPixel = _SV_putPixel256Lin; DC.line = _SV_line256Lin; } break; case 15: case 16: DC.clear = _SV_clear32k; DC.putPixel = _SV_putPixel32k; DC.line = _SV_line32k; DC.maxcolor = DC.defcolor = SV_rgbColor(0xFF,0xFF,0xFF); DC.bytesperpixel = 2; if (mode & svLinearBuffer) { DC.clear = _SV_clear32kLin; DC.putPixel = _SV_putPixel32kLin; DC.line = _SV_line32kLin; } break; case 24: DC.clear = _SV_clear16m; DC.putPixel = _SV_putPixel16m; DC.line = _SV_line16m; DC.maxcolor = DC.defcolor = SV_rgbColor(0xFF,0xFF,0xFF); DC.bytesperpixel = 3; if (mode & svLinearBuffer) { DC.clear = _SV_clear16mLin; DC.putPixel = _SV_putPixel16mLin; DC.line = _SV_line16mLin; } break; case 32: DC.clear = _SV_clear4G; DC.putPixel = _SV_putPixel4G; DC.line = _SV_line4G; DC.maxcolor = DC.defcolor = SV_rgbColor(0xFF,0xFF,0xFF); DC.bytesperpixel = 4; if (mode & svLinearBuffer) { DC.clear = _SV_clear4GLin; DC.putPixel = _SV_putPixel4GLin; DC.line = _SV_line4GLin; } break; } /* Setup support for accelerator functions if we have these. Note that * we transparently support acceleration of screen clearing and line * drawing functions only. You can call the VBE/AF function to draw * other primitives directly but we dont have software emulation for * the routines if they are not available in hardware. */ DC.beginDirectAccess = (void*)SV_nop; DC.endDirectAccess = (void*)SV_nop; DC.beginPixel = (void*)SV_nop; DC.putPixelFast = DC.putPixel; DC.endPixel = (void*)SV_nop; DC.beginLine = (void*)SV_nop; DC.lineFast = DC.line; DC.endLine = (void*)SV_nop; if (modeInfo.Attributes & afHaveAccel2D) { if (DC.AFDC->EnableDirectAccess) { DC.beginDirectAccess = _SV_beginDirectAccessAFSLOW; DC.endDirectAccess = _SV_endDirectAccessAFSLOW; DC.beginPixel = _SV_beginPixelAFSLOW; DC.endPixel = _SV_endPixelAFSLOW; DC.beginLine = _SV_beginLineAFSLOW; DC.endLine = _SV_endLineAFSLOW; } else { DC.beginDirectAccess = _SV_beginDirectAccessAF; DC.endDirectAccess = _SV_endDirectAccessAF; DC.beginPixel = _SV_beginPixelAF; DC.endPixel = _SV_endPixelAF; DC.beginLine = _SV_beginLineAF; DC.endLine = _SV_endLineAF; } DC.clear = _SV_clearAF; DC.putPixel = _SV_putPixelAF; #if 0 if (DC.AFDC->DrawLine) { /* Accelerated line drawing */ DC.beginLine = (void*)SV_nop; DC.line = _SV_lineFastAF; DC.lineFast = _SV_lineFastAF; DC.endLine = (void*)SV_nop; } else { #endif /* Software line drawing */ DC.line = _SV_softLineAF; // } /* Set default mix */ AF_setMix(DC.AFDC,AF_REPLACE_MIX,AF_REPLACE_MIX); } PM_saveDS(); if (DC.bitsperpixel == 8) { /* Program the default VGA palette. Note that VBE/AF always takes * palette values in 8 bits per pixel format. */ _SV_convertPal = false; if (setPalette) SV_setPalette(0,256,VGA8_defPal,-1); else { SV_palette tmp[256]; memset(tmp,0,sizeof(tmp)); SV_setPalette(0,256,tmp,-1); } } DC.setActivePage(0); DC.setVisualPage(0,false); if ((mode & svDontClear) == 0) SV_clear(0); return true; } void SVAPI SV_setACCELDriver(AF_devCtx *driver) { loadedDC = driver; } #endif #if defined(SAFE_MODE) || defined(__WINDOWS__) /* The following Safe Mode can be enabled to save/restore the entire * video memory to disk before the video mode is started. This can solve * some problems with Windows drivers for code running in a DOS box or * in a WinDirect Window. This does however cause a significant slowdown * in the code, which is why it is currently only enabled for Windows * apps when the safe mode option of WinDirect is on. */ PRIVATE int saveMode; PRIVATE char saveMemName[_MAX_PATH] = ""; PRIVATE void backslash(char *s) { uint pos = strlen(s); if (s[pos-1] != '\\') { s[pos] = '\\'; s[pos+1] = '\0'; } } PRIVATE void SaveVideoMemory(int mode) /**************************************************************************** * * Function: SaveVideoMemory * * Description: Starts a 640x480x256 color graphics mode and streams all * video memory to a tempory disk file. This is necessary so * we can restore the video memory back to the state it was * in originally to avoid problems with buggy Windows drivers * that cache bitmaps in offscreen video memory but do not * correctly restore the memory when a DOS box or WinDirect * application returns to GDI mode. * * If we are starting a banked video mode, we start a banked * version of 640x480x256 and save the memory with that. For * linear modes we start the linear version instead. * ****************************************************************************/ { ulong size; bool fail = false; FILE *f; if (saveMemName[0] != 0) return; #ifndef __WINDOWS__ /* Dont bother to save/restore video memory when running under real DOS, * only under Windows DOS boxes. */ { RMREGS regs; regs.x.ax = 0x160A; PM_int86(0x2F,®s,®s); if (regs.x.ax != 0) return; } #else if (!WD_isSafeMode()) return; #endif saveMode = 0x101 | (mode & svLinearBuffer) | svDontClear; #ifdef USE_VBEAF if (DC.AFDC) { if (!SetModeAF(saveMode,-1,-1,false,1,false)) return; } else #endif if (!SetModeVBE(saveMode,false,false,false)) return; /* Open a temporary file to save the video memory to */ if (getenv("TEMP")) strcpy(saveMemName,getenv("TEMP")); else if (getenv("TMP")) strcpy(saveMemName,getenv("TEMP")); else strcpy(saveMemName,"c:\\"); backslash(saveMemName); strcat(saveMemName,tmpnam(NULL)); if ((f = fopen(saveMemName,"wb")) == NULL) return; /* Save entire video memory in chunks of 32Kb at a time except under * 32 bit protecetd mode with a linear framebuffer in which case we * can save it directly as a single block. */ #ifdef PM386 if (saveMode & svLinearBuffer) { size = DC.memory * 1024L; if (fwrite(DC.videoMem,1,size,f) != size) fail = true; } else #endif { #ifndef __WIN386__ int i,maxBlocks = DC.memory / 64; size = 0x8000; for (i = 0; i < maxBlocks; i++) { SV_setBank(i >> 1); if ((i & 1) == 0) { if (fwrite((uchar*)DC.videoMem,1,size,f) != size) { fail = true; break; } } else { if (fwrite((uchar*)DC.videoMem + size,1,size,f) != size) { fail = true; break; } } } #endif } fclose(f); if (fail) { unlink(saveMemName); saveMemName[0] = 0; } } PRIVATE void RestoreVideoMemory(void) /**************************************************************************** * * Function: RestoreVideoMemory * * Description: Restores the video memory from the memory buffer or * disk file after the mode has been reset to correctly * restore all cached bitmaps for Windows drivers. * ****************************************************************************/ { ulong size; FILE *f; if (saveMemName[0] == 0) return; #ifdef USE_VBEAF if (DC.AFDC) { if (!SetModeAF(saveMode,-1,-1,false,1,false)) return; } else #endif if (!SetModeVBE(saveMode,false,false,false)) return; /* Open the temporary file to restore the video memory from */ if ((f = fopen(saveMemName,"rb")) == NULL) return; /* Restore entire video memory in chunks of 32Kb at a time except under * 32 bit protecetd mode with a linear framebuffer in which case we * can restore it directly as a single block. */ #ifdef PM386 if (saveMode & svLinearBuffer) { size = DC.memory * 1024L; fread(DC.videoMem,1,size,f); } else #endif { #ifndef __WIN386__ int i,maxBlocks = DC.memory / 64; size = 0x8000; for (i = 0; i < maxBlocks; i++) { SV_setBank(i >> 1); if ((i & 1) == 0) fread((uchar*)DC.videoMem,1,size,f); else fread((uchar*)DC.videoMem + size,1,size,f); } #endif } fclose(f); unlink(saveMemName); saveMemName[0] = 0; } #else #define SaveVideoMemory(m) #define RestoreVideoMemory() #endif PUBLIC bool SVAPI SV_setMode(ushort mode,bool use8BitDAC, bool useVirtualBuffer,bool numBuffers) /**************************************************************************** * * Function: SV_setMode * Parameters: mode - SuperVGA video mode to set. * use8BitDAC - Turn on 8 bit DAC mode (for VBE modes only) * useVirtualBuffer - True to use virtual linear buffer * numBuffers - Number of image buffers to use * 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 SV_init() routine first. * * If the use8BitDAC flag is set, the 8 bit DAC mode will be * use for VBE graphics modes. For VBE/AF the 8 bit DAC mode * is used automatically if it is available, so this flag is * ignored. * ****************************************************************************/ { SV_modeInfo mi; if (!SV_getModeInfo(mode & svModeMask,&mi)) return false; #ifdef __WINDOWS__ WD_startFullScreen(hwndMain,mi.XResolution,mi.YResolution); #else WD_startFullScreen(NULL,mi.XResolution,mi.YResolution); #endif SaveVideoMemory(mode); #ifdef USE_VBEAF if (DC.AFDC) { if (!SetModeAF(mode,-1,-1,useVirtualBuffer,numBuffers,true)) return false; } else #endif { if (!SetModeVBE(mode &= ~svMultiBuffer,use8BitDAC,useVirtualBuffer,true)) return false; } WD_inFullScreen(); return true; } PUBLIC bool SVAPI SV_setVirtualMode(ushort mode,int virtualX,int virtualY, bool use8BitDAC,bool useVirtualBuffer,int numBuffers) /**************************************************************************** * * Function: SV_setVirtualMode * Parameters: mode - SuperVGA video mode to set. * virtualX - Virtual screen X coordinate * virtualY - Virtual screen Y coordinate * Returns: True if the mode was set, false if not. * * Description: Attempts to set the specified video mode with virtual * scrolling enabled for the specified dimensions. If virtual * scrolling cannot be obtained correctly for this mode, * we return false. * ****************************************************************************/ { int newbytes; SV_modeInfo mi; if (!SV_getModeInfo(mode & svModeMask,&mi)) return false; #ifdef __WINDOWS__ WD_startFullScreen(hwndMain,mi.XResolution,mi.YResolution); #else WD_startFullScreen(NULL,mi.XResolution,mi.YResolution); #endif SaveVideoMemory(mode); #ifdef USE_VBEAF if (DC.AFDC) { return SetModeAF(mode | afVirtualScroll,virtualX,virtualY, useVirtualBuffer,numBuffers,true); } else #endif { if (!SetModeVBE(mode,use8BitDAC,useVirtualBuffer,true)) return false; if (!VBE_setPixelsPerLine(virtualX,&newbytes,&virtualX,&virtualY)) { SV_restoreMode(); return false; } } DC.bytesperline = newbytes; DC.maxx = virtualX-1; DC.maxy = virtualY-1; return true; } PUBLIC void SVAPI SV_restoreMode(void) /**************************************************************************** * * Function: SV_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. * ****************************************************************************/ { RMREGS regs; RestoreVideoMemory(); #ifdef USE_VBE20 VF_exit(); VBE_freePMCode(); /* Free up protected mode code */ #endif #ifdef USE_VBEAF if (DC.AFDC) AF_restoreTextMode(DC.AFDC); else #endif VBE_setVideoMode(0x3); /* Reset to text mode */ if (_SV_old50Lines) { regs.x.ax = 0x1112; regs.x.bx = 0; PM_int86(0x10,®s,®s); /* Restore 50 line mode */ } WD_restoreGDI(); } PUBLIC void SVAPI SV_setPalette(int start,int num,SV_palette *pal,int maxProg) /**************************************************************************** * * Function: SV_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 the palette by interleaving blocks of values with * the vertical retrace interval. We use the VBE 2.0 palette * interface routines if possible, and have a VGA style * routine for VBE 1.2 implementations. * * Note that this routine *requires* all input palette values * to be in 8 bits per primary format, and does automatic * conversion from 8 bits per primary formay to the 6 bit * format required by some cards if necessary. * ****************************************************************************/ { int i,waitFlag,count; uchar temp[1024],*t,*p = (uchar*)&pal[start]; /* First copy the palette values into our temporary palette, * translating from the internal 8 bit format to the VGA 6 bit * format (if we have a wide palette, then we simply skip this step) */ if (_SV_convertPal) { for (i = 0,t = temp; i < num; i++) { *t++ = *p++ >> 2; *t++ = *p++ >> 2; *t++ = *p++ >> 2; t++; p++; } p = temp; } /* Determine if we need to wait for the vertical retrace */ if (maxProg == -1) { waitFlag = 0x00; count = num; } else { waitFlag = 0x80; count = (num > maxProg) ? maxProg : num; } while (num) { #ifdef USE_VBEAF if (DC.AFDC) AF_setPaletteData(DC.AFDC,(AF_palette*)p,count,start,waitFlag == 0x80); else #endif if (!DC.isNonVGA) _VGA_setPalette(start,count,(SV_palette*)p,waitFlag); #ifdef USE_VBE20 else if (_SV_setPal20) _VBE20_setPalette(start,count,(SV_palette*)p,waitFlag); #endif else VBE_setPalette(start,count,(VBE_palette*)p,waitFlag); start += count; p += count; num -= count; count = (num > maxProg) ? maxProg : num; } } PUBLIC ulong SVAPI SV_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 ((ulong)((r >> DC.redAdjust) & DC.redMask) << DC.redPos) | ((ulong)((g >> DC.greenAdjust) & DC.greenMask) << DC.greenPos) | ((ulong)((b >> DC.blueAdjust) & DC.blueMask) << DC.bluePos); } PUBLIC void SVAPI SV_writeText(int x,int y,char *str,ulong 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 = font8x16; length = strlen(str); DC.beginPixel(); 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) DC.putPixelFast(x+i,y+j,color); byte <<= 1; } } x += 8; } DC.endPixel(); } void SVAPI SV_setDisplayStart(int x,int y,bool waitVRT) /**************************************************************************** * * Function: SV_setDisplayStart * Parameters: x,y - Position of the first pixel to display * * Description: Sets the new starting display position to implement * hardware scrolling. * ****************************************************************************/ { #ifdef USE_VBEAF if (DC.AFDC) AF_setDisplayStart(DC.AFDC,x,y,waitVRT); else #endif VBE_setDisplayStart(x,y,waitVRT); } #ifdef USE_VBEAF PUBLIC void _ASMAPI _SV_setActivePageAF(int page) { ulong addr; /* Set active buffer and update internal pointers */ AF_setActiveBuffer(DC.AFDC,page); addr = DC.AFDC->OriginOffset; DC.originOffset = (ushort)addr; SV_setBank(DC.bankOffset = (addr >> 16)); /* Set hardware clip rectangle to new active page */ if (DC.AFDC->SetClipRect) AF_setClipRect(DC.AFDC,0,0,DC.maxx,DC.maxy); } PUBLIC void _ASMAPI _SV_setActivePageLinAF(int page) { /* Set active buffer and update internal pointers */ AF_setActiveBuffer(DC.AFDC,page); DC.originOffset = (ulong)DC.videoMem + DC.AFDC->OriginOffset; /* Set hardware clip rectangle to new active page */ if (DC.AFDC->SetClipRect) AF_setClipRect(DC.AFDC,0,0,DC.maxx,DC.maxy); } PUBLIC void _ASMAPI _SV_setVisualPageAF(int page,bool waitVRT) { AF_setVisibleBuffer(DC.AFDC,page,waitVRT); } PUBLIC void _ASMAPI _SV_clearAF(ulong color) { AF_drawRect(DC.AFDC,color,0,0,DC.maxx+1,DC.maxy+1); } PUBLIC void _ASMAPI _SV_putPixelAF(int x,int y,ulong color) { DC.beginPixel(); DC.putPixelFast(x,y,color); DC.endPixel(); } PUBLIC void _ASMAPI _SV_softLineAF(int x1,int y1,int x2,int y2,ulong color) { DC.beginLine(); DC.lineFast(x1,y1,x2,y2,color); DC.endLine(); } #endif #ifdef __WINDOWS16__ /* Windows specific stubs to handle different calling conventions for * 16 bit DLL's. We export all functions as pascal calling conventions, * and we do an internal thunk to the C calling conventions that we * require internally. */ void _ASMAPI _SV_setBank(int bank); int _ASMAPI _SV_queryCpu(void); void SVAPI SV_setBank(int bank) { _SV_setBank(bank); } int SVAPI SV_queryCpu(void) { return _SV_queryCpu(); } void SVAPI SV_beginPixel(void) { DC.beginPixel(); } void SVAPI SV_putPixel(int x,int y,ulong color) { DC.putPixel(x,y,color); } void SVAPI SV_putPixelFast(int x,int y,ulong color) { DC.putPixelFast(x,y,color); } void SVAPI SV_endPixel(void) { DC.endPixel(); } void SVAPI SV_clear(ulong color) { DC.clear(color); } void SVAPI SV_line(int x1,int y1,int x2,int y2,ulong color) { DC.line(x1,y1,x2,y2,color); } void SVAPI SV_beginLine(void) { DC.beginLine(); } void SVAPI SV_lineFast(int x1,int y1,int x2,int y2,ulong color) { DC.lineFast(x1,y1,x2,y2,color); } void SVAPI SV_endLine(void) { DC.endLine(); } void SVAPI SV_setActivePage(int page) { DC.setActivePage(page); } void SVAPI SV_setVisualPage(int page,bool waitVRT) { DC.setVisualPage(page,waitVRT); } void SVAPI SV_beginDirectAccess(void) { DC.beginDirectAccess(); } void SVAPI SV_endDirectAccess(void) { DC.endDirectAccess(); } #endif #ifdef __WINDOWS__ void SVAPI SV_setMainWindow(HWND hwnd) { hwndMain = hwnd; } #endif