⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video.c

📁 CEPC的引导代码,在BOIS基础上自定义引导WINCE内核,基于VC的工程
💻 C
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.

Module Name:

Abstract:

Functions:


Notes:

--*/

#include <string.h>
#include "loadcepc.h"
#include "video.h"
#include "..\inc\bootarg.h"

extern	BOOT_ARGS BootArgs;

BOOL	bNoModeSet = FALSE;

void mode320x200x256(void)
{
	/*
	** Put the display into 320x200x256 colour mode and clear it
	*/
	__asm
	{
		mov     ah, 0       ; Set video mode
		mov     al, 013h    ; 320x200x256 and clear screen
		int     10h         ; set mode 13
	}
}


int isVesaSupported(void)
{
    VESA_GENERAL_INFO   vesaInfo, far *pVesaInfo = &vesaInfo;

	__asm
    {
        mov     ax, 04F00h      ; Get VESA info
        les     di, pVesaInfo   ; Pointer to info buffer
        int     10h             ; check for VESA

        cmp     ax, 0004Fh      ; Was it successful?
        jne     noVesa
    }
	return TRUE;

noVesa:
	return FALSE;
}

int setVesaMode(int vesaMode, int scanLength)
{
    __asm
    {
        mov     ax, 04F02h      ; VESA Set mode
        mov     bx, vesaMode    ; Set given VESA Mode
        int     10h             ;

        cmp     ax, 0004Fh      ; Was it successful?
        jne     failed			;

		mov     cx, scanLength  ; Set so banks are an integral number lines
		jcxz	finished		; if no scanLength requested, just exit
        mov     ax, 04F06h      ; VESA Set logical scan line length
        mov     bl, 0			;
        int     10h             ; set VESA scan length

        cmp     ax, 0004Fh      ; Was it successful?
        jne     failed			;
    }

finished:
    return TRUE;

failed:
	return FALSE;
}

/* SetVideoMode: maps from the user input 0-X to a VESA mode
** User  VESA MODE
** Input
** 0	 320x200x256   default mode, should work with any video card with 64K memory
** 1     480x240x256   non-standard VGA resolution, emulated in a 640x480 window.
** 2	 640x480x256
** 3	 800x600x256
** 4	 1024x768x256
** 5	 320x240x256   non-standard VGA resolution, emulated in a 640x480 window.
** 6     208x240x256
*/

UCHAR SetVideoMode(int desiredMode)
{
    int		vesaMode = 0;
	int		scanLength;

	if(bNoModeSet)								/* if user requested to skip the mode set, just pass bootargs */
	{
		return	0xFF;							/* cause caller to leave bootargs vars alone */
	}

    if (desiredMode == 0)
    {
		/* In the default mode, there is no need to bank switch the card since only 64K required */
		/* VESA is NOT required for this mode. */
		goto defaultMode;
	}

	if (isVesaSupported())
	{
		/* Use VESA to put the video card into the appropriate mode */
		switch (desiredMode)
		{
		case 0x01:								/* 480x240x256 is emulated in a partial 640x480x256 screen	*/
		case 0x02:
		case 0x05:								/* 240x320x256 is emulated in a partial 640x480x256 screen	*/
		case 0x06:								/* 208x240x256 is emulated in a partial 640x480x256 screen	*/
			scanLength = VESASCANLENGTH1024;	/* scan length for this mode	*/
			vesaMode = VESAMODE640x480x256;		/* VESA Mode 101 - 640x480x256	*/
			break;

		case 0x03:
			scanLength = VESASCANLENGTH1024;	/* scan length for this mode	*/
			vesaMode = VESAMODE800x600x256;		/* VESA Mode 103 - 800x600x256	*/
			break;

		case 0x04:
			scanLength = VESASCANLENGTH1024;	/* scan length for this mode	*/
			vesaMode = VESAMODE1024x768x256;	/* VESA Mode 105 - 1024x768x256 */
			break;

		default:								/* otherwise VESA mode value was passed in - use directly */
			vesaMode = desiredMode;				/* use passed in mode value */
			vesaMode |= 0x4000;					/* ask for linear/flat framebuffer mode */
			scanLength = 0;						/* use mode default scan length */
			break;
		}

		/* OK, setup the video card */
		if (setVesaMode(vesaMode, scanLength))
		{
			return (UCHAR)(desiredMode < 0x100 ? desiredMode : 0xFF);	/* Successful setting of VESA mode */
		}
	}

defaultMode:
	mode320x200x256();
	return 0;
}

//
// FindClosestVESAMode - Finds VESA mode with X and Y size closest to requested screen size
// Returns flat framebuffer pointer, flat framebuffer stride, and physical X and Y size
//

void	FindClosestVESAMode (void)
{
	VESA_GENERAL_INFO	vesaInfo, far *pVesaInfo = &vesaInfo;
	VESA_MODE_INFO		modeInfo, far *pModeInfo = &modeInfo;
	DWORD				deltaX, deltaY;
	DWORD				currError, error;
	WORD				vesaMode;
	int					index;

	vesaInfo.szSignature[0] = 'V';
	vesaInfo.szSignature[1] = 'B';
	vesaInfo.szSignature[2] = 'E';
	vesaInfo.szSignature[3] = '2';

	__asm
    {
		push	es
        mov     ax, 04F00h      ; Get VESA info
        les     di, pVesaInfo   ; Pointer to info buffer
        int     10h             ; check for VESA
		pop		es

        cmp     ax, 0004Fh      ; Was it successful?
        je      itsok
		jmp		noVesa
    }

itsok:

	if (vesaInfo.wVersion < 0x0200)		// check for minimum compat version of VBE
	{
		goto	noVesa;
	}

	BootArgs.vesaMode = 0;
	currError = 0xFFFFFFFF;
	for (index = 0; vesaInfo.pModeList[index] != -1; index++)
	{
		vesaMode = vesaInfo.pModeList[index];
		__asm
		{
			push	es
			mov		cx, vesaMode
			les		di, pModeInfo   ; Pointer to info buffer
			mov		ax, 04F01h      ; Return VBE Mode Information
			int		10h
			pop		es
		}
		if (modeInfo.ucNumberOfPlanes == 1 && 						// must be a planer mode
			modeInfo.dwPhysBasePtr != 0 &&							// and be a flat frame buffer compatible mode
			modeInfo.ucBitsPerPixel == BootArgs.bppScreen &&		// and have matching color depth
			modeInfo.wXResolution >= BootArgs.cxDisplayScreen &&	// and be same size or bigger than requested
			modeInfo.wYResolution >= BootArgs.cyDisplayScreen)
		{
			deltaX = (DWORD)modeInfo.wXResolution - (DWORD)BootArgs.cxDisplayScreen;
			deltaY = (DWORD)modeInfo.wYResolution - (DWORD)BootArgs.cyDisplayScreen;
			error = ((deltaX * deltaX) + (deltaY * deltaY));
			if (error < currError)
			{
				currError = error;
				BootArgs.vesaMode = vesaMode;
				BootArgs.pvFlatFrameBuffer = modeInfo.dwPhysBasePtr;
				BootArgs.cxPhysicalScreen  = modeInfo.wXResolution;
				BootArgs.cyPhysicalScreen  = modeInfo.wYResolution;
				BootArgs.cbScanLineLength  = modeInfo.wBytesPerScanLine;
				BootArgs.RedMaskSize       = modeInfo.ucRedMaskSize;
				BootArgs.RedMaskPosition   = modeInfo.ucRedFieldPosition;
				BootArgs.GreenMaskSize     = modeInfo.ucGreenMaskSize;
				BootArgs.GreenMaskPosition = modeInfo.ucGreenFieldPosition;
				BootArgs.BlueMaskSize      = modeInfo.ucBlueMaskSize;
				BootArgs.BlueMaskPosition  = modeInfo.ucBlueFieldPosition;
			}
		}
	}

	if (BootArgs.vesaMode == 0)
	{
		goto	noVesa;
	}

	return;

noVesa:	// no matching VESA mode found, use 320x200x8 video mode as fallback
	BootArgs.vesaMode = 0;
}

//
// FindVESAMode - Finds VESA mode which exactly matches requested X and Y size
// Returns flat framebuffer pointer and flat framebuffer stride
void	FindVESAMode (void)
{
	VESA_GENERAL_INFO	vesaInfo, far *pVesaInfo = &vesaInfo;
	VESA_MODE_INFO		modeInfo, far *pModeInfo = &modeInfo;
	WORD				vesaMode;
	int					index;

	vesaInfo.szSignature[0] = 'V';
	vesaInfo.szSignature[1] = 'B';
	vesaInfo.szSignature[2] = 'E';
	vesaInfo.szSignature[3] = '2';

	__asm
    {
		push	es
        mov     ax, 04F00h      ; Get VESA info
        les     di, pVesaInfo   ; Pointer to info buffer
        int     10h             ; check for VESA
		pop		es

        cmp     ax, 0004Fh      ; Was it successful?
        je     	itsok
		jmp		noVesa
    }

itsok:

	if (vesaInfo.wVersion < 0x0200)		// check for minimum compat version of VBE
	{
		goto	noVesa;
	}

    BootArgs.vesaMode = 0;
	for (index = 0; vesaInfo.pModeList[index] != -1; index++)
	{
		vesaMode = vesaInfo.pModeList[index];
		__asm
		{
			push	es
			mov		cx, vesaMode
			les		di, pModeInfo   ; Pointer to info buffer
			mov		ax, 04F01h      ; Return VBE Mode Information
			int		10h
			pop		es
		}
		if (modeInfo.ucNumberOfPlanes == 1 && 						// must be a planer mode
			modeInfo.dwPhysBasePtr != 0 &&							// and be a flat frame buffer compatible mode
			modeInfo.ucBitsPerPixel == BootArgs.bppScreen &&		// and have matching color depth
			modeInfo.wXResolution == BootArgs.cxPhysicalScreen && 	// and be same size or bigger than requested
			modeInfo.wYResolution == BootArgs.cyPhysicalScreen)
		{
			BootArgs.vesaMode = vesaMode;
			BootArgs.pvFlatFrameBuffer = modeInfo.dwPhysBasePtr;
			BootArgs.cbScanLineLength  = modeInfo.wBytesPerScanLine;
			BootArgs.RedMaskSize       = modeInfo.ucRedMaskSize;
			BootArgs.RedMaskPosition   = modeInfo.ucRedFieldPosition;
			BootArgs.GreenMaskSize     = modeInfo.ucGreenMaskSize;
			BootArgs.GreenMaskPosition = modeInfo.ucGreenFieldPosition;
			BootArgs.BlueMaskSize      = modeInfo.ucBlueMaskSize;
			BootArgs.BlueMaskPosition  = modeInfo.ucBlueFieldPosition;
			return;
		}
	}

noVesa:	// no matching VESA mode found, use 320x200x8 video mode as fallback
	BootArgs.vesaMode = 0;
}

BOOL	ParseVESAOptions (char * params)
{
	int	cArgs;

	BootArgs.vesaMode = 0;

	if (params[2] != ':')
	{
		return	FALSE;		// must have a : following the /L
	}

	// Check for /L:N:xxx form of switch - this skips all of the VESA mode related stuff and skips the mode set as well
	if(memcmp (&params[3], "N:", 2) == 0 ||
	   memcmp (&params[3], "n:", 2) == 0)
	{
		bNoModeSet = TRUE;
		cArgs = sscanf (&params[5], "%dx%dx%d:%dx%d",
						&BootArgs.cxDisplayScreen,
						&BootArgs.cyDisplayScreen,
						&BootArgs.bppScreen,
						&BootArgs.cxPhysicalScreen,
						&BootArgs.cyPhysicalScreen);
		if(cArgs == 3)
		{
			BootArgs.cxPhysicalScreen = BootArgs.cxDisplayScreen;
			BootArgs.cyPhysicalScreen = BootArgs.cyDisplayScreen;
		}
		else if(cArgs == 5)
		{
			if (BootArgs.cxPhysicalScreen < BootArgs.cxDisplayScreen ||
				BootArgs.cyPhysicalScreen < BootArgs.cyDisplayScreen)
			{
				return	FALSE;		// physical screen size must be >= display screen size
			}
		}
		BootArgs.vesaMode = 0xffff;		// just some really large value
	}
	else	// not N: version of switch - do all the VESA mode related stuff and set the mode
	{
		bNoModeSet = FALSE;
		cArgs = sscanf (&params[3], "%dx%dx%d:%dx%d",
						&BootArgs.cxDisplayScreen,
						&BootArgs.cyDisplayScreen,
						&BootArgs.bppScreen,
						&BootArgs.cxPhysicalScreen,
						&BootArgs.cyPhysicalScreen);

		if (cArgs == 3)		// user didn't specify explicit physical size, find closest to displayed size
		{
			FindClosestVESAMode ();	// uses and fills in BootArgs values
		}
		else if (cArgs == 5)	// user did specify explicit physical size, find it
		{
			if (BootArgs.cxPhysicalScreen < BootArgs.cxDisplayScreen ||
				BootArgs.cyPhysicalScreen < BootArgs.cyDisplayScreen)
			{
				return	FALSE;		// physical screen size must be >= display screen size
			}
			FindVESAMode ();		// uses and fills in BootArgs values
		}
		else
		{
			return	FALSE;			// invalid number of params entered
		}
	}

	return	TRUE;		// normal return code
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -