wrap2bpp.cpp

来自「老外的一个开源项目」· C++ 代码 · 共 406 行

CPP
406
字号
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
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.

Module Name:  

Abstract:  
  
Functions:


Notes: 


--*/

#include "precomp.h"

#define PALETTE_SIZE              	4
RGBQUAD _rgb2bpp[PALETTE_SIZE] =
{
    { 0x00, 0x00, 0x00, 0 },    /*   0 */	/* Black        */   	   \
    { 0x80, 0x80, 0x80, 0 },    /* 248 */	/* Dark Grey         	*/ \
    { 0xc0, 0xc0, 0xc0, 0 },    /*   7 */	/* Light Grey   */   	   \
    { 0xff, 0xff, 0xff, 0 }     /* 255 */	/* White         		*/ \
};


INSTANTIATE_GPE_ZONES(0x3,"MGDI Driver","unused1","unused2")	 /* Start with Errors, warnings, and temporary messages */

BOOL APIENTRY GPEEnableDriver(          // This gets around problems exporting from .lib
	ULONG          iEngineVersion,
	ULONG          cj,
	DRVENABLEDATA *pded,
	PENGCALLBACKS  pEngCallbacks);
BOOL APIENTRY DrvEnableDriver(
	ULONG          iEngineVersion,
	ULONG          cj,
	DRVENABLEDATA *pded,
	PENGCALLBACKS  pEngCallbacks)
{
	return GPEEnableDriver( iEngineVersion, cj, pded, pEngCallbacks );
}


static GPE *pGPE = (GPE *)NULL;
// Main entry point for a GPE-compliant driver
GPE *GetGPE()
{
	if( !pGPE )
		pGPE = new Wrap2bpp();
	return pGPE;
}


Wrap2bpp::Wrap2bpp()
{
	DEBUGMSG( GPE_ZONE_INIT,(TEXT("Wrap2bpp::Wrap2bpp\r\n")));

	DispDrvrInitialize();	// call entry point to 2bpp GDI driver
	
	// When this DispDrvrInitialize returns, DispDrvrPhysicalFrameBuffer contains
	// the physical address of the screen if it is in 2bpp DIB format. - Alternatively it
	// is NULL - in which case this is a "dirty-rect" driver

	m_ModeInfo.modeId = 0;
	m_ModeInfo.width = m_nScreenWidth = DispDrvr_cxScreen;
	m_ModeInfo.height = m_nScreenHeight = DispDrvr_cyScreen;
	m_ModeInfo.Bpp = 2;
	m_ModeInfo.frequency = 60;		// not too important
	m_ModeInfo.format = gpe2Bpp;

	m_pMode = &m_ModeInfo;
	
	if( DispDrvrPhysicalFrameBuffer == NULL )
	{
		// it is a "dirty-rect" driver - we create a system memory bitmap to represent
		// the screen and refresh rectangles of this to the screen as they are altered
		m_pPrimarySurface = new GPESurf( m_nScreenWidth, m_nScreenHeight, gpe2Bpp );
		if (!m_pPrimarySurface)
		{
		    RETAILMSG(1, (TEXT("Wrap2bpp::Wrap2bpp: Error allocating GPESurf.\r\n")));
		    return;

		}

		DispDrvrSetDibBuffer( m_pPrimarySurface->Buffer() );
	}
	else
	{
		// The hardware is arranged as a DIB
		// Map it into virtual addr space
		unsigned long fbSize = DispDrvr_cxScreen * DispDrvr_cdwStride / 4;
		m_pVirtualFrameBuffer = VirtualAlloc( 0, fbSize, MEM_RESERVE, PAGE_NOACCESS );
		VirtualCopy( m_pVirtualFrameBuffer, DispDrvrPhysicalFrameBuffer, fbSize,
			PAGE_READWRITE | PAGE_NOCACHE );
			
		m_pPrimarySurface = new GPESurf( m_nScreenWidth, m_nScreenHeight, m_pVirtualFrameBuffer,
			 DispDrvr_cdwStride / 4, gpe2Bpp );
	}
}

SCODE Wrap2bpp::SetMode( int modeId, HPALETTE *pPalette )
{
	if( modeId != 0 )
		return E_INVALIDARG;

	// Here, we use EngCreatePalette to create a palette that that MGDI will use as a
	// stock palette

	DEBUGMSG(1,(TEXT("SetMode - creating stock palette\r\n")));

	if( pPalette )
	{
		*pPalette = EngCreatePalette
							(
								PAL_INDEXED,
								PALETTE_SIZE, 	// i.e. 2
								(ULONG *)_rgb2bpp,
								0,
								0,
								0
							);
//		DEBUGMSG(1,(TEXT("Created 2 Bpp palette, handle = 0x%08x\r\n"),*pPalette));
	}

	DEBUGMSG(1,(TEXT("SetMode done\r\n")));

	return S_OK;				// Mode is inherently set
}

SCODE Wrap2bpp::GetModeInfo
(
	GPEMode *pMode,
	int modeNo
)
{
	if( modeNo != 0 )
		return E_INVALIDARG;

	*pMode = m_ModeInfo;

	return S_OK;
}

int Wrap2bpp::NumModes()
{
	return 1;
}

SCODE Wrap2bpp::SetPointerShape(
	GPESurf *pMask,
	GPESurf *pColorSurf,
	int xHot,
	int yHot,
	int cx,
	int cy )
{
	return S_OK;
}

SCODE Wrap2bpp::MovePointer(
	int x,
	int y )
{
	DEBUGMSG(GPE_ZONE_HW,(TEXT("Moving cursor to %d,%d\r\n"), x, y ));
	if( x == -1 )
	{
		DispDrvrMoveCursor( DispDrvr_cxScreen, DispDrvr_cyScreen );		// disable cursor
	}
	{
		DispDrvrMoveCursor( x, y );		// disable cursor
	}
	return S_OK;
}

void Wrap2bpp::WaitForNotBusy()
{
	return;
}

int Wrap2bpp::IsBusy()
{
	return 0;	// Never busy as there is no acceleration
}

void Wrap2bpp::GetPhysicalVideoMemory
(
	unsigned long *pPhysicalMemoryBase,
	unsigned long *pVideoMemorySize
)
{
	*pPhysicalMemoryBase = (unsigned long)DispDrvrPhysicalFrameBuffer;
	*pVideoMemorySize = DispDrvr_cdwStride * DispDrvr_cyScreen / 4;
}


SCODE Wrap2bpp::AllocSurface(
	GPESurf **ppSurf,
	int width,
	int height,
	EGPEFormat format,
	int surfaceFlags )
{
	if( surfaceFlags & GPE_REQUIRE_VIDEO_MEMORY )
		return E_OUTOFMEMORY;	// Can't allocate video-memory surfaces in the Wrap2bpp environment
	// Allocate from system memory
	DEBUGMSG(GPE_ZONE_CREATE,(TEXT("Creating a GPESurf in system memory. EGPEFormat = %d\r\n"), (int)format ));
	*ppSurf = new GPESurf( width, height, format );
	if( *ppSurf )
	{
		// check we allocated bits succesfully
		if( !((*ppSurf)->Buffer()) )
			delete *ppSurf;	// and then return E_OUTOFMEMORY
		else
			return S_OK;
	}
	return E_OUTOFMEMORY;
}

SCODE Wrap2bpp::WrappedEmulatedLine( GPELineParms *pParms )
{
	SCODE sc = EmulatedLine( pParms );	// Draw to the backup framebuffer

	if( FAILED(sc) )
		return sc;

	// Now, calculate the dirty-rect to refresh to the actual hardware
	RECT bounds;

	int N_plus_1;			// Minor length of bounding rect + 1

	if( pParms->dN )	// The line has a diagonal component (we'll refresh the bounding rect)
		N_plus_1 = 1 + ( ( pParms->cPels * pParms->dN ) / pParms->dM );
	else
		N_plus_1 = 1;

	switch( pParms->iDir )
	{
		case 0:
			bounds.left = pParms->xStart;
			bounds.top = pParms->yStart;
			bounds.right = pParms->xStart + pParms->cPels + 1;
			bounds.bottom = bounds.top + N_plus_1;
			break;
		case 1:
			bounds.left = pParms->xStart;
			bounds.top = pParms->yStart;
			bounds.bottom = pParms->yStart + pParms->cPels + 1;
			bounds.right = bounds.left + N_plus_1;
			break;
		case 2:
			bounds.right = pParms->xStart + 1;
			bounds.top = pParms->yStart;
			bounds.bottom = pParms->yStart + pParms->cPels + 1;
			bounds.left = bounds.right - N_plus_1;
			break;
		case 3:
			bounds.right = pParms->xStart + 1;
			bounds.top = pParms->yStart;
			bounds.left = pParms->xStart - pParms->cPels;
			bounds.bottom = bounds.top + N_plus_1;
			break;
		case 4:
			bounds.right = pParms->xStart + 1;
			bounds.bottom = pParms->yStart + 1;
			bounds.left = pParms->xStart - pParms->cPels;
			bounds.top = bounds.bottom - N_plus_1;
			break;
		case 5:
			bounds.right = pParms->xStart + 1;
			bounds.bottom = pParms->yStart + 1;
			bounds.top = pParms->yStart - pParms->cPels;
			bounds.left = bounds.right - N_plus_1;
			break;
		case 6:
			bounds.left = pParms->xStart;
			bounds.bottom = pParms->yStart + 1;
			bounds.top = pParms->yStart - pParms->cPels;
			bounds.right = bounds.left + N_plus_1;
			break;
		case 7:
			bounds.left = pParms->xStart;
			bounds.bottom = pParms->yStart + 1;
			bounds.right = pParms->xStart + pParms->cPels + 1;
			bounds.top = bounds.bottom - N_plus_1;
			break;
		default:
			DEBUGMSG(GPE_ZONE_ERROR,(TEXT("Invalid direction: %d\r\n"),pParms->iDir));
			return E_INVALIDARG;
	}

	DispDrvrDirtyRectDump( (LPRECT)&bounds );

	return sc;
}
   
			  
SCODE Wrap2bpp::Line(
	GPELineParms *pLineParms,
	EGPEPhase phase )
{
	DEBUGMSG(GPE_ZONE_LINE,(TEXT("Wrap2bpp::Line\r\n")));

	if( phase == gpeSingle || phase == gpePrepare )
	{
		if( ( pLineParms->pDst != m_pPrimarySurface ) || ( DispDrvrPhysicalFrameBuffer != NULL ) )
			pLineParms->pLine = EmulatedLine;
		else
			pLineParms->pLine = (SCODE (GPE::*)(struct GPELineParms *))WrappedEmulatedLine;
	}
	return S_OK;
}

#undef SWAP
#define SWAP(type,a,b) { type tmp; tmp=a; a=b; b=tmp; }

SCODE Wrap2bpp::WrappedEmulatedBlt( GPEBltParms *pParms )
{
	SCODE sc = EmulatedBlt( pParms );	// Draw to the backup framebuffer

	if( FAILED(sc) )
		return sc;

	// Now, calculate the dirty-rect to refresh to the actual hardware
	RECT bounds;

	bounds.left = pParms->prclDst->left;
	bounds.top = pParms->prclDst->top;
	bounds.right = pParms->prclDst->right;
	bounds.bottom = pParms->prclDst->bottom;

	if( bounds.left > bounds.right )
	{
		SWAP( int, bounds.left, bounds.right )
	}
	if( bounds.top > bounds.bottom )
	{
		SWAP( int, bounds.top, bounds.bottom )
	}

	DispDrvrDirtyRectDump( (LPRECT)&bounds );

	return sc;
}


SCODE Wrap2bpp::BltPrepare(
	GPEBltParms *pBltParms )
{
	DEBUGMSG(GPE_ZONE_LINE,(TEXT("Wrap2bpp::BltPrepare\r\n")));

	if( ( pBltParms->pDst != m_pPrimarySurface ) || ( DispDrvrPhysicalFrameBuffer != NULL ) )
		pBltParms->pBlt = EmulatedBlt;
	else
		pBltParms->pBlt = (SCODE (GPE::*)(struct GPEBltParms *))WrappedEmulatedBlt;

	return S_OK;
}

// This function would be used to undo the setting of clip registers etc
SCODE Wrap2bpp::BltComplete( GPEBltParms *pBltParms )
{
	return S_OK;
}

int Wrap2bpp::InVBlank()
{
	return 0;
}

SCODE Wrap2bpp::SetPalette
(
	const PALETTEENTRY *src,
	unsigned short firstEntry,
	unsigned short numEntries
)
{
	return S_OK;
}

void RegisterDDHALAPI()
{
	;	// No DDHAL support in 2bpp wrapper
}

ulong BitMasks[] = { 0x0001,0x0002,0x0000 };

ULONG *APIENTRY DrvGetMasks(
    DHPDEV     dhpdev)
{
	return BitMasks;
}

⌨️ 快捷键说明

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