📄 display.cpp
字号:
#include "StdAfx.h"
#include "display.h"
#pragma comment(lib , "dxguid.lib" )
#pragma comment(lib , "ddraw.lib" )
#pragma comment(lib , "winmm.lib" )
CDisplay* CDisplay::m_Instance = 0;
CDisplay::CDisplay(void)
{
m_pDraw = NULL;
m_pMainBuffer = NULL;
m_pBackBuffer = NULL;
m_dwScreenColor = 32;
m_dwFPSState = false;
m_pEngineBuffer = NULL;
m_dwEngineBufferPitch = 0;
}
CDisplay::~CDisplay(void)
{
Destroy();
}
CDisplay* CDisplay::Instance(void)
{
if(m_Instance == 0)
m_Instance = new CDisplay;
return m_Instance;
}
bool CDisplay::Create(HWND hWnd,bool isFullScreen,DWORD Width,DWORD Height,DWORD ScreenColor)
{
RECT Rect;
m_hWnd = hWnd;
m_bFullScreen = isFullScreen;
m_dwScreenHeight = Height;
m_dwScreenWidth = Width;
m_dwScreenColor = ScreenColor;
NesDrawLineInit();
// 创建DirectDraw7接口
if( FAILED( DirectDrawCreateEx( NULL , ( VOID ** )&m_pDraw , IID_IDirectDraw7 , NULL ) ) )
{
DebugMsg("DirectDrawCreateEx Error\n");
return false;
}
// 设置窗口合作级别
if( m_bFullScreen )
{
if( FAILED( m_pDraw->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ) ) )
{
DebugMsg("Ddraw CooperativeLevel Error\n");
return false;
}
if( FAILED( m_pDraw->SetDisplayMode( m_dwScreenWidth , m_dwScreenHeight , m_dwScreenColor , 0 , 0 ) ) )
{
DebugMsg("Ddraw SetDisplay Error in Full Screen State\n");
return false;
}
}
else
{
//校正窗口位置,大小
RECT t_Rect;
GetClientRect( hWnd , &Rect );
GetWindowRect(hWnd,&t_Rect);
SetWindowPos( hWnd , NULL , t_Rect.left , t_Rect.top ,m_dwScreenWidth + ( m_dwScreenWidth - Rect.right ) , m_dwScreenHeight + ( m_dwScreenHeight - Rect.bottom ) , 0 );
ShowWindow( hWnd, SW_SHOW );
SetFocus( hWnd );
if( FAILED( m_pDraw->SetCooperativeLevel( hWnd, DDSCL_NORMAL ) ) ) // 窗口处理
{
DebugMsg("Ddraw SetCooperativeLevel Error in Window State\n");
return false;
}
}
// 创建主表面
DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
if( m_bFullScreen )
{
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
}
else
{
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
}
if( FAILED( m_pDraw->CreateSurface( &ddsd, &m_pMainBuffer , NULL ) ) )
{
DebugMsg("Ddraw CreateSurface Error\n");
return false;
}
// 创建后台表面
if( m_bFullScreen )
{
DDSCAPS2 ddscaps;
ZeroMemory( &ddscaps, sizeof( ddscaps ) );
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
if( FAILED( m_pMainBuffer->GetAttachedSurface( &ddscaps , &m_pBackBuffer ) ) )
{
DebugMsg("m_pMainBuffer GetAttachedSurface Error");
return false;
}
m_pMainBuffer->AddRef();
DDCAPS ddcaps;
ZeroMemory( &ddscaps, sizeof( ddscaps ) );
ddcaps.dwSize = sizeof( ddcaps );
m_pDraw->GetCaps( &ddcaps , NULL );
if( ( ddcaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED ) == 0 )
DebugMsg( "The display card can not render GDI\n");
if( FAILED( m_pDraw->CreateClipper( 0 , &m_pClipper, NULL ) ) )
{
DebugMsg("m_pDraw->CreateClipper Error\n");
return false;
}
m_pClipper->SetHWnd( 0 , hWnd );
m_pDraw->FlipToGDISurface();
}
else
{
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = m_dwScreenWidth;
ddsd.dwHeight = m_dwScreenHeight;
if( FAILED( m_pDraw->CreateSurface( &ddsd, &m_pBackBuffer, NULL) ) )
{
DebugMsg("m_pDraw->CreateSurface Error\n");
return false;
}
if( FAILED( m_pDraw->CreateClipper( 0 , &m_pClipper, NULL ) ) )
{
DebugMsg("m_pDraw->CreateClipper Error\n" );
return false;
}
if( FAILED( m_pClipper->SetHWnd( 0 , hWnd ) ) )
{
m_pClipper->Release();
DebugMsg("m_pClipper->SetHWnd Error" );
return false;
}
if( FAILED( m_pMainBuffer->SetClipper( m_pClipper ) ) )
{
m_pClipper->Release();
DebugMsg("m_pMainBuffer->SetClipper Error\n" );
return false;
}
m_pClipper->Release();
m_pClipper = NULL;
m_pDraw->FlipToGDISurface();
//判断当前颜色状态,以便进行像素格式转换
DEVMODE dmScreenSettings;
ZeroMemory( &dmScreenSettings, sizeof( dmScreenSettings ) );
if( EnumDisplaySettings( NULL , ENUM_REGISTRY_SETTINGS , &dmScreenSettings ) != 0 )
{
m_dwScreenColor = dmScreenSettings.dmBitsPerPel;
}
}
//创建一内存块,作为自定义缓冲,将所有的图片都复制到这个内存上,在拷贝到
//ddraw的缓冲表面,这样,可以防止从内存中拷贝图片直接复制到显存上
m_pEngineBuffer = new DWORD[m_dwScreenWidth*m_dwScreenHeight];
if(m_pEngineBuffer == NULL)
{
DebugMsg("Alloc Custom Buffer error!\n");
return false;
}
m_dwEngineBufferPitch = m_dwScreenWidth*sizeof(DWORD);
GetClientRect( hWnd , &Rect );
ClientToScreen( hWnd, ( LPPOINT )&Rect.left );
ClientToScreen( hWnd, ( LPPOINT )&Rect.right );
m_dwWinX = Rect.left;
m_dwWinY = Rect.top;
m_dwWinWidth = (DWORD)(Rect.right - Rect.left);
m_dwWinHeight = (DWORD)(Rect.bottom - Rect.top);
return true;
}
void CDisplay::Destroy(void)
{
if(m_pEngineBuffer != NULL)
delete[] m_pEngineBuffer;
if( m_pDraw != NULL )
{
if( m_pBackBuffer != NULL )
{
m_pBackBuffer->Release();
m_pBackBuffer = NULL;
}
if( m_pMainBuffer != NULL )
{
m_pMainBuffer->Release();
m_pMainBuffer = NULL;
}
if( m_pClipper != NULL )
{
m_pClipper->Release();
m_pClipper = NULL;
}
m_pDraw->Release();
m_pDraw = NULL;
}
}
void CDisplay::ClearScreen(DWORD Color)
{
DDBLTFX ddbltfx;
ZeroMemory(&ddbltfx,sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = Color;
m_pMainBuffer->Blt(NULL,NULL,NULL,DDBLT_COLORFILL,&ddbltfx);
}
void CDisplay::ClearBackBuffer(DWORD Color)
{
NesMemSet(m_pEngineBuffer,0,Color,m_dwScreenWidth*m_dwScreenHeight);
}
void CDisplay::UpdataDisplay(void)
{
m_dwTimer = timeGetTime();
static DWORD OldTimer = m_dwTimer;
static DWORD FPSCounter = 1;
static DWORD TimeCounter = 1;
FPSCounter ++;
RECT Rect;
GetClientRect( m_hWnd , &Rect );
ClientToScreen( m_hWnd, ( LPPOINT )&Rect.left );
ClientToScreen( m_hWnd, ( LPPOINT )&Rect.right );
m_dwWinX = Rect.left;
m_dwWinY = Rect.top;
m_dwWinWidth = (DWORD)(Rect.right - Rect.left);
m_dwWinHeight = (DWORD)(Rect.bottom - Rect.top);
DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
m_pBackBuffer->GetSurfaceDesc( &ddsd );
if( FAILED( m_pBackBuffer->Lock( NULL , &ddsd , DDLOCK_WAIT | DDLOCK_WRITEONLY , 0 ) ) )
{
m_pBackBuffer->Restore();
m_pMainBuffer->Restore();
if( FAILED( m_pBackBuffer->Lock( NULL , &ddsd , 0 , 0 ) ) )
{
DebugMsg( "Lock Back Buffer Error\n" );
return;
}
}
//将自定义缓冲拷贝到ddraw后台缓冲
//根据屏幕色彩转换像素格式
DWORD DestOff = 0 , SrcOff = 0,i;
switch( m_dwScreenColor )
{
case 32:
for( i = 0; i < m_dwScreenHeight; i ++ )
{
NesDrawLineNormal(ddsd.lpSurface,DestOff,m_pEngineBuffer,SrcOff,m_dwScreenWidth);
DestOff += ddsd.lPitch;
SrcOff += m_dwEngineBufferPitch;
}
break;
case 24:
for( i = 0; i < m_dwScreenHeight; i ++ )
{
NesDrawLine32To24(ddsd.lpSurface,DestOff,m_pEngineBuffer,SrcOff,m_dwScreenWidth);
DestOff += ddsd.lPitch;
SrcOff += m_dwEngineBufferPitch;
}
break;
case 16:
for( i = 0; i < m_dwScreenHeight; i ++ )
{
NesDrawLine32To16( ddsd.lpSurface,DestOff ,m_pEngineBuffer,SrcOff,m_dwScreenWidth);
DestOff += ddsd.lPitch;
SrcOff += m_dwEngineBufferPitch;
}
break;
}
m_pBackBuffer->Unlock(NULL);
//FPS开关
if( m_dwFPSState )
{
if( m_dwTimer - OldTimer > 1000 )
{
TimeCounter += m_dwTimer - OldTimer;
OldTimer = m_dwTimer;
}
DWORD FPS = ( FPSCounter * 1000 ) / TimeCounter;
char Buffer[ 256 ] = "";
sprintf( Buffer , "FPS= %d" , FPS );
HDC hDC;
m_pBackBuffer->GetDC( &hDC );
SetBkColor( hDC , 0 );
SetTextColor( hDC , RGB( 0 , 255 , 0 ) );
TextOut( hDC , 3 , 3 , Buffer , ( int )strlen( Buffer ) );
m_pBackBuffer->ReleaseDC( hDC );
}
if( FAILED( m_pMainBuffer->Blt( &Rect , m_pBackBuffer , NULL , DDBLT_WAIT , NULL ) ) )
DebugMsg( "Flip Error \n" );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -