📄 ddraw.cpp
字号:
#include "gl.h"
#include "gengine.h"
#include "..\common.h"
#define _SHOWFPS //显示帧速
LPDIRECTDRAW lpDD = NULL;
LPDIRECTDRAWSURFACE lpDDSScreen = NULL;
DDSURFACEDESC ddsd;
Bitmap* screen = NULL; // 实际屏幕
Bitmap* backScreen = NULL; // 作图时操作的"屏幕"
CRITICAL_SECTION dDrawCritical; //临界区
extern HWND hScreen;
extern ScreenInfo screenInfo;
extern CRITICAL_SECTION dDrawCritical;
#ifdef _SHOWFPS
DWORD startTime, frameCounter;
#endif
void (*UpdateScreen)( void );
static void UpdateScreenNoMMX( void )
{
EnterCriticalSection( &dDrawCritical );
MouseBeforeUpdatescreen();
#ifdef _DEBUG
if( lpDDSScreen == NULL ){
MsgBox( "lpDDSScreen not exist." );
return;
}
#endif
if( FAILED( lpDDSScreen->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ))){
FailMsg( "Lock screen failed." );
return;
}
int pitch;
if(( pitch = ddsd.lPitch - screenInfo.width * BYTES_PER_PIXEL( screenInfo.colorDepth )) == 0 ){
int len = screenInfo.width * screenInfo.height /2;
__asm{
mov eax, offset ddsd;
mov ebx, backScreen;
mov ecx, len;
mov edx, [ebx]backScreen.line;
mov edi, [eax]ddsd.lpSurface;
mov esi, [edx];
cld;
rep movsd;
}
}
else{
__asm{
mov eax, backScreen;
mov ebx, offset ddsd;
mov edx, [eax]Bitmap.line;
mov edi, [ebx]ddsd.lpSurface;
mov esi, [edx];
lea ecx, screenInfo;
mov edx, [ecx]screenInfo.width;
mov eax, [ecx]screenInfo.height;
shr edx, 1;
shr eax, 2;
mov ebx, pitch;
cld;
ALIGN 4;
four_lines:
mov ecx, edx;
rep movsd;
add edi, ebx;
mov ecx, edx;
rep movsd;
add edi, ebx;
mov ecx, edx;
rep movsd;
add edi, ebx;
mov ecx, edx;
rep movsd;
add edi, ebx;
dec eax;
jnz four_lines;
}
}
lpDDSScreen->Unlock( NULL );
LeaveCriticalSection( &dDrawCritical );
}
static void UpdateScreenMMX( void )
{
EnterCriticalSection( &dDrawCritical );
MouseBeforeUpdatescreen();
#ifdef _DEBUG
if( lpDDSScreen == NULL ){
MsgBox( "lpDDSScreen not exist." );
return;
}
#endif
#ifdef _SHOWFPS
char fps[20];
frameCounter ++;
if(( frameCounter % 100 )== 0 ){
backScreen->Clear( 0,0,80,16,0);
sprintf( fps, "%d fps", frameCounter*1000/(GetTickCount()-startTime) );
hz.TextOut( backScreen, 0,0, fps, 0xffffff );
}
#endif
if( FAILED( lpDDSScreen->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ))){
FailMsg( "Lock screen failed." );
return;
}
int pitch;
if(( pitch = ddsd.lPitch - screenInfo.width * BYTES_PER_PIXEL( screenInfo.colorDepth )) == 0 ){
int len = screenInfo.width * screenInfo.height / 8;
__asm{
mov ebx, backScreen;
mov eax, offset ddsd;
mov edx, [ebx]Bitmap.line;
mov edi, [eax]ddsd.lpSurface;
mov ecx, len;
mov eax, 16;
mov esi, [edx];
ALIGN 4
mmx_loop:
movq mm0, [esi];
movq mm1, [esi+8];
movq [edi], mm0;
add esi, eax;
movq [edi+8], mm1;
add edi, eax;
dec ecx;
jnz mmx_loop;
emms;
}
}
else{
OutDebugInt( "pitch", pitch );
__asm{
mov eax, backScreen;
mov ebx, offset ddsd;
mov esi, [eax]Bitmap.line;
mov edi, [ebx]ddsd.lpSurface;
lea edx, screenInfo;
mov esi, [esi];
mov ecx, [edx]screenInfo.width;
mov eax, [edx]screenInfo.height;
shr ecx, 2;
mov ebx, pitch;
mov edx, 8;
movd mm1, ecx;
ALIGN 4;
one_line:
movq mm0, [esi];
add esi, edx;
movq [edi], mm0;
add edi, edx;
loop one_line;
add edi, ebx;
movd ecx, mm1;
dec eax;
jnz one_line;
emms;
}
}
lpDDSScreen->Unlock( NULL );
LeaveCriticalSection( &dDrawCritical );
}
int LockScreen( void )
{
#ifdef _DEBUG
if( !lpDD ){
MsgBox( "lpDD no exist" );
return -1;
}
#endif
if( FAILED( lpDDSScreen->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL ))){
return -1;
}
__asm{
lea ebx, ddsd;
mov edx, screen;
mov esi, [ebx]ddsd.lPitch;
mov ecx, [edx]screen.height;
mov [edx]screen.pitch, esi;
mov eax, [ebx]ddsd.lpSurface;
mov edi, [edx]screen.line;
cmp eax, [edi];
je lock_end;
lock_loop:
stosd;
add eax, esi;
dec ecx;
jnz lock_loop;
lock_end:
}
return 0;
}
int UnlockScreen( void )
{
#ifdef _DEBUG
if( !lpDD ){
MsgBox( "lpDD no exist" );
return -1;
}
#endif
if( FAILED( lpDDSScreen->Unlock( NULL ))){
return -1;
}
return 0;
}
int InitDDraw( void )
{
DDPIXELFORMAT ddpf;
if( FAILED( DirectDrawCreate( NULL, &lpDD, NULL )))
return FailMsg( "DirectDrawCreate failed." );
lpDD->SetCooperativeLevel( hScreen, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
if( FAILED( lpDD->SetDisplayMode( screenInfo.width, screenInfo.height, screenInfo.colorDepth )))
return FailMsg( "SetDisplayMode failed." );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if( FAILED( lpDD->CreateSurface( &ddsd, &lpDDSScreen, NULL )))
return FailMsg( "Unable to createsurface lpDDSScreen." );
ddpf.dwSize = sizeof( ddpf );
if( FAILED( lpDDSScreen->GetPixelFormat( &ddpf )))
return FailMsg( "GetPixelFormat failed." );
//根据DDraw主表面创建自定义内存位图
if( FAILED( lpDDSScreen->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL)))
return FailMsg( "Lock lpDDSScreen failed." );
lpDDSScreen->Unlock( NULL );
if( ddpf.dwGBitMask == 0x03e0 ){
screenInfo.colorDepth = 15;
screen = new Bitmap15;
}
else{
screenInfo.colorDepth = 16;
screen = new Bitmap16;
}
if( InitGraphicLibrary( screenInfo.colorDepth ) != 0 )
return FailMsg( "init graphic library failed" );
screen->line = (char**)new char[ddsd.dwHeight*sizeof(char*)];
backScreen = CreateBitmap( screenInfo.width, screenInfo.height );
if( screen == NULL || backScreen == NULL || screen->line == NULL ){
delete[] screen->line;
delete screen;
delete backScreen;
return FailMsg( "CreateBitmap failed." );
}
screen->width = screen->cr = ddsd.dwWidth;
screen->height = screen->cb = ddsd.dwHeight;
screen->cl = screen->ct = 0;
screen->clip = true;
screen->dat = ddsd.lpSurface;
screen->pitch = ddsd.lPitch;
screen->color = 0;
screen->colorKey = COLORKEY16;
screen->line[0] = (char*)screen->dat;
for( int i=1; i<screen->height; i++ )
screen->line[i] = (char*)screen->line[i-1] + screen->pitch;
UpdateScreen = ( cpu.mmx ) ? UpdateScreenMMX : UpdateScreenNoMMX;
#ifdef _SHOWFPS
startTime = GetTickCount();
frameCounter = 0;
#endif
InitializeCriticalSection( &dDrawCritical );
return 0;
}
void RestoreDDraw( void )
{
if( lpDDSScreen ){
if( lpDDSScreen->IsLost() == DDERR_SURFACELOST )
if( FAILED(lpDDSScreen->Restore()))
FailMsg( "lpDDSScreen restore failed." );
else
UpdateScreen();
}
}
void DestroyDDraw( void )
{
if( lpDD ){
if( lpDDSScreen )
lpDDSScreen->Release();
lpDD->Release();
lpDDSScreen = NULL;
lpDD = NULL;
}
delete[] screen->line;
screen->dat = NULL;
delete screen;
delete backScreen;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -