📄 directdraw.cpp
字号:
// 嫤挷儌乕僪
if( m_lpDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ) != DD_OK )
throw "CDirectDraw:SetCooperativeLevel failed.";
// 僾儔僀儅儕僒乕僼僃僗
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if( m_lpDD->CreateSurface( &ddsd, &m_lpDDPrimary, NULL ) != DD_OK )
throw "CDirectDraw:CreateSurface failed.";
// 僋儕僢僷乕偺嶌惉
if( m_lpDD->CreateClipper( 0, &m_lpDDClipper, NULL ) != DD_OK )
throw "CDirectDraw:CreateClipper failed.";
m_lpDDClipper->SetHWnd( 0, m_hWnd );
m_lpDDPrimary->SetClipper( m_lpDDClipper );
RELEASE( m_lpDDClipper );
} else {
// 僼儖僗僋儕乕儞
// 攔懠儌乕僪
if( m_lpDD->SetCooperativeLevel( m_hWnd, DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ) != DD_OK )
throw "CDirectDraw:SetCooperativeLevel error";
// 夋柺夝憸搙偺愝掕
if( m_lpDD->SetDisplayMode( m_dwDisplayWidth, m_dwDisplayHeight,
m_dwDisplayDepth, m_dwDisplayRate,
DDSDM_STANDARDVGAMODE ) != DD_OK ) {
// 幐攕偟偨傜儕僼儗僢僔儏儗乕僩巜掕傪柍偔偟偰傕偆堦搙傗偭偰傒傞
if( m_lpDD->SetDisplayMode( m_dwDisplayWidth, m_dwDisplayHeight,
m_dwDisplayDepth, 0,
DDSDM_STANDARDVGAMODE ) != DD_OK ) {
throw "CDirectDraw:SetDisplayMode failed.";
} else {
m_dwDisplayRate = 0;
}
}
// 僾儔僀儅儕僒乕僼僃僗偲僶僢僋僒乕僼僃僗偺嶌惉
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDPrimary, NULL) != DD_OK )
throw "CDirectDraw:CreateSurface failed.";
ZEROMEMORY( &ddscaps, sizeof(DDSCAPS2) );
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
if( m_lpDDPrimary->GetAttachedSurface(&ddscaps, &m_lpDDBack) != DD_OK )
throw "CDirectDraw:GetAttachedSurface failed.";
}
// offscreen surface
m_bForceWrite = FALSE;
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
if( !m_bSystemMemory ) {
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
} else {
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
m_bForceWrite = TRUE; // 懡抜儗儞僟儕儞僌偟側偄
}
ddsd.dwWidth = SCREEN_WIDTH*2;
ddsd.dwHeight = SCREEN_HEIGHT*2;
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDRender, NULL) != DD_OK ) {
// 僔僗僥儉儊儌儕偵傕庢傟側偄偭偰偐....
if( ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
throw "CDirectDraw:CreateSurface failed.";
// 價僨僆儊儌儕偵庢傟側偄帪丆偟傚偆偑側偄偺偱僔僗僥儉儊儌儕偵庢傞
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDRender, NULL) != DD_OK )
throw "CDirectDraw:CreateSurface failed.";
m_bForceWrite = TRUE; // 懡抜儗儞僟儕儞僌偟側偄
}
if( !m_bSystemMemory ) {
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
} else {
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
}
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDRender2, NULL) != DD_OK ) {
// 僔僗僥儉儊儌儕偵傕庢傟側偄偭偰偐....
if( ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
throw "CDirectDraw:CreateSurface failed.";
// 價僨僆儊儌儕偵庢傟側偄帪丆偟傚偆偑側偄偺偱僔僗僥儉儊儌儕偵庢傞
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDRender2, NULL) != DD_OK )
throw "CDirectDraw:CreateSurface failed.";
}
typedef struct tagDDRGNDATA {
RGNDATAHEADER rdh;
RECT rect[8];
} DDRGNDATA;
DDRGNDATA rgn;
rgn.rdh.dwSize = sizeof(RGNDATAHEADER);
rgn.rdh.iType = RDH_RECTANGLES;
rgn.rdh.nCount = 1;
rgn.rdh.nRgnSize = sizeof(RECT);
rgn.rdh.rcBound.left = 0;
rgn.rdh.rcBound.top = 0;
rgn.rdh.rcBound.right = ddsd.dwWidth;
rgn.rdh.rcBound.bottom = ddsd.dwHeight;
rgn.rect[0].left = 0;
rgn.rect[0].top = 0;
rgn.rect[0].right = ddsd.dwWidth;
rgn.rect[0].bottom = ddsd.dwHeight;
// Rendering surface clipper
if( m_lpDD->CreateClipper( 0, &m_lpDDClipper2, NULL ) != DD_OK )
throw "CDirectDraw:CreateClipper failed.";
m_lpDDClipper2->SetClipList( (LPRGNDATA)&rgn, 0 );
m_lpDDRender->SetClipper( m_lpDDClipper2 );
// Ascii surface(6x6x64character)
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
// ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = 6*8;
ddsd.dwHeight = 6*8;
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDAscii, NULL) != DD_OK )
throw "CDirectDraw:CreateSurface failed.";
// Color key
DDCOLORKEY ddck;
ZEROMEMORY( &ddck, sizeof(DDCOLORKEY) );
ddck.dwColorSpaceLowValue = 0;
ddck.dwColorSpaceHighValue = 0;
m_lpDDAscii->SetColorKey( DDCKEY_SRCBLT, &ddck );
// Zapper surface
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
// ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = 16;
ddsd.dwHeight = 16;
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDZapper, NULL) != DD_OK )
throw "CDirectDraw:CreateSurface failed.";
// Color key
ZEROMEMORY( &ddck, sizeof(DDCOLORKEY) );
ddck.dwColorSpaceLowValue = 0;
ddck.dwColorSpaceHighValue = 0;
m_lpDDZapper->SetColorKey( DDCKEY_SRCBLT, &ddck );
// TV
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
if( !m_bSystemMemory ) {
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
} else {
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
}
ddsd.dwWidth = 512;
ddsd.dwHeight = 480;
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDTV, NULL) != DD_OK ) {
// 僔僗僥儉儊儌儕偵傕庢傟側偄偭偰偐....
if( ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
throw "CDirectDraw:CreateSurface failed.";
// 價僨僆儊儌儕偵庢傟側偄帪丆偟傚偆偑側偄偺偱僔僗僥儉儊儌儕偵庢傞
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDTV, NULL) != DD_OK )
throw "CDirectDraw:CreateSurface failed.";
}
// Color key
ZEROMEMORY( &ddck, sizeof(DDCOLORKEY) );
ddck.dwColorSpaceLowValue = 0;
ddck.dwColorSpaceHighValue = 0;
m_lpDDTV->SetColorKey( DDCKEY_SRCBLT, &ddck );
// DirectDraw/GDI Palette
ZEROMEMORY( &m_logPalette, sizeof(m_logPalette) );
m_logPalette.palVersion = 0x0300;
m_logPalette.palNumEntries = 256;
HDC hdc = ::GetDC( NULL );
GetSystemPaletteEntries( hdc, 0, 256, m_logPalette.pe );
ReleaseDC( NULL, hdc );
for( i = 0; i < 10; i++ ) {
m_logPalette.pe[i ].peFlags = PC_EXPLICIT;
m_logPalette.pe[i+246].peFlags = PC_EXPLICIT;
}
for( i = 10; i < 246; i++ ) {
m_logPalette.pe[i].peRed = 0;
m_logPalette.pe[i].peGreen = 0;
m_logPalette.pe[i].peBlue = 0;
if( i >= 0x10 && i < 0x20 ) {
m_logPalette.pe[i].peRed = (i-0x10)*0x10;
m_logPalette.pe[i].peGreen = (i-0x10)*0x10;
m_logPalette.pe[i].peBlue = (i-0x10)*0x10;
m_logPalette.pe[i].peFlags = PC_RESERVED;
} else if( i >= 0x40 && i < 0xC0 ) {
m_logPalette.pe[i].peFlags = PC_RESERVED;
} else {
m_logPalette.pe[i].peFlags = PC_NOCOLLAPSE;
}
}
// Surface clear
ddbltfx.dwSize = sizeof(DDBLTFX);
ddbltfx.dwFillColor = 0;
if( m_lpDDBack ) {
m_lpDDBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
}
m_lpDDRender->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
m_lpDDRender2->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
// Palette object
DDSURFACEDESC2 ddsd;
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
m_lpDDPrimary->GetSurfaceDesc(&ddsd);
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
if( !m_bScreenMode ) {
if( (m_hPalette = CreatePalette( (LOGPALETTE *)&m_logPalette )) == NULL )
throw "CDirectDraw:CreatePalette failed.";
} else {
if( m_lpDD->CreatePalette( DDPCAPS_8BIT, m_logPalette.pe, &m_lpDDPalette, NULL ) != DD_OK )
throw "CDirectDraw:CreatePalette error";
if( m_lpDDPrimary->SetPalette( m_lpDDPalette ) != DD_OK )
throw "CDirectDraw:SetPalette failed.";
}
}
// Palette calculate
CalcPaletteTable();
// Palette Realize
RealizePalette();
m_bPaletteUpdate = TRUE;
// Character setup
SetLZSSChar( lzAscii, m_lpDDAscii );
SetLZSSChar( lzSight, m_lpDDZapper );
SetLZSSChar( lzTVlayer, m_lpDDTV );
// 嵞昤夋偺堊
m_bDeltaUpdate = TRUE;
} catch( char *str ) {
ReleaseSurface();
// DEBUGOUT( "%s\n", str );
::MessageBox( m_hWnd, str, "ERROR", MB_ICONERROR|MB_OK );
return FALSE;
}
// DEBUGOUT( "CDirectDraw:InitialSurface complete.\n" );
return TRUE;
}
// 僒乕僼僃僗偺奐曻
BOOL CDirectDraw::ReleaseSurface( void )
{
if( !m_lpDD )
return FALSE;
GDIDELETE( m_hPalette );
RELEASE( m_lpDDPalette );
RELEASE( m_lpDDClipper2 );
RELEASE( m_lpDDClipper );
RELEASE( m_lpDDTV );
RELEASE( m_lpDDZapper );
RELEASE( m_lpDDAscii );
RELEASE( m_lpDDRender2 );
RELEASE( m_lpDDRender );
RELEASE( m_lpDDBack );
RELEASE( m_lpDDPrimary );
return TRUE;
}
// 僒乕僼僃僗偺儕僗僩傾僒僽
BOOL CDirectDraw::RestoreSurfaceSub( LPDIRECTDRAWSURFACE7 lpSurface )
{
if( lpSurface ) {
if( lpSurface->IsLost() == DDERR_SURFACELOST ) {
// 儘僗僩偟偰偄偨傜儕僗僩傾偡傞
// DEBUGOUT( "CDirectDraw:Restore surface...." );
if( lpSurface->Restore() == DD_OK ) {
// DEBUGOUT( "Ok.\n" );
} else {
// DEBUGOUT( "Failed.\n" );
}
return FALSE;
}
}
return TRUE;
}
// 僒乕僼僃僗偺儕僗僩傾
BOOL CDirectDraw::RestoreSurface()
{
if( !m_lpDD ) return FALSE;
if( m_bNoRestore )
return FALSE;
BOOL bRet = TRUE;
// 儘僗僩偟偰偨傜撪梕偼幐傢傟偰偄傞偺偱昤夋傪僉儍儞僙儖偟偰偹
if( !RestoreSurfaceSub( m_lpDDRender ) ) {
bRet = FALSE;
}
if( !RestoreSurfaceSub( m_lpDDRender2 ) ) {
bRet = FALSE;
}
if( !RestoreSurfaceSub( m_lpDDBack ) ) {
bRet = FALSE;
}
if( !RestoreSurfaceSub( m_lpDDPrimary ) ) {
bRet = FALSE;
}
if( !RestoreSurfaceSub( m_lpDDAscii ) ) {
SetLZSSChar( lzAscii, m_lpDDAscii );
bRet = FALSE;
}
if( !RestoreSurfaceSub( m_lpDDZapper ) ) {
SetLZSSChar( lzSight, m_lpDDZapper );
bRet = FALSE;
}
if( !RestoreSurfaceSub( m_lpDDTV ) ) {
SetLZSSChar( lzTVlayer, m_lpDDTV );
bRet = FALSE;
}
if( !bRet ) {
// 嵞昤夋偺堊
m_bDeltaUpdate = TRUE;
}
return bRet;
}
//
// 僨傿僗僾儗僀儌乕僪曄峏奐巒
//
BOOL CDirectDraw::BeginDisplayChange()
{
if( !m_lpDD )
return FALSE;
// 婛偵曄峏拞傗側偄偐
if( m_bChangeMode )
return FALSE;
// 曄峏拞偠傖
m_bChangeMode = TRUE;
if( m_bScreenMode ) {
m_lpDD->RestoreDisplayMode();
}
// 僒乕僼僃僗偺奐曻
ReleaseSurface();
// 嫤挷儌乕僪
m_lpDD->SetCooperativeLevel( NULL, DDSCL_NORMAL );
return TRUE;
}
//
// 僨傿僗僾儗僀儌乕僪曄峏廔椆偲僒乕僼僃僗偺嵞峔抸
//
BOOL CDirectDraw::EndDisplayChange()
{
if( !m_lpDD || !m_bChangeMode )
return FALSE;
// Rebuild surface
if( !InitialSurface( m_bScreenMode ) ) {
m_bChangeMode = FALSE;
return FALSE;
}
// Wait
::Sleep( 250 );
// Change mode complete
m_bChangeMode = FALSE;
return TRUE;
}
//
// WM_DISPLAYCHANGE僴儞僪儔偐傜屇偽傟傞
//
BOOL CDirectDraw::OnChangeDisplayMode()
{
// 帺暘帺恎偱曄峏偟偰偄傞帪偼僉儍儞僙儖
if( m_bChangeMode )
return TRUE;
// DirectDraw僆僽僕僃僋僩偑柍偗傟偽堄枴柍偟
if( !m_lpDD )
return FALSE;
// DEBUGOUT( "CDirectDraw:OnChangeDisplayMode\n" );
// 嫤挷儌乕僪偺僠僃僢僋
HRESULT hr = m_lpDD->TestCooperativeLevel();
if( !m_bScreenMode ) {
// 僂僀儞僪僂
if( hr == DDERR_EXCLUSIVEMODEALREADYSET ) {
// 懠偵攔懠儌乕僪栰榊偑偍傞偺偱偍偟傑偄
// DEBUGOUT( "CDirectDraw:DDERR_EXCLUSIVEMODEALREADYSET\n" );
// 儕僗僩傾偟偪傖偄傗傫
m_bNoRestore = TRUE;
return TRUE;
} else if( hr == DDERR_WRONGMODE || hr == DD_OK ) {
// 晛捠偺僨傿僗僾儗僀儌乕僪偺曄峏(壗屘偐Window儊僢僙乕僕偩偲DD_OK側帪偑偁傞)
// DEBUGOUT( "CDirectDraw:DDERR_WRONGMODE\n" );
// 儕僗僩傾偟偰偊偊傛
m_bNoRestore = FALSE;
// 僒乕僼僃僗偺奐曻
ReleaseSurface();
// 僒乕僼僃僗偺弶婜壔
BOOL bRet = InitialSurface( m_bScreenMode );
if( bRet ) {
// DEBUGOUT( "CDirectDraw:InitialSurface ok.\n" );
} else {
// DEBUGOUT( "CDirectDraw:InitialSurface failed.\n" );
}
return bRet;
} else if( hr == DDERR_INVALIDOBJECT ) {
// DEBUGOUT( "CDirectDraw:DDERR_INVALIDOBJECT\n" );
return FALSE;
} else if( hr == DDERR_NOEXCLUSIVEMODE ) {
// DEBUGOUT( "CDirectDraw:DDERR_NOEXCLUSIVEMODE\n" );
} else {
// DEBUGOUT( "CDirectDraw:Unknown error. hr=%08X偨\n", hr );
}
// 椙偔暘偐傜傫偺偱偲傝偁偊偢僒乕僼僃僗傪儕僗僩傾
m_bNoRestore = FALSE;
RestoreSurface();
return TRUE;
} else {
// 僼儖僗僋儕乕儞
if( hr == DDERR_NOEXCLUSIVEMODE ) {
// 僼儖僗僋儕乕儞儌乕僪偐傜敳偗偨帪
// DEBUGOUT( "CDirectDraw:DDERR_NOEXCLUSIVEMODE\n" );
return TRUE;
}
if( hr == DD_OK ) {
// 儕僗僩傾偟傠偭偰帠偐...
// 僒乕僼僃僗傪儕僗僩傾
RestoreSurface();
return TRUE;
}
// 晄柧側尨場
return FALSE;
}
return TRUE;
}
void CDirectDraw::SetDisplayMode( DWORD dwWidth, DWORD dwHeight, DWORD dwDepth, DWORD dwRate )
{
m_dwDisplayWidth = dwWidth;
m_dwDisplayHeight = dwHeight;
m_dwDisplayDepth = dwDepth;
m_dwDisplayRate = dwRate;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -