📄 ddapi.cpp
字号:
//////////////////////////////
// DDAPI.cpp : v0039
// Written by : Liu Gang
// Compiler : Microsoft Visual C++ 4.0 & DirectX
// Library : DDraw.Lib
// Copyright (C) : 1996 WayAhead Corporation
// v0010 : Aug.26.1996
// v0011 : Sep.26.1996
// v0020 : Nov.8.1996
// Warning: the width of the surface cannot larger than 640 pixel
// when this occurs, there will be only a general error code
// and return failed.
// v0021 : Nov.27.1996
// v0030 : Dec.11.1996, upgrade DirectDraw from 1.0 to 2.0
// v0031 : Feb.10.1997, fixed a bug that cannot release surfaces entirly
// add a parameter to DD_EraseFrontScreen(), DD_EraseBckScreen() and CDDSurface::Erase()
// add CDDSurface::SetColorKeyRGB() and CDDSurface::SetColorKeyPAL(), changed color key method
// v0032 : Mar.7.1997, Add a member "m_bInVideo" to CDDSurface
// To decrease the load time when surface lost
// v0033 : Mar.10.1997
// Warning: when using Lock()/Unlock() to access surface,
// please use ddsd.lPitch to stand for the width of
// the source surface. Mostly, the value in ddsd.dwWidth is equal to
// that in ddsd.lPitch. But if the surface is in video memory, and its
// width is less than 640, and cannot devied by 4, they do not match before you
// draw ddsd.lpSurface to other surfaces.
// v0034 : April.1.1997, add function FadeOut() and FadeIn(), add surface and palette counter
// add a member "m_bCreated" and a function IfCreated() to CDDSurface
// add a member "m_strPalette" and a function Reload() to CDDPalette
// v0035 : Apr.9.1997, fixed a bug that generated by last version, did not initialize m_bCreated when
// constructing class instance, it took two whole days.
// v0036 : Apr.18.1997, add CS_DBLCLKS to window style
// v0037 : May.6.1997, add fadein and fadeout functions, and read palette from customed palette file
// v0038 : May.10.1997, edited fadein and fadeout functions, to make them easy to use.
// v0039 : May.12.1997, changed the global palette to object
//////////////////////////////
//////////////////////////////
// implementation file
// This file provide basic interfaces for DirectDraw with C++
// extension, so that someone can use more easily.
//////////////////////////////
#include "stdafx.h"
#include <stdio.h>
#include "DDAPI.h"
#include "DDutils.h"
#include "Assert.h"
#include "resource.h"
#define MAX_SURFACE 256 // max surface is 256
#define MAX_PALETTE 8 // max palette is 8
// Aug. 20. 1997
//#define _DD_SYSTEMMEMORY
#ifdef _DEBUG
#define _DD_DEBUG
#endif
//////////////////////////////
// globals
// major window object
HWND hwndGame;
//////////////////////////////
//////////////////////////////
// locals
// abnormal structure: only one primary buffer
// not recommended to use global
// DirectDraw个体,唯一
LPDIRECTDRAW2 DD_lpDD=NULL; // DirectDraw object
// 第一个面,显示面,全屏
LPDIRECTDRAWSURFACE2 DD_lpDDSFront=NULL; // DirectDraw primary surface, front buffer
// 第二个面,用来保存背景,全屏
LPDIRECTDRAWSURFACE2 DD_lpDDSBack=NULL; // DirectDraw secondary surface, back buffer
// 系统当前调色版
LPDIRECTDRAWPALETTE DD_lpDDPal=NULL; // current palette that primary surface is using
// global control, cannnot used outside
// 其它用户生成的面,封装内部操作
class CDDSurface *DD_lppSurfaces[MAX_SURFACE]; // stores surfaces, max number is MAX_SURFACE
int DD_nSurfaceCounter = 0; // stores for the number of surfaces have been loaded
class CDDPalette *DD_lppPalettes[MAX_PALETTE]; // stores palettes, max number is MAX_PALETTE
int DD_nPaletteCounter = 0; // stores for the number of palettes have been loaded
// 淡入淡出效果
int nFadeLevel=0; // current fading step
PALETTEENTRY peFadeSave[256]; // save palette when fading
//added by tian yue.
PALETTEENTRY pe[256];
BOOL bFadeIn; // TRUE for fading in
//////////////////////////////
// local functions
//////////////////////////////
// get blitter error when using BltFast() and Blt(),
// not all the errors are here
// strHead : prefix string to be displayed
// ddrval : error number returned by BltFast() and Blt()
void DD_getBltError( char *strHead, int ddrval );
// get remained video memory, for debug version only
void DD_testVideoMemory();
//////////////////////////////
//////////////////////////////
// major window
//////////////////////////////
/*
* initialize major window
*/
// hInstance : handle of application instance
// nCmdShow : show major window or not
// strName : window name
// return value: handle of the window
HWND DD_InitWindow( HANDLE hInstance, int nCmdShow , LPCTSTR strName )
{
WNDCLASS wc;
/*
* set up and register window class
*/
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = DD_WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = HINSTANCE(hInstance);
// 用户要在其应用程序的资源编辑器里建立一个名为IDI_MAINGAME的图标
wc.hIcon = LoadIcon( HINSTANCE(hInstance), MAKEINTRESOURCE(IDI_MAINGAME) );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = HBRUSH(GetStockObject(BLACK_BRUSH));
wc.lpszMenuName = strName;
wc.lpszClassName = strName;
RegisterClass( &wc );
/*
* create a window
*/
hwndGame = CreateWindowEx(
0,
strName,
strName,
WS_POPUP,
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL,
NULL,
HINSTANCE(hInstance),
NULL );
if( !hwndGame )
{
DD_initFail(NULL, DD_ERROR_ID+90);
return NULL;
}
SetCursor(NULL); // hide cursor when begin application
ShowWindow( hwndGame, nCmdShow );
UpdateWindow( hwndGame );
return hwndGame;
} // DD_InitWindow()
//////////////////////////////
// graphic mode
//////////////////////////////
int gScreenWidth=0, gScreenHeight=0;
/*
* Initialize graphic system
*/
// hwnd : handle of the major window
// nWidth, nHeight, nDepth: the display mode of screen
// bInVideo : if 1, should load back buffer surface in video memory
// if 0, should load back buffer surface in system memory
// if -1, can load back buffer surface anywhere
// return value : TRUE if succeeded
BOOL DD_InitGraph( HWND hwnd, int nWidth/*=-1*/, int nHeight/*=-1*/, int nDepth/*=-1*/, int bInVideo/*=-1*/ )
{
DDSURFACEDESC ddsd;
HRESULT ddrval;
/*
* create the main DirectDraw object
*/
LPDIRECTDRAW lpDD = NULL;
ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
if( ddrval != DD_OK )
{
return DD_initFail(hwnd, DD_ERROR_ID+0);
}
// query direct draw object to object2
ddrval = lpDD->QueryInterface(IID_IDirectDraw2, (LPVOID *)&DD_lpDD);
if(ddrval != DD_OK)
{
return DD_initFail( hwnd, DD_ERROR_ID+6 );
}
// lpDD->Release(); // do not release, maybe useful
gScreenWidth = GetSystemMetrics( SM_CXSCREEN );
gScreenHeight = GetSystemMetrics( SM_CYSCREEN );
// Get exclusive mode
#ifdef _DD_DEBUG
ddrval = DD_lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
if( ddrval != DD_OK )
{
return DD_initFail(hwnd, DD_ERROR_ID+1);
}
#else
ddrval = DD_lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT );
if( ddrval != DD_OK )
{
return DD_initFail(hwnd, DD_ERROR_ID+3);
}
// Set the video mode to 640x480x256
// SCREEN_WIDTH*SCREEN_HEIGHT*SCREEN_THICK
if( nWidth == -1 ) nWidth = SCREEN_WIDTH;
if( nHeight == -1 ) nHeight = SCREEN_HEIGHT;
if( nDepth == -1 ) nDepth = SCREEN_THICK;
ddrval = DD_lpDD->SetDisplayMode( nWidth, nHeight, nDepth, 0, 0 );
if( ddrval != DD_OK )
{
if( nDepth > 8 )
{
DD_lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
DD_lpDD->Release();
DD_lpDD = NULL;
return FALSE;
}
else
return DD_initFail(hwnd, DD_ERROR_ID+2);
}
#endif
// get remained video memory
#ifdef _DEBUG
if( bInVideo )
DD_testVideoMemory();
#endif
// Create the primary surface without back buffer
LPDIRECTDRAWSURFACE lpDDSFront = NULL;
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
ddrval = DD_lpDD->CreateSurface( &ddsd, &lpDDSFront, NULL );
if( ddrval != DD_OK )
{
return DD_initFail(hwnd, DD_ERROR_ID+4);
}
// query direct draw surface to surface2
ddrval = lpDDSFront->QueryInterface(IID_IDirectDrawSurface2, (LPVOID *)&DD_lpDDSFront);
if(ddrval != DD_OK)
{
return DD_initFail( hwnd, DD_ERROR_ID+7 );
}
//lpDDSFront->Release(); // do not release, if so,
// when surface lost there are something wrong with that
// get remained video memory
#ifdef _DEBUG
if( bInVideo )
DD_testVideoMemory();
#endif
// create secondary surface, back buffer
LPDIRECTDRAWSURFACE lpDDSBack = NULL;
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
#ifdef _DD_DEBUG
#else
#ifdef _DD_SYSTEMMEMORY
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
#else
if( bInVideo == 0 )
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
else if( bInVideo == 1 )
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
#endif // _DDSYSTEMMEMORY
#endif // _DD_DEBUG
// same size as full screen
ddsd.dwWidth = SCREEN_WIDTH;
ddsd.dwHeight = SCREEN_HEIGHT;
ddrval = DD_lpDD->CreateSurface(&ddsd, &lpDDSBack, NULL);
if( ddrval != DD_OK )
{
if( bInVideo )
{
// try in system memory again
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
ddrval = DD_lpDD->CreateSurface(&ddsd, &lpDDSBack, NULL);
if( ddrval != DD_OK )
return DD_initFail(hwnd, DD_ERROR_ID+10);
}
else
return DD_initFail(hwnd, DD_ERROR_ID+5);
}
// query direct draw surface to surface2
ddrval = lpDDSBack->QueryInterface(IID_IDirectDrawSurface2, (LPVOID *)&DD_lpDDSBack);
if(ddrval != DD_OK)
{
return DD_initFail( hwnd, DD_ERROR_ID+8 );
}
lpDDSBack->Release(); // must release, bug fix
// init other (user) surfaces
for( int i=0 ; i< MAX_SURFACE; i++ )
DD_lppSurfaces[i] = NULL;
// init other (user) palettes
for( int j=0 ; j< MAX_PALETTE; j++ )
DD_lppPalettes[j] = NULL;
//-------------
// init primary palette object
PALETTEENTRY ape[256];
// build a 332 palette as the default.
//
for (i=0; i<256; i++)
{
ape[i].peRed = (BYTE)(((i >> 5) & 0x07) * 255 / 7);
ape[i].peGreen = (BYTE)(((i >> 2) & 0x07) * 255 / 7);
ape[i].peBlue = (BYTE)(((i >> 0) & 0x03) * 255 / 3);
ape[i].peFlags = (BYTE)0;
}
DD_lpDD->CreatePalette(DDPCAPS_8BIT, ape, &DD_lpDDPal, NULL);
if( DD_lpDDPal == NULL )
{
return DD_initFail(hwnd, DD_ERROR_ID+9);
}
//-------------
// clear screens
DD_EraseFrontScreen();
DD_EraseBackScreen();
return TRUE;
} /* DD_InitGraph */
/*
* quit graphic system, end DirectDraw section
*/
void DD_QuitGraph()
{
HRESULT ddrval;
if( DD_lpDD == NULL )
return;
// reset graph mode and cooperative level
ddrval = DD_lpDD->SetDisplayMode( gScreenWidth, gScreenHeight, 8, 0, 0 );
if( ddrval != DD_OK )
{
}
ddrval = DD_lpDD->SetCooperativeLevel( hwndGame, DDSCL_NORMAL );
if( ddrval != DD_OK )
{
}
if( DD_lpDD != NULL )
{
// restore other surfaces
for( int i=0 ; i< MAX_SURFACE; i++ )
{
if( DD_lppSurfaces[i] != NULL )
{
DD_lppSurfaces[i]->Release();
DD_lppSurfaces[i] = NULL;
}
}
Assert( DD_nSurfaceCounter == 0 );
//-------------
// release primary palette
if( DD_lpDDPal != NULL )
{
Assert( DD_lpDDPal != NULL );
DD_lpDDPal->Release();
DD_lpDDPal = NULL;
}
//-------------
// release palettes
for( int j=0; j< MAX_PALETTE ; j++ )
{
if( DD_lppPalettes[j] != NULL )
{
DD_lppPalettes[j]->Release();
DD_lppPalettes[j] = NULL;
}
}
Assert( DD_nPaletteCounter == 0 );
// release global surfaces
if( DD_lpDDSFront )
DD_lpDDSFront->Release();
DD_lpDDSFront = NULL;
if( DD_lpDDSBack )
DD_lpDDSBack->Release();
DD_lpDDSBack = NULL;
// release DirectDraw Object
DD_lpDD->Release();
DD_lpDD = NULL;
}
/*
LPDIRECTDRAW lpDD = NULL;
ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
if( ddrval != DD_OK )
{
return;
}
// query direct draw object to object2
ddrval = lpDD->QueryInterface(IID_IDirectDraw2, (LPVOID *)&DD_lpDD);
if(ddrval != DD_OK)
{
return;
}
// lpDD->Release(); // do not release, maybe useful
ddrval = DD_lpDD->SetCooperativeLevel( hwndGame, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT );
if( ddrval != DD_OK )
{
return;
}
// Set the video mode to 640x480x256
// SCREEN_WIDTH*SCREEN_HEIGHT*SCREEN_THICK
ddrval = DD_lpDD->SetDisplayMode( gScreenWidth, gScreenHeight, 8, 0, 0 );
if( ddrval != DD_OK )
{
return;
}
ddrval = DD_lpDD->SetCooperativeLevel( hwndGame, DDSCL_NORMAL );
if( ddrval != DD_OK )
{
return;
}
if( DD_lpDD != NULL )
{
// release DirectDraw Object
DD_lpDD->Release();
DD_lpDD = NULL;
}
*/
} /* DD_QuitGraph */
/*
* This function is called if the initialization function fails
*/
// hwnd : handle of the parent window
// err : error ID
// return value: Always FALSE
BOOL DD_initFail( HWND hwnd , int err )
{
char buf[MAX_SURFACE];
DD_QuitGraph();
wsprintf(buf, "DirectDraw init FAILED (%d)", err);
MessageBox( hwnd, buf, "ERROR", MB_OK );
return FALSE;
} /* DD_initFail */
// get front buffer pointer
// return value : pointer of front buffer
inline LPDIRECTDRAWSURFACE2 DD_GetFrontBuffer( void )
{
return DD_lpDDSFront;
}
// get back buffer pointer
// return value : pointer of back buffer
inline LPDIRECTDRAWSURFACE2 DD_GetBackBuffer( void )
{
return DD_lpDDSBack;
}
//////////////////////////////
// screen
//////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -