⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddraw.cpp

📁 仿游戏 Diablo 的源代码
💻 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 + -