📄 ddutil.cpp
字号:
#include "stdafx.h"
#include "ddraw.h"
#include "card.h"
LPDIRECTDRAW g_pDD;
LPDIRECTDRAWSURFACE g_pDDSPrimary;
LPDIRECTDRAWSURFACE g_pDDSOverlay;
DDOVERLAYFX g_OverlayFX; // DirectDraw overlay effects struct
int g_PrimeMode;
DDCOLORKEY g_ColorKey;
int g_InitScaleX=1000;
int g_InitScaleY=1000;
int g_ScaleX=1000;
int g_ScaleY=1000;
AVE2KLIB_DISPLAY_PARAMETER g_ParaPrimary, g_ParaOverlay;
enum {DD_RGB565=1, DD_RGB1555, DD_RGB24, DD_RGB32, DD_RGB8};
RECT g_rcSrc, g_rcDest;
int m_DDRAWValid=0;
BOOL bYUV=FALSE;
///////////DDRAW functions
void PrintDDrawError(HRESULT hResult)
{
if(hResult==DD_OK)
return;
char szBuffer[100];
switch(hResult)
{
case DDERR_NODIRECTDRAWHW:
sprintf(szBuffer, "DDERR_INCOMPATIBLEPRIMARY\n");
break ;
case DDERR_INVALIDPARAMS:
sprintf(szBuffer, "DDERR_INVALIDOBJECT\n");
break ;
case DDERR_INVALIDPIXELFORMAT:
sprintf(szBuffer, "DDERR_INVALIDPIXELFORMAT\n");
break;
case DDERR_NOALPHAHW :
sprintf(szBuffer, "DDERR_NOCOOPERATIVELEVELSET\n");
break;
case DDERR_INVALIDCAPS:
sprintf(szBuffer, "DDERR_INVALIDPARAMS\n");
break;
case DDERR_PRIMARYSURFACEALREADYEXISTS:
sprintf(szBuffer, "DDERR_INVALIDCAPS\n");
break;
case DDERR_NOOVERLAYHW:
sprintf(szBuffer, "DDERR_NOOVERLAYHW\n");
break;
case DDERR_OUTOFVIDEOMEMORY:
sprintf(szBuffer, "DDERR_OUTOFVIDEOMEMORY\n");
break;
case DDERR_TOOBIGWIDTH:
sprintf(szBuffer, "DDERR_TOOBIGWIDTH\n");
break;
case DDERR_TOOBIGSIZE:
sprintf(szBuffer, "DDERR_TOOBIGSIZE\n");
break;
case DDERR_NOCOLORKEYHW:
sprintf(szBuffer, "DDERR_NOCOLORKEYHW\n");
break;
default:
sprintf(szBuffer, "DDERR_UNKNOWN\n");
}
AfxMessageBox( szBuffer, MB_OK);
}
DWORD DDColorMatch(IDirectDrawSurface * pdds, COLORREF rgb)
{
COLORREF rgbT;
HDC hdc;
DWORD dw = CLR_INVALID;
DDSURFACEDESC ddsd;
HRESULT hres;
//
// Use GDI SetPixel to color match for us
//
if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
{
rgbT = GetPixel(hdc, 0, 0); // Save current pixel value
SetPixel(hdc, 0, 0, rgb); // Set our value
pdds->ReleaseDC(hdc);
}
//
// Now lock the surface so we can read back the converted color
//
ddsd.dwSize = sizeof(ddsd);
while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
;
if (hres == DD_OK)
{
dw = *(DWORD *) ddsd.lpSurface; // Get DWORD
if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1; // Mask it to bpp
//memset(ddsd.lpSurface, dw, 3200);
pdds->Unlock(NULL);
}
//
// Now put the color that was there back.
//
if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
{
SetPixel(hdc, 0, 0, rgbT);
pdds->ReleaseDC(hdc);
}
return dw;
}
//-----------------------------------------------------------------------------
// Name: DestroyOverlay()
// Desc: Releases the overlay surface
//-----------------------------------------------------------------------------
void
DestroyOverlay()
{
if (g_pDDSOverlay)
{
g_pDDSOverlay->Release();
g_pDDSOverlay = NULL;
}
}
//-----------------------------------------------------------------------------
// Name: DestroyPrimary()
// Desc: Releases the primary surface
//-----------------------------------------------------------------------------
void
DestroyPrimary()
{
if (g_pDDSPrimary)
{
g_pDDSPrimary->Release();
g_pDDSPrimary = NULL;
}
}
//-----------------------------------------------------------------------------
// Name: DestroyDDraw()
// Desc: Releases core DirectDraw objects
//-----------------------------------------------------------------------------
void
DestroyDDraw()
{
DestroyPrimary();
// Release the DDraw object
if (g_pDD)
{
g_pDD->Release();
g_pDD = NULL;
}
}
//-----------------------------------------------------------------------------
// Name: DDPrimaryInit()
// Desc: Init the primary surface
//-----------------------------------------------------------------------------
int
DDPrimaryInit()
{
HRESULT hRet;
DDSURFACEDESC ddsd; // A surface description structure
if(g_pDD==NULL)
return FALSE;
// Create the primary surface. The primary surface is the full screen -
// since we're a windowed app - we'll just write to the portion of the
// screen within our window.
memset(&ddsd, 0, sizeof(ddsd)); // Set all fields of struct to 0 and set .dwSize to
ddsd.dwSize = sizeof(ddsd); // Sizeof the variable - these two steps required for most DDraw structs
ddsd.dwFlags = DDSD_CAPS; // Set flags for variables we're using...
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // Set the variables we said we would in dwFlags
hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);
if (hRet != DD_OK)
return FALSE;
//detect g_PrimeMode
hRet = g_pDDSPrimary->GetSurfaceDesc(&ddsd);
if ( hRet != DD_OK )
{
g_pDD->Release();
MessageBox(0, "Failed to get surface desciption!", "Error", MB_OK);
return FALSE;
}
// check if it is RGB Format
// delete format check because I'm sure primary surface is RGB only
//if ( ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB )
//{
DWORD m_dwVGAPitch = (DWORD)ddsd.lPitch;
DWORD m_dwVGABitCount = ddsd.ddpfPixelFormat.dwRGBBitCount;
DWORD m_dwVGAPixelDepth = (ddsd.ddpfPixelFormat.dwRGBBitCount + 7) / 8;
g_ParaPrimary.Pitch = m_dwVGAPitch;
g_ParaPrimary.Depth = m_dwVGAPixelDepth;
g_ParaPrimary.Height = ddsd.dwHeight;
g_ParaPrimary.Width = ddsd.dwWidth;
if (ddsd.ddpfPixelFormat.dwRGBBitCount == 16)
{
if ((ddsd.ddpfPixelFormat.dwRBitMask == 0x7C00) &&
(ddsd.ddpfPixelFormat.dwGBitMask == 0x03E0) &&
(ddsd.ddpfPixelFormat.dwBBitMask == 0x001F))
{
m_dwVGABitCount = 15;
g_PrimeMode=DD_RGB1555;
}
else
g_PrimeMode=DD_RGB565;
}
else
if(ddsd.ddpfPixelFormat.dwRGBBitCount == 24)
g_PrimeMode=DD_RGB24;
else
if(ddsd.ddpfPixelFormat.dwRGBBitCount == 8)
g_PrimeMode=DD_RGB8;
else
g_PrimeMode=DD_RGB32;
g_ParaPrimary.BitCount=m_dwVGABitCount;
g_pDDSPrimary->Lock( NULL , &ddsd , 0 , NULL );
g_ParaPrimary.VirtualAddress = (DWORD)ddsd.lpSurface;
g_pDDSPrimary->Unlock( NULL );
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: DDOverlayInit()
// Desc: Setup the overlay object
//-----------------------------------------------------------------------------
int
DDOverlayInit()
{
DDSURFACEDESC ddsd; // DirectDraw surface descriptor
HRESULT hRet; // I'm not even going to try...
int nTestPass=0;
DDPIXELFORMAT ddpfOverlayFormat =
// The pixel format that we want the surface to be in
{
sizeof(DDPIXELFORMAT),
DDPF_RGB,
0, 16,
0xf800, 0x07e0, 0x001F, // 16 bit RGB 5:6:5
//0x7c00, 0x03e0, 0x001F, // 16 bit RGB 1:5:5:5
0
};
//return FALSE;
// Setup the overlay surface's attributes in the surface descriptor
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.dwBackBufferCount = 0;
ddsd.dwWidth = (g_ParaPrimary.Width*1000)/g_InitScaleX;
ddsd.dwHeight = (g_ParaPrimary.Height*1000)/g_InitScaleY;
//ddsd.ddpfPixelFormat = ddpfOverlayFormat; // Use 16 bit RGB 5:6:5 pixel format
ddsd.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
ddsd.ddpfPixelFormat.dwFourCC = 0x32595559L; // YUY2
RECREATE:
// Attempt to create the surface with theses settings
hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSOverlay, NULL);
//PrintDDrawError(hRet);
if (hRet != DD_OK){
switch(nTestPass){
case 0:
ddsd.ddpfPixelFormat.dwFourCC = 0x59565955L; // YUYV
nTestPass++;
goto RECREATE;
case 1:
ddsd.ddpfPixelFormat = ddpfOverlayFormat;
nTestPass++;
goto RECREATE;
case 2:
ddpfOverlayFormat.dwRBitMask=0x7c00;
ddpfOverlayFormat.dwGBitMask=0x3e0;
ddpfOverlayFormat.dwBBitMask=0x001f;
ddsd.ddpfPixelFormat = ddpfOverlayFormat;
nTestPass++;
goto RECREATE;
case 3:
return FALSE;
}
}
switch(nTestPass){
case 0:
g_ParaOverlay.BitCount=0x80000000|15;
break;
case 1:
g_ParaOverlay.BitCount=0x80000000|16;
break;
case 2:
g_ParaOverlay.BitCount=16;
break;
case 3:
g_ParaOverlay.BitCount=15;
break;
}
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwFlags=DDSD_ALL;
ddsd.dwSize=sizeof(ddsd);
hRet = g_pDDSOverlay->GetSurfaceDesc(&ddsd);
DWORD m_dwVGAPitch = (DWORD)ddsd.lPitch;
DWORD m_dwVGABitCount = ddsd.ddpfPixelFormat.dwYUVBitCount;
DWORD m_dwVGAPixelDepth = (ddsd.ddpfPixelFormat.dwYUVBitCount + 7) / 8;
g_ParaOverlay.Pitch = m_dwVGAPitch;
g_ParaOverlay.Depth = m_dwVGAPixelDepth;
if(g_ParaOverlay.Depth==0)
g_ParaOverlay.Depth=((g_ParaOverlay.BitCount&0xff)+7)/8;
g_ParaOverlay.Height = ddsd.dwHeight;
g_ParaOverlay.Width = ddsd.dwWidth;
g_pDDSOverlay->Lock( NULL , &ddsd , 0 , NULL );
g_ParaOverlay.VirtualAddress = (DWORD)ddsd.lpSurface;
PULONG pDest=(PULONG)ddsd.lpSurface;
memset(pDest, 0, ddsd.dwHeight*ddsd.dwWidth*m_dwVGAPixelDepth);
g_pDDSOverlay->Unlock( NULL );
g_ColorKey.dwColorSpaceHighValue=DDColorMatch(g_pDDSPrimary, RGB(255,0,255));
g_ColorKey.dwColorSpaceLowValue = g_ColorKey.dwColorSpaceHighValue;
g_pDDSOverlay->SetColorKey(DDCKEY_DESTOVERLAY, &g_ColorKey);
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: DDInit()
// Desc: Init DirectDraw Stuff
//-----------------------------------------------------------------------------
int
DDInit()
{
HRESULT hRet;
//hRet = DirectDrawCreateEx(NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL);
hRet = DirectDrawCreate(NULL, &g_pDD, NULL);
if (hRet != DD_OK)
return FALSE;
// Set cooperation level with other windows to be normal (ie. not full screen)
// You MUST set the cooperation level to be SOMETHING, for windowed apps use
// DDSCL_NORMAL, for full screen use: DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN.
hRet = g_pDD->SetCooperativeLevel(0/*g_hAppWnd*/, DDSCL_NORMAL);
if (hRet != DD_OK)
return FALSE;
if (!DDPrimaryInit())
return FALSE;
return TRUE;
}
int
DDUpdate()
{
HRESULT hRet;
// Check the primary surface to see if it's lost - if so you can
// pretty much bet that the other surfaces are also lost - thus
// restore EVERYTHING! If we got our surfaces stolen by a full
// screen app - then we'll destroy our primary - and won't be able
// to initialize it again. When we get our next paint message (the
// full screen app closed for example) we'll want to try to reinit
// the surfaces again - that's why there is a check for
// g_pDDSPrimary == NULL. The other option, is that our program
// went through this process, could init the primary again, but it
// couldn't init the overlay, that's why there's a third check for
// g_pDDSOverlay == NULL. Make sure that the check for
// !g_pDDSPrimary is BEFORE the IsLost call - that way if the
// pointer is NULL (ie. !g_pDDSPrimary is TRUE) - the compiler
// won't try to evaluate the IsLost function (which, since the
// g_pDDSPrimary surface is NULL, would be bad...).
if (!g_pDDSPrimary || (g_pDDSPrimary->IsLost() != DD_OK) ||
(g_pDDSOverlay == NULL))
{
DestroyOverlay();
DestroyPrimary();
if (DDPrimaryInit())
if (!DDOverlayInit())
return FALSE;
//if (!DrawOverlay())
// DestroyOverlay();
}
//PrintDDrawError(hRet);
if (g_pDDSOverlay && g_pDDSPrimary)
hRet = g_pDDSOverlay->UpdateOverlay(NULL, g_pDDSPrimary,
NULL, DDOVER_SHOW,
NULL);
memset(&g_OverlayFX, 0, sizeof(g_OverlayFX));
g_OverlayFX.dwSize = sizeof(g_OverlayFX);
g_OverlayFX.dckDestColorkey = g_ColorKey;
// UpdateOverlay is how we put the overlay on the screen.
if (g_pDDSOverlay && g_pDDSPrimary)
hRet = g_pDDSOverlay->UpdateOverlay(&g_rcSrc, g_pDDSPrimary,
&g_rcDest, DDOVER_SHOW|DDOVER_DDFX|DDOVER_KEYDESTOVERRIDE,
&g_OverlayFX);
return TRUE;
}
int UpdateScreen()
{
if(!g_pDDSOverlay)
return FALSE;
//if(!bFullScreen){
g_rcDest.left=0;
g_rcDest.right=g_ParaPrimary.Width;
g_rcDest.top=0;
g_rcDest.bottom=g_ParaPrimary.Height;
//if(bFullScreen)
g_rcSrc.left=0;
g_rcSrc.right=(g_ParaOverlay.Width*g_InitScaleX)/g_ScaleX;
g_rcSrc.top=0;
g_rcSrc.bottom=(g_ParaOverlay.Height*g_InitScaleY)/g_ScaleY;
//}
return DDUpdate();
}
BOOL PrepareScreen(
int *pMode
)
{
if(g_pDDSPrimary)
//forbid to call this function more than once
return FALSE;
g_pDDSPrimary=NULL;
if (DDInit() == FALSE)
{
DestroyDDraw();
//DisplayError("Unable to initialize the DirectDraw object");
*pMode=AVE2KLIB_SCREEN_NONE;
return FALSE;
}
g_pDDSOverlay=NULL;
//if(*pMode!=AVE2KLIB_SCREEN_PRIMARY)
if (DDOverlayInit() == FALSE)
{
DestroyOverlay();
//DestroyDDraw();
//DisplayError("Could not create the overlay surface. The display card may not support the requested format, or may not have enough memory available.");
}
if(g_pDDSOverlay){
*pMode=AVE2KLIB_SCREEN_OVERLAY;
UpdateScreen();
}
else{
*pMode=AVE2KLIB_SCREEN_PRIMARY;
}
return 1;
}
int ReleaseScreen(
)
{
DestroyOverlay();
DestroyDDraw();
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -