📄 gscreen.cpp
字号:
#include"GScreen.h"
#include<windows.h>
__int64 GetCPUFrequency()
{
__int64 qwFreq;
::QueryPerformanceFrequency((LARGE_INTEGER*)&qwFreq);
return qwFreq;
}
GScreen::GScreen()
{
m_pDD=NULL;
m_pDSPrimary=NULL;
m_pDSBack=NULL;
m_pBuffer=NULL;
m_dwFPS=0;
m_dwBufSize=0;
m_bDefaultPal=true;
m_bUseVideoMemory=true;
for(int i=0;i<256;i++)
{
m_pPal[i]=i|(i<<8);
}
}
GScreen::~GScreen()
{
DestroySurface();
if(m_pDD)
{
m_pDD->Release();
m_pDD=NULL;
}
if(m_pBuffer)
{
delete [] m_pBuffer;
m_pBuffer=NULL;
}
}
void GScreen::DestroySurface()
{
if(m_pDSBack)
{
m_pDSBack->Release();
m_pDSBack=NULL;
}
if(m_pDSPrimary)
{
m_pDSPrimary->Release();
m_pDSPrimary=NULL;
}
}
HRESULT GScreen::RestoreSurface()
{
HRESULT hr;
if(m_pDSPrimary)
{
hr=m_pDSPrimary->Restore();
}
if(m_pDSBack)
{
hr=m_pDSBack->Restore();
}
return hr;
}
void GScreen::Present()
{
HRESULT hr;
static __int64 ddwOldTime=0,ddwNewTime;
static int frames=0;
static __int64 s_ddFreq=GetCPUFrequency();
QueryPerformanceCounter((LARGE_INTEGER*)&ddwNewTime);
if(ddwNewTime-ddwOldTime<s_ddFreq)
{
frames++;
}
else
{
ddwOldTime=ddwNewTime;
m_dwFPS=frames;
frames=0;
}
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
hr=m_pDSBack->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
while(DD_OK!=hr)
{
if(DDERR_SURFACELOST==hr)
RestoreSurface();
else
return;
hr=m_pDSBack->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
}
unsigned char*pSourBuf=(unsigned char*)m_pBuffer;
if(m_bDefaultPal)
{
//由于初学mmx,还不会作优化~代码见笑了~
unsigned long dwResPitch=ddsd.lPitch-(m_nWidth<<1);
unsigned char*pBuf=(unsigned char*)ddsd.lpSurface;
unsigned long dwHeight=m_nHeight;
unsigned long loopTime=m_nWidth>>5; //一次处理32个索引点
{
_asm
{
mov esi,pSourBuf;
mov edi,pBuf;
mov edx,dwHeight;
rowLoop:
cmp edx,0;
je end;
mov ecx,loopTime;
mmxdraw:
movq mm0,[esi]; //8个索引点
movq mm2,[esi+8]; //后8个索引点
movq mm4,[esi+16];
movq mm6,[esi+24];
movq mm1,mm0;
movq mm3,mm2;
movq mm5,mm4;
movq mm7,mm6;
punpcklbw mm0,mm0; //0-3个索引的值
punpckhbw mm1,mm1; //4-7
punpcklbw mm2,mm2; //8-11
punpckhbw mm3,mm3; //12-15
punpcklbw mm4,mm4;
punpckhbw mm5,mm5;
punpcklbw mm6,mm6;
punpckhbw mm7,mm7;
movq [edi],mm0;
movq [edi+8],mm1;
movq [edi+16],mm2;
movq [edi+24],mm3;
movq [edi+32],mm4;
movq [edi+40],mm5;
movq [edi+48],mm6;
movq [edi+56],mm7;
add esi,32;
add edi,64;
loop mmxdraw;
dec edx;
add edi,dwResPitch;
jmp rowLoop;
end:
emms;
}
}
}
else
{
unsigned long dwResPitch=(ddsd.lPitch>>1)-m_nWidth;
unsigned short*pBuf=(unsigned short*)ddsd.lpSurface;
for(register int i=0;i<m_nHeight;i++)
{
for(register int j=0;j<m_nWidth;j++)
{
*pBuf=m_pPal[*pSourBuf];
pBuf++;
pSourBuf++;
}
pBuf+=dwResPitch;
}
}
m_pDSBack->Unlock(NULL);
if(m_bFullScreen)
{
#ifdef NOFLIP
hr=m_pDSPrimary->Blt(NULL,m_pDSBack,NULL,DDBLT_WAIT,NULL);
while(DD_OK!=hr)
{
if(DDERR_SURFACELOST==hr)
RestoreSurface();
else
return;
hr=m_pDSPrimary->Blt(NULL,m_pDSBack,NULL,DDBLT_WAIT,NULL);
}
#else
hr=m_pDSPrimary->Flip(NULL,DDFLIP_WAIT);
while(DD_OK!=hr)
{
if(DDERR_SURFACELOST==hr)
RestoreSurface();
else
return;
hr=m_pDSPrimary->Flip(NULL,DDFLIP_WAIT);
}
#endif
}
else
{
RECT rtWindow;
::GetClientRect(m_hWnd,&rtWindow);
::ClientToScreen(m_hWnd,(POINT*)&rtWindow);
::ClientToScreen(m_hWnd,(POINT*)&rtWindow+1);
hr=m_pDSPrimary->Blt(&rtWindow,m_pDSBack,NULL,DDBLT_WAIT,NULL);
while(DD_OK!=hr)
{
if(DDERR_SURFACELOST==hr)
RestoreSurface();
else
return;
hr=m_pDSPrimary->Blt(&rtWindow,m_pDSBack,NULL,DDBLT_WAIT,NULL);
}
}
}
bool GScreen::CreateDirectDrawObject()
{
if(m_pDD)
return true;
HDC hdc=GetDC(GetDesktopWindow());
m_nDesktopBpp=GetDeviceCaps(hdc,PLANES)*GetDeviceCaps(hdc,BITSPIXEL);
ReleaseDC(GetDesktopWindow(),hdc);
HRESULT hr=DirectDrawCreateEx(NULL,(void**)&m_pDD,IID_IDirectDraw7,NULL);
if(FAILED(hr))
{
return false;
}
return true;
}
bool GScreen::CreateFullScreen(HWND hWnd,int width,int height)
{
m_nWidth=width;
m_nHeight=height;
m_nBpp=16;
m_hWnd=hWnd;
if(!CreateDirectDrawObject())
return false;
DestroySurface();
HRESULT hr;
hr=m_pDD->SetCooperativeLevel(m_hWnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWREBOOT);
if(FAILED(hr))
{
return false;
}
hr=m_pDD->SetDisplayMode(m_nWidth,m_nHeight,m_nBpp,0,0);
if(FAILED(hr))
{
return false;
}
#ifdef NOFLIP
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS;
ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
hr=m_pDD->CreateSurface(&ddsd,&m_pDSPrimary,NULL);
if(FAILED(hr))
{
return false;
}
ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth=m_nWidth;
ddsd.dwHeight=m_nHeight;
hr=m_pDD->CreateSurface(&ddsd,&m_pDSBack,NULL);
if(FAILED(hr))
{
return false;
}
#else
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount=1;
if(m_bUseVideoMemory)
ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_VIDEOMEMORY;
else
ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_SYSTEMMEMORY;
hr=m_pDD->CreateSurface(&ddsd,&m_pDSPrimary,NULL);
if(FAILED(hr))
{
return false;
}
ZeroMemory(&ddsd.ddsCaps,sizeof(ddsd.ddsCaps));
ddsd.ddsCaps.dwCaps=DDSCAPS_BACKBUFFER;
hr=m_pDSPrimary->GetAttachedSurface(&ddsd.ddsCaps,&m_pDSBack);
if(FAILED(hr))
{
return false;
}
#endif
if(NULL==m_pBuffer)
{
m_pBuffer=new unsigned char[m_nWidth*m_nHeight];
if(!m_pBuffer)
{
MessageBox(m_hWnd,"Out of memory!","Error",MB_OK);
return false;
}
}
m_bFullScreen=true;
m_dwBufSize=m_nWidth*m_nHeight;
return true;
}
bool GScreen::CreateWindowed(HWND hWnd,int width,int height)
{
m_nWidth=width;
m_nHeight=height;
m_nBpp=16;
m_hWnd=hWnd;
if(!CreateDirectDrawObject())
return false;
if(m_nBpp!=m_nDesktopBpp)
{
MessageBox(m_hWnd,"您的桌面不是16位色的,不能在窗口模式下运行","ERROR",MB_OK);
return false;
}
m_pDD->RestoreDisplayMode();
DestroySurface();
HRESULT hr;
hr=m_pDD->SetCooperativeLevel(m_hWnd,DDSCL_NORMAL);
if(FAILED(hr))
{
return false;
}
unsigned long dwStyle=GetWindowLong(m_hWnd,GWL_STYLE);
dwStyle &= ~WS_POPUP;
dwStyle|=WS_SYSMENU|WS_MINIMIZEBOX;
SetWindowLong(m_hWnd,GWL_STYLE,dwStyle );
SetWindowPos(m_hWnd,NULL,0,0,m_nWidth,m_nHeight,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
SetWindowPos(m_hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
MoveWindow(m_hWnd,(GetSystemMetrics(SM_CXSCREEN)-m_nWidth)/2,
(GetSystemMetrics(SM_CYSCREEN)-m_nHeight)/2,
m_nWidth,
m_nHeight,
true);
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS;
ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
hr=m_pDD->CreateSurface(&ddsd,&m_pDSPrimary,NULL);
if(FAILED(hr))
{
return false;
}
ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps=DDSCAPS_3DDEVICE|DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY;
ddsd.dwWidth=m_nWidth;
ddsd.dwHeight=m_nHeight;
hr=m_pDD->CreateSurface(&ddsd,&m_pDSBack,NULL);
if(FAILED(hr))
{
ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
hr=m_pDD->CreateSurface(&ddsd,&m_pDSBack,NULL);
if(FAILED(hr))
{
return false;
}
}
LPDIRECTDRAWCLIPPER pClipper;
hr=m_pDD->CreateClipper(0,&pClipper,NULL);
if(FAILED(hr))
{
return false;
}
hr=pClipper->SetHWnd(0,m_hWnd);
if(FAILED(hr))
{
pClipper->Release();
return false;
}
hr=m_pDSPrimary->SetClipper(pClipper);
if(FAILED(hr))
{
pClipper->Release();
return false;
}
pClipper->Release();
if(NULL==m_pBuffer)
{
m_pBuffer=new unsigned char[m_nWidth*m_nHeight];
if(!m_pBuffer)
{
MessageBox(m_hWnd,"Out of memory!","Error",MB_OK);
return false;
}
}
m_bFullScreen=false;
m_dwBufSize=m_nWidth*m_nHeight;
return true;
}
bool GScreen::SwitchDisplayMode()
{
if(m_bFullScreen)
{
return CreateWindowed(m_hWnd,m_nWidth,m_nHeight);
}
else
{
return CreateFullScreen(m_hWnd,m_nWidth,m_nHeight);
}
}
void GScreen::ClearPrimary()
{
DDBLTFX ddbltfx;
ZeroMemory(&ddbltfx,sizeof(ddbltfx));
ddbltfx.dwSize=sizeof(ddbltfx);
ddbltfx.dwFillColor=0;
m_pDSPrimary->Blt(NULL,NULL,NULL,DDBLT_COLORFILL,&ddbltfx);
}
void GScreen::TextOutDC(int x,int y,unsigned long dwColor,unsigned long dwLineChar,char*str,...)
{
POINT pt={x,y};
::ClientToScreen(m_hWnd,&pt);
x=pt.x;
y=pt.y;
char txt[1024];
va_list vl;
va_start(vl,str);
wvsprintf(txt,str,vl);
va_end(vl);
char strtmp[256];
HDC hdc;
m_pDSPrimary->GetDC(&hdc);
::SetBkMode(hdc,TRANSPARENT);
::SetTextColor(hdc,dwColor);
TEXTMETRIC tm;
::GetTextMetrics(hdc,&tm);
int nTextIndex;
int i=0;
while(txt[i]!='\0')
{
memset(strtmp,0,256);
nTextIndex=0;
while(txt[i]!='\0' && nTextIndex< (int)dwLineChar)
{
if((char)txt[i]<0) //如果是汉字
{
strtmp[nTextIndex++]=txt[i++];
strtmp[nTextIndex++]=txt[i++];
}
else
{
strtmp[nTextIndex++]=txt[i++];
}
}
::TextOut(hdc,x,y,strtmp,strlen(strtmp));
y+=tm.tmHeight;
}
m_pDSPrimary->ReleaseDC(hdc);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -