www.pudn.com > chibi > 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#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 ////////////////////////////// // if surface is lost, run retore // return value : TRUE if succeeded BOOL DD_RestoreScreen( void ) { HRESULT ddrval; // reset primary surface if( DD_lpDDSFront ) { ddrval = DD_lpDDSFront->Restore(); if( ddrval != DD_OK ) { int nErr=-1; switch( ddrval ) { case DDERR_GENERIC : nErr = 1; break; case DDERR_INCOMPATIBLEPRIMARY : nErr = 2; break; case DDERR_IMPLICITLYCREATED : nErr = 3; break; case DDERR_INVALIDOBJECT : nErr = 4; break; case DDERR_INVALIDPARAMS : nErr = 5; break; case DDERR_NOEXCLUSIVEMODE : nErr = 6; break; case DDERR_OUTOFMEMORY : nErr = 7; break; case DDERR_UNSUPPORTED : nErr = 8; break; case DDERR_WRONGMODE : nErr = 9; break; } // WriteErrorFile( "a.log", nErr ); return FALSE; } } // reset secondary surface if( DD_lpDDSBack ) { ddrval = DD_lpDDSBack->Restore(); if( ddrval != DD_OK ) return FALSE; } // reset palette, disband fade mode int nLevel = nFadeLevel; DD_FadeScreen( FALSE, 0 ); // reset surfaces for( int i=0; i Restore() ) return FALSE; } } // reset fade mode for( int l=0; l < nLevel ; l++ ) DD_FadeScreen( bFadeIn ); // send surface lost error message to user's application PostMessage( hwndGame, WM_DD_SURFACELOST, 0, 0 ); return TRUE; } /* DD_RestoreScreen */ // draw from back buffer to front buffer // pRect : rectangle region to update, full surface if it is NULL // return value : TRUE if succeeded BOOL DD_UpdateScreen( RECT *pRect/*=NULL*/ ) { HRESULT ddrval; RECT rect; if( pRect == NULL ) { rect.left = 0, rect.top = 0, rect.right = SCREEN_WIDTH, rect.bottom = SCREEN_HEIGHT; } else { rect.left = pRect->left, rect.top = pRect->top; rect.right = pRect->right, rect.bottom = pRect->bottom; } while( 1 ) { ddrval = DD_lpDDSFront->BltFast( rect.left, rect.top, DD_lpDDSBack, &rect, DDBLTFAST_NOCOLORKEY ); if( ddrval == DD_OK ) break; #ifdef _DEBUG DD_getBltError( "DD_UpdateScreen", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) if( !DD_RestoreScreen() ) return FALSE; if( ddrval != DDERR_WASSTILLDRAWING ) return FALSE; } return TRUE; } // DD_UpdateScreen() // fill black color to front screen // nColor : color index you want to fill, default is BLACK // pRect : rectangle region to erase, full surface if it is NULL // return value : TRUE if succeeded BOOL DD_EraseFrontScreen( int nColor, RECT *pRect/*=NULL*/ ) { DDBLTFX ddbltfx; HRESULT ddrval; // Erase the background ddbltfx.dwSize = sizeof( ddbltfx ); ddbltfx.dwFillColor = nColor; while( 1 ) { ddrval = DD_lpDDSFront->Blt( pRect, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); if( ddrval == DD_OK ) { break; } #ifdef _DEBUG DD_getBltError( "DD_EraseFrontScreen", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) { if( !DD_RestoreScreen() ) return FALSE; } if( ddrval != DDERR_WASSTILLDRAWING ) { return FALSE; } } return TRUE; } /* DD_EraseFrontScreen() */ // fill black color to back screen // nColor : color index you want to fill, default is BLACK // pRect : rectangle region to erase, full surface if it is NULL // return value : TRUE if succeeded BOOL DD_EraseBackScreen( int nColor/*=0*/, RECT *pRect/*=NULL*/ ) { DDBLTFX ddbltfx; HRESULT ddrval; // Erase the background ddbltfx.dwSize = sizeof( ddbltfx ); ddbltfx.dwFillColor = nColor; while( 1 ) { ddrval = DD_lpDDSBack->Blt( pRect, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); if( ddrval == DD_OK ) { break; } #ifdef _DEBUG DD_getBltError( "DDEraseBackScreen", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) { if( !DD_RestoreScreen() ) return FALSE; } if( ddrval != DDERR_WASSTILLDRAWING ) { return FALSE; } } return TRUE; } // DD_EraseBackScreen() // fill black color to a given surface // pSurface : surface to be erased // nColor : color index you want to fill, default is BLACK // pRect : rectangle region to erase, full surface if it is NULL // return value : TRUE if succeeded BOOL DD_EraseScreen( LPDIRECTDRAWSURFACE2 pSurface, int nColor, RECT *pRect/*=NULL*/ ) { DDBLTFX ddbltfx; HRESULT ddrval; // Erase the background ddbltfx.dwSize = sizeof( ddbltfx ); ddbltfx.dwFillColor = nColor; while( 1 ) { ddrval = pSurface->Blt( pRect, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); if( ddrval == DD_OK ) { break; } #ifdef _DEBUG DD_getBltError( "DDEraseScreen", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) { if( !DD_RestoreScreen() ) return FALSE; } if( ddrval != DDERR_WASSTILLDRAWING ) { return FALSE; } } return TRUE; } ////////////////////////////// // fade screen ////////////////////////////// // make screen fade in or fade out // bIn : TRUE for fade in screen, else for fade out screen // nMaxStep : ranges from 1 to 255, set to 0 if to reset this function // return value : TRUE for end session BOOL DD_FadeScreen( BOOL bIn , int nMaxStep /*=10*/ ) { RGBQUAD rgb[256]; PALETTEENTRY pe[256]; int nStep; // reset Fade mode if( nMaxStep == 0 ) { if( nFadeLevel != 0 ) DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ); nFadeLevel=0; return TRUE; } // get palette entries and save it if( nFadeLevel == 0 ) { if(DD_lpDDPal->GetEntries( 0, 0, 256, peFadeSave ) != DD_OK) { return TRUE; } } // if end section, restore palette if( nFadeLevel == nMaxStep ) { nFadeLevel = 0; DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ); return TRUE; } // set from palette entries to rgb for ( int j = 0; j< 256; j++ ) { rgb[j].rgbRed = peFadeSave[j].peRed; rgb[j].rgbGreen = peFadeSave[j].peGreen; rgb[j].rgbBlue = peFadeSave[j].peBlue; } // fade in or fade out bFadeIn = bIn; if( bIn ) nStep=nFadeLevel; // fade in else nStep=nMaxStep-nFadeLevel; // do it for( int i=0; i<256; i++ ) { rgb[i].rgbRed = peFadeSave[i].peRed*nStep/nMaxStep; rgb[i].rgbGreen = peFadeSave[i].peGreen*nStep/nMaxStep; rgb[i].rgbBlue = peFadeSave[i].peBlue*nStep/nMaxStep; } // set from rgb to palette entries for ( int k = 0; k< 256; k++ ) { pe[k].peRed = rgb[k].rgbRed; pe[k].peGreen = rgb[k].rgbGreen; pe[k].peBlue = rgb[k].rgbBlue; } // set to palette if(DD_lpDDPal->SetEntries( 0, 0, 256, pe ) != DD_OK) { nFadeLevel = 0; DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ); return TRUE; } nFadeLevel ++; return FALSE; } /* DD_FadeScreen */ // fade out // nMaxStep : ranges from 1 to 255, set to 0 if to reset this function // return value : TRUE for end session BOOL DD_FadeOut( int nMaxStep ) { PALETTEENTRY pe[256]; int nStep; // get palette entries and save it if( nFadeLevel == 0 ) { if(DD_lpDDPal->GetEntries( 0, 0, 256, peFadeSave ) != DD_OK) { return TRUE; } } // if end section, restore palette if( nFadeLevel == (nMaxStep+1) ) { nFadeLevel = 0; return TRUE; } // to computation the current step nStep= nMaxStep - nFadeLevel; // do it for( int i=0; i<256; i++ ) { pe[i].peRed = peFadeSave[i].peRed*nStep/nMaxStep; pe[i].peGreen = peFadeSave[i].peGreen*nStep/nMaxStep; pe[i].peBlue = peFadeSave[i].peBlue*nStep/nMaxStep; } if(DD_lpDDPal->SetEntries( 0, 0, 256, pe ) != DD_OK) { nFadeLevel = 0; DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ); return TRUE; } nFadeLevel ++; return FALSE; } /* DD_FadeOut */ // fade in // nMaxStep : ranges from 1 to 255, set to 0 if to reset this function // return value : TRUE for end session BOOL DD_FadeIn(PALETTEENTRY * pe,PALETTEENTRY * peFadeSave,int nMaxStep ) { // do it DD_lpDDPal->SetEntries( 0, 0, 256, pe ) ; for( int i=0; i<256; i++ ) { if (pe[i].peRed SetEntries( 0, 0, 256, peFadeSave ); return TRUE; } if(DD_lpDDPal->SetEntries( 0, 0, 256, pe ) != DD_OK) { nFadeLevel = 0; DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ); return TRUE; } nFadeLevel ++; return FALSE; } /* DD_FadeOut */ // fade out screen, from color to black // nMaxStep : how much steps fade from begin to end // nDelay : time each step should pause, in million second void DD_FadeOutScreen( int nMaxStep, int nDelay ) { PALETTEENTRY pe[256]; #ifdef _DD_DEBUG return; #endif //_DD_DEBUG // get palette entries and save it Assert( DD_lpDDPal != NULL ); if(DD_lpDDPal->GetEntries( 0, 0, 256, peFadeSave ) != DD_OK) { // error in get entry return; } if( nMaxStep <= 0 ) return; // step error for( int nStep=nMaxStep-1; nStep>=0; nStep-- ) { // do it for( int i=0; i<256; i++ ) { pe[i].peRed = peFadeSave[i].peRed*nStep/nMaxStep; pe[i].peGreen = peFadeSave[i].peGreen*nStep/nMaxStep; pe[i].peBlue = peFadeSave[i].peBlue*nStep/nMaxStep; } if(DD_lpDDPal->SetEntries( 0, 0, 256, pe ) != DD_OK) { // error in set entry DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ); return; } Sleep( nDelay ); } } // DD_FadeOutScreen() // fade in screen, from black to color, muset used with DD_FadeClear() // nStep : how much steps fade from begin to end // nDelay : time each step should pause, in million second // pPal : the palette you want to display at last void DD_FadeInScreen( int nMaxStep, int nDelay ) { PALETTEENTRY pe[256]; #ifdef _DD_DEBUG return; #endif //_DD_DEBUG Assert( DD_lpDDPal != NULL ); if( DD_lpDDPal == NULL ) { OutputDebugString( "FadeInScreen Error(4): current palette is NULL!\n" ); return; // palette pointer cannot be NULL } if( nMaxStep <= 0 ) { OutputDebugString( "DD_FadeInScreen Error(5): Step is less than 0!\n" ); if( DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ) != DD_OK ) { OutputDebugString( "DD_FadeInScreen Error(0): Cannot set entries at last!\n" ); } return; // step error, set palette directly } for( int nStep=0; nStep SetEntries( 0, 0, 256, pe ) != DD_OK) { // error in set entry OutputDebugString( "DD_FadeInScreen Error(1): Cannot set entries!\n" ); DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ); return; } Sleep( nDelay ); } if( DD_lpDDPal->SetEntries( 0, 0, 256, peFadeSave ) != DD_OK ) { OutputDebugString( "DD_FadeInScreen Error(2): Cannot set entries at last!\n" ); } } // DD_FadeInScreen() // Restore saved palette from "peFadeSave" to spcecified palette // pointer. Usually used after DD_FadeOutScreen(), to reset the // palette at last, or maybe not useful after v0039. // pPal : palette pointer to be restored void DD_FadeRestore( LPDIRECTDRAWPALETTE pPal ) { #ifdef _DD_DEBUG return; #endif //_DD_DEBUG if( pPal->SetEntries( 0, 0, 256, peFadeSave ) != DD_OK ) { OutputDebugString( "DD_FaceRestore Error: Cannot set entries!\n" ); } } // DD_FadeRestore() // Clear the palette pointer to whole black. Usually used before // DD_FadeInScreen(), to set a palette first and save the origional // value to "peFadeSave" // pPal : palette to be cleared void DD_FadeClear( LPDIRECTDRAWPALETTE pPal ) { PALETTEENTRY pe[256]; #ifdef _DD_DEBUG return; #endif //_DD_DEBUG if( pPal == NULL ) return; if( pPal->GetEntries( 0, 0, 256, peFadeSave ) != DD_OK ) { // save palette OutputDebugString( "DD_FaceClear Error(0): Cannot get entries!\n" ); } memset( pe, 0, sizeof( pe ) ); if( pPal->SetEntries( 0, 0, 256, pe ) != DD_OK ) { // set to Zero OutputDebugString( "DD_FaceClear Error(1): Cannot set entries!\n" ); } } // DD_FadeClear() ////////////////////////////// // blt ////////////////////////////// // draw from one surface to another // ptDest : destination position in destination surface // lprcSrc : source rectangle in source surface, full surface if it is NULL // dwFlags : DDBLTFAST_NOCOLORKEY or DDBLTFAST_SRCCOLORKEY // return value : TRUE if succeeded BOOL DD_BltSurface( POINT ptDest, LPDIRECTDRAWSURFACE2 lpDDSDest, RECT *lprcSrc, LPDIRECTDRAWSURFACE2 lpDDSSrc, DWORD dwFlags ) { HRESULT ddrval; while( 1 ) { ddrval = lpDDSDest->BltFast( ptDest.x, ptDest.y, lpDDSSrc, lprcSrc, dwFlags ); if( ddrval == DD_OK ) break; #ifdef _DEBUG DD_getBltError( "DD_BltSurface", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) if( !::DD_RestoreScreen() ) return FALSE; if( ddrval != DDERR_WASSTILLDRAWING ) return FALSE; } return TRUE; } // get global palette pointer LPDIRECTDRAWPALETTE DD_GetPalette() { return DD_lpDDPal; } ////////////////////////////// ////////////////////////////// // for class CDDSurface, standard offscreen plain surface // contructor CDDSurface::CDDSurface() { m_lpSurface = NULL; m_lpPalette = NULL; // the surface is not created yet m_bCreated = FALSE; // bitmap attributes m_bHasBitmap = FALSE; strcpy( m_strBitmap, "" ); m_szBitmap.cx = m_szBitmap.cy = 0; // color key m_dwDrawFlag = 0; // if in video memory, only used when surface lost m_bInVideo = FALSE; } // destructor CDDSurface::~CDDSurface() { Release(); if( m_lpPalette != NULL ) { m_lpPalette->Release(); m_lpPalette = NULL; } m_bHasBitmap = FALSE; } // create surface object // width, height: size of surface to create // bColorkey : TRUE if want color key, BLACK // bInVideo : 1, should load surface in video memory // 0, should load surface in system memory // -1, load surface anywhere possible // return value : TRUE if succeeded BOOL CDDSurface::Create( int width, int height, BOOL bColorKey/*=FALSE*/, BOOL bInVideo/*=-1*/ ) { HRESULT ddrval; DDSURFACEDESC ddsd; LPDIRECTDRAWSURFACE lpSurface = NULL; // get remained video memory #ifdef _DEBUG if( bInVideo ) DD_testVideoMemory(); #endif if( m_bCreated == TRUE ) { OutputDebugString( "CDDSurface Create Warning: surface has been already created\n " ); return FALSE; } ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; #ifdef _DD_SYSTEMMEMORY m_bInVideo = FALSE; ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; #else m_bInVideo = bInVideo; if( bInVideo == 0 ) ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; else if( bInVideo == 1 ) ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; #endif // _DDSYSTEMMEMORY ddsd.dwWidth = width; ddsd.dwHeight = height; // create DirectDraw surface if ((ddrval = DD_lpDD->CreateSurface(&ddsd, &lpSurface, NULL)) != DD_OK) { int nErr=-1; switch( ddrval ) { case DDERR_INVALIDOBJECT: nErr = 0; break; case DDERR_INVALIDPARAMS: nErr = 1; break; case DDERR_OUTOFVIDEOMEMORY: nErr = 2; break; case DDERR_NODIRECTDRAWHW: nErr = 3; break; case DDERR_NOCOOPERATIVELEVELSET: nErr = 4; break; case DDERR_INVALIDCAPS: nErr = 5; break; case DDERR_INVALIDPIXELFORMAT: nErr = 6; break; case DDERR_NOALPHAHW: nErr = 7; break; case DDERR_NOFLIPHW: nErr = 8; break; case DDERR_NOZBUFFERHW: nErr = 9; break; case DDERR_NOEXCLUSIVEMODE: nErr = 10; break; case DDERR_OUTOFMEMORY: nErr = 11; break; case DDERR_PRIMARYSURFACEALREADYEXISTS: nErr = 12; break; case DDERR_NOEMULATION: nErr = 13; break; case DDERR_INCOMPATIBLEPRIMARY: nErr = 14; break; } if( nErr == 2 ) // out of video memory is not an Must Quit eror { OutputDebugString( "Out of video memory error!\n" ); return FALSE; } if( bInVideo == TRUE ) { OutputDebugString( "In video error!\n" ); return FALSE; } OutputDebugString( "CDDSurface Create() Error(5): Surface create error!\n" ); return DD_initFail(hwndGame, DD_ERROR_ID+70+nErr); } // query direct draw surface to surface2 ddrval = lpSurface->QueryInterface(IID_IDirectDrawSurface2, (LPVOID *)&m_lpSurface); if( ddrval != DD_OK ) { OutputDebugString( "CDDSurface Create() Error(6): Query interface error!\n" ); return DD_initFail( hwndGame, DD_ERROR_ID+68 ); } lpSurface->Release(); // must release, bug fix // add to global surfaces array BOOL bSuccess = FALSE; for( int i=0; i GetSurfaceDesc( &ddsd ); if( ddrval != DD_OK ) { OutputDebugString( "CDDSurface Loadbitmap() Error(2): Get Surface desc error!\n" ); return DD_initFail(hwndGame, DD_ERROR_ID+59); } m_szBitmap.cx = ddsd.dwWidth, m_szBitmap.cy = ddsd.dwHeight; // set color key if( bColorKey ) { // use color on top-left corner of the surface as color key SetColorKeyRGB( RGB(0,0,0) ); //m_dwDrawFlag set by SetColorKeyRGB() just now. //m_dwDrawFlag = DDBLTFAST_SRCCOLORKEY; } else m_dwDrawFlag = DDBLTFAST_NOCOLORKEY; m_bCreated = TRUE; return TRUE; } ////////////////////////////// // color key ////////////////////////////// // actually, you need not use these two functions to set color key, // if you want color key, by default, BLACK is the color key // they all can run correctly on 256 color, exclusive mode. // in unexclusive mode, surface created by Create(), // SetColorKeyPAL() and SetColorKeyRGB() are not correct. // in high color mode, surface created by Create(), // SetColorKeyPAL() and SetColorKeyRGB() are not correct. // if surface created by LoadBitmap(), they are all correct. // only SetColorKeyDEF() can run correctly in any condition. // set colorkey by default // color on top left corner of the surface to be color key // must be used after Create() or LoadBitmap() // if used before, no effects // return : TRUE if successful BOOL CDDSurface::SetColorKeyDEF() { // use color on top-left corner of the surface as color key HRESULT ddrval; if( !m_lpSurface ) { OutputDebugString( "CDDSurface Error(38): Set color key before create surface!\n" ); return FALSE; } // get color from top-left corner of the surface DWORD dw; DDSURFACEDESC ddsd; ddsd.dwSize = sizeof(ddsd); while ((ddrval = m_lpSurface->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) ; if (ddrval == DD_OK) { dw = *(DWORD *)ddsd.lpSurface; // get DWORD dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1; // mask it to bpp m_lpSurface->Unlock(NULL); } // set as color key DDCOLORKEY ddck; ddck.dwColorSpaceLowValue = dw; ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue; while( 1 ) { ddrval = m_lpSurface->SetColorKey(DDCKEY_SRCBLT, &ddck); if( ddrval == DD_OK ) break; if( ddrval == DDERR_SURFACELOST ) if( !::DD_RestoreScreen() ) return DD_initFail(hwndGame, DD_ERROR_ID+52); if( ddrval != DDERR_WASSTILLDRAWING ) return DD_initFail(hwndGame, DD_ERROR_ID+53); } m_dwDrawFlag = DDBLTFAST_SRCCOLORKEY; return TRUE; } // set colorkey by given RGB value // must be used after Create() or LoadBitmap() // if used before, no effects // nColor : color key value // return : TRUE if successful BOOL CDDSurface::SetColorKeyRGB( DWORD dwColor ) { HRESULT ddrval; if( !m_lpSurface ) { OutputDebugString( "CDDSurface Error(39): Set color key before create surface!\n" ); return FALSE; } while( 1 ) { ddrval = ::DDSetColorKey(m_lpSurface, dwColor); if( ddrval == DD_OK ) break; if( ddrval == DDERR_SURFACELOST ) if( !::DD_RestoreScreen() ) return DD_initFail(hwndGame, DD_ERROR_ID+54); if( ddrval != DDERR_WASSTILLDRAWING ) return DD_initFail(hwndGame, DD_ERROR_ID+55); } m_dwDrawFlag = DDBLTFAST_SRCCOLORKEY; return TRUE; } // set colorkey by given palette entry // must be used after Create() or LoadBitmap() // if used before, no effects // if in high/true color mode, this functions is obsolete // nColor : color key value // return : TRUE if successful BOOL CDDSurface::SetColorKeyPAL( BYTE nColor ) { HRESULT ddrval; if( !m_lpSurface ) { OutputDebugString( "CDDSurface Error(40): Set color key before create surface!\n" ); return FALSE; } /* // There is a bug here: // a surface may not have palette of its own if created by Create() // function. if( !m_lpPalette ) { OutputDebugString( "CDDSurface Error(41): Set color key before load palette!\n" ); OutputDebugString( "This may usually occured when set program with high/true color!\n" ); return FALSE; } */ DDCOLORKEY ddck; ddck.dwColorSpaceLowValue = nColor; ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue; while( 1 ) { ddrval = m_lpSurface->SetColorKey(DDCKEY_SRCBLT, &ddck); if( ddrval == DD_OK ) break; if( ddrval == DDERR_SURFACELOST ) if( !::DD_RestoreScreen() ) return DD_initFail(hwndGame, DD_ERROR_ID+66); if( ddrval != DDERR_WASSTILLDRAWING ) return DD_initFail(hwndGame, DD_ERROR_ID+57); } m_dwDrawFlag = DDBLTFAST_SRCCOLORKEY; return TRUE; } ////////////////////////////// ////////////////////////////// // release surface object void CDDSurface::Release() { if( DD_lpDD == NULL ) return; if( m_lpSurface != NULL ) { // delete surface object from global array for( int i=0 ; i Release(); m_lpSurface = NULL; m_lpPalette = NULL; } m_bCreated = FALSE; } // load a bitmap to an existing surface // strBitmap: new bitmap file name // return value: TRUE if succeeded BOOL CDDSurface::ReLoadBitmap( LPCTSTR strBitmap /*= NULL*/) { // store name of file or resource if( strBitmap != NULL ) strcpy( m_strBitmap, strBitmap ); m_bHasBitmap = TRUE; // test if the palette pointer has been deleted if( m_lpPalette != NULL ) { BOOL bSuccess = FALSE; for ( int j=0 ; j< MAX_PALETTE ; j++ ) { if( DD_lppPalettes[j] != NULL && m_lpPalette == DD_lppPalettes[j]->GetPalette() ) bSuccess = TRUE; } if( bSuccess == FALSE ) m_lpPalette = NULL; } // set my palette // if( m_lpPalette != NULL ) DD_lpDDSFront->SetPalette( m_lpPalette ); // reload if( ::DDReLoadBitmap(m_lpSurface, m_strBitmap) == NULL ) return DD_initFail(hwndGame, DD_ERROR_ID+67); // restore palette DD_lpDDSFront->SetPalette( DD_lpDDPal ); return TRUE; } // if surface is lost, run restore // there maybe a bug, if bitmap was loaded by Auto memory detect, // and load into video memory, but got surface lost, the bitmap may // not be reloaded. // return value : TRUE if it is succeeded BOOL CDDSurface::Restore( void ) { HRESULT ddrval; ddrval = m_lpSurface->Restore(); if( ddrval == DD_OK ) { // only if has bitmap loaded and is in video memory, // should reload bitmap from file if( m_bHasBitmap && m_bInVideo != FALSE ) { // test if the palette pointer has been deleted if( m_lpPalette != NULL ) { BOOL bSuccess = FALSE; for ( int j=0 ; j< MAX_PALETTE ; j++ ) { if( DD_lppPalettes[j] != NULL && m_lpPalette == DD_lppPalettes[j]->GetPalette() ) bSuccess = TRUE; } if( bSuccess == FALSE ) m_lpPalette = NULL; } // set my palette if( m_lpPalette != NULL ) DD_lpDDSFront->SetPalette( m_lpPalette ); // reload ddrval = ::DDReLoadBitmap(m_lpSurface, m_strBitmap); if( ddrval != DD_OK ) return FALSE; // reset palette DD_lpDDSFront->SetPalette( DD_lpDDPal ); } return TRUE; } return FALSE; } // MMX // blt my surface to front surface // 贴图直接到显示面上 // ptDest : destination position, top-left // lpercSrc : source rectangle, full surface if it is NULL // return value : TRUE if succeeded BOOL CDDSurface::BltToFront( POINT ptDest, LPRECT lprcSrc ) { HRESULT ddrval; while( 1 ) { ddrval = DD_lpDDSFront->BltFast( ptDest.x, ptDest.y, m_lpSurface, lprcSrc, m_dwDrawFlag ); if( ddrval == DD_OK ) break; #ifdef _DEBUG DD_getBltError( "CDDSurface::BltToFront", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) if( !::DD_RestoreScreen() ) return FALSE; if( ddrval != DDERR_WASSTILLDRAWING ) return FALSE; } return TRUE; } // MMX // blt my surface to back surface // 贴图到背景面上 // ptDest : destination position, top-left // lprcSrc : source rectangle, full surface if it is NULL // return value : TRUE if succeeded BOOL CDDSurface::BltToBack( POINT ptDest, LPRECT lprcSrc ) { HRESULT ddrval; while( 1 ) { ddrval = DD_lpDDSBack->BltFast( ptDest.x, ptDest.y, m_lpSurface, lprcSrc, m_dwDrawFlag ); if( ddrval == DD_OK ) break; #ifdef _DEBUG DD_getBltError( "CDDSurface::BltToBack", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) if( !::DD_RestoreScreen() ) return FALSE; if( ddrval != DDERR_WASSTILLDRAWING ) return FALSE; } return TRUE; } // blt given surface to my surface // if created by Create(), flags must be DDBLTFAST_NOCOLORKEY // if created by LoadBitmap( .., FALSE ), flags must be DDBLTFAST_NOCOLORKEY // if created by LoadBitmap( .., [TRUE]), flags must be DDBLTFAST_SRCCOLORKEY // x,y : Destinaiton position // lpsrcSurface : source surface // src : source rectangle, full surface if it is NULL // flags : blting flag, DDBLTFAST_NOCOLORKEY or DDBLTFAST_SRCCOLORKEY // return value : TRUE if succeeded BOOL CDDSurface::BltSurface( int x, int y, LPDIRECTDRAWSURFACE2 lpsrcSurface, LPRECT src, DWORD dwflags ) { HRESULT ddrval; while( 1 ) { ddrval = m_lpSurface->BltFast( x, y, lpsrcSurface, src, dwflags ); if( ddrval == DD_OK ) break; #ifdef _DEBUG DD_getBltError( "CDDSurface::BltSurface", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) if( !::DD_RestoreScreen() ) return FALSE; if( ddrval != DDERR_WASSTILLDRAWING ) return FALSE; } return TRUE; } // fill black color to the surface // nColor : color index you want to fill, default is BLACK // pRect : region to fill, default is the entire surface // return value : TRUE if succeeded BOOL CDDSurface::Erase( int nColor/*=0*/, RECT *pRect/*=NULL*/ ) { DDBLTFX ddbltfx; HRESULT ddrval; // Erase the background ddbltfx.dwSize = sizeof( ddbltfx ); ddbltfx.dwFillColor = nColor; while( 1 ) { ddrval = m_lpSurface->Blt( pRect, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); if( ddrval == DD_OK ) { break; } #ifdef _DEBUG DD_getBltError( "CDDSurface::Erase", ddrval ); #endif if( ddrval == DDERR_SURFACELOST ) { if( !::DD_RestoreScreen() ) return FALSE; } if( ddrval != DDERR_WASSTILLDRAWING ) { return FALSE; } } return TRUE; } ////////////////////////////// ////////////////////////////// // class palette // contructor CDDPalette::CDDPalette() { m_lpPalette = NULL; m_nType = -1; } // destructor CDDPalette::~CDDPalette() { Release(); } // create palette object from a bitmap // strBitmap : bitmap file name // bSet : TRUE if should set palette to // the primary surface right after creation BOOL CDDPalette::LoadPalette( LPCTSTR strBitmap , BOOL bSet /*=FALSE*/) { strcpy( m_strPalette, strBitmap ); // save source bitmap file name m_lpPalette = DDLoadPalette(DD_lpDD, strBitmap); m_nType = DD_PALTYPE_BMP; if( m_lpPalette ) { // add to global palette array BOOL bSuccess = FALSE; for ( int j=0 ; j< MAX_PALETTE ; j++ ) { if( DD_lppPalettes[j] == NULL ) { DD_lppPalettes[j] = this; DD_nPaletteCounter++; bSuccess = TRUE; break; } } if( !bSuccess ) return DD_initFail(hwndGame, DD_ERROR_ID+60); // set palette to primary if you want if( bSet ) if( !SetPalette() ) return DD_initFail(hwndGame, DD_ERROR_ID+62); return TRUE; } return DD_initFail(hwndGame, DD_ERROR_ID+61); } // create palette object from a customed palette file // strPal : palette file name // bSet : TRUE if should set palette to // the primary surface right after creation BOOL CDDPalette::LoadPalettePAL( LPCTSTR strPal , BOOL bSet /*=TRUE*/) { PALETTEENTRY ape[256]; strcpy( m_strPalette, strPal ); // save source bitmap file name TY_LoadPaletteFromPAL( strPal, ape, 256 ); // !Warning: // you must use DDPCAPS_ALLOW256 if you want to use all the 256 palette entries //|DDPCAPS_ALLOW256 DD_lpDD->CreatePalette(DDPCAPS_8BIT, ape, &m_lpPalette, NULL); m_nType = DD_PALTYPE_PAL; if( m_lpPalette ) { // add to global palette array BOOL bSuccess = FALSE; for ( int j=0 ; j< MAX_PALETTE ; j++ ) { if( DD_lppPalettes[j] == NULL ) { DD_lppPalettes[j] = this; DD_nPaletteCounter++; bSuccess = TRUE; break; } } if( !bSuccess ) return DD_initFail(hwndGame, DD_ERROR_ID+63); // set palette to primary if you want if( bSet ) if( !SetPalette() ) return DD_initFail(hwndGame, DD_ERROR_ID+64); return TRUE; } return DD_initFail(hwndGame, DD_ERROR_ID+65); } // return : TRUE if successful BOOL CDDPalette::ReloadPalette() { int nType = m_nType; Release(); if( nType == DD_PALTYPE_PAL ) return LoadPalettePAL( m_strPalette ); else if( nType == DD_PALTYPE_BMP ) return LoadPalette( m_strPalette ); return FALSE; } // set palette to primary surface // if color depth is higher than 256, this may result an unkown error // return value : TRUE if succeeded BOOL CDDPalette::SetPalette( void ) { HRESULT ddrval; if ( m_lpPalette ) { PALETTEENTRY pe[256]; if(m_lpPalette->GetEntries( 0, 0, 256, pe ) != DD_OK) { // get source palette entries OutputDebugString( "CDDPalette SetPalette Error(0): Cannot get entries!\n" ); return FALSE; } if(DD_lpDDPal->SetEntries( 0, 0, 256, pe ) != DD_OK) { // set to global palette object OutputDebugString( "CDDPalette SetPalette Error(1): Cannot set entries!\n" ); return FALSE; } ddrval = DD_lpDDSFront->SetPalette( DD_lpDDPal ); if( ddrval == DDERR_SURFACELOST ) { if( DD_RestoreScreen() == FALSE ) { return FALSE; } return TRUE; } else if( ddrval == DD_OK ) { return TRUE; } else { int nErr = -1; switch( ddrval ) { case DDERR_GENERIC : nErr = 0; break; case DDERR_INVALIDOBJECT : nErr = 1; break; case DDERR_INVALIDPARAMS : nErr = 2; break; case DDERR_INVALIDSURFACETYPE : nErr = 3; break; case DDERR_NOEXCLUSIVEMODE : nErr = 4; break; case DDERR_NOPALETTEATTACHED : nErr = 5; break; case DDERR_NOPALETTEHW : nErr = 6; break; case DDERR_NOT8BITCOLOR : nErr = 7; break; case DDERR_SURFACELOST : nErr = 8; break; case DDERR_UNSUPPORTED : nErr = 9; break; case 0x88760091: // the palette cannot be initialized under high // color or True color mode nErr = 10; break; } OutputDebugString( "CDDPalette SetPalette Error(2): Set palette error!\n" ); return DD_initFail(hwndGame, DD_ERROR_ID+30+nErr); } } OutputDebugString( "CDDPalette SetPalette Error(3): No palette pointer at all!\n" ); return FALSE; } // release palette object void CDDPalette::Release( void ) { if( DD_lpDD == NULL ) return; m_nType = -1; if( m_lpPalette ) { // reset current palette to NULL if( m_lpPalette == DD_lpDDPal ) DD_lpDDPal = NULL; // delete palette object from global array for( int j=0 ; j Release(); m_lpPalette = NULL; } } ////////////////////////////// // local functions ////////////////////////////// // get remained video memory, for debug version only void DD_testVideoMemory() { DDCAPS capsDRV, capsHEL; capsDRV.dwSize = sizeof( DDCAPS ); capsHEL.dwSize = sizeof( DDCAPS ); if( DD_lpDD->GetCaps( &capsDRV, &capsHEL ) == DD_OK ) { char strVideo[128]; wsprintf( strVideo, "DD_testVideoMemory: %d, %d\n", capsDRV.dwVidMemTotal, capsDRV.dwVidMemFree ); //OutputDebugString( strVideo ); } } // get blitter error when using BltFast() and Blt(), // not all the errors are here // ddrval : error number returned by BltFast() and Blt() void DD_getBltError( char * strHead, int ddrval ) { char msg[128]; if( strlen( strHead ) > 65 ) return; strcpy( msg, strHead ); strcat( msg, ": " ); switch( ddrval ) { case DDERR_EXCEPTION : strcat( msg, "Exception" ); break; case DDERR_GENERIC : strcat( msg, "Generic" ); break; case DDERR_INVALIDOBJECT : strcat( msg, "Invalid Object" ); break; case DDERR_INVALIDPARAMS : strcat( msg, "Invalid Params" ); break; case DDERR_INVALIDRECT : strcat( msg, "Invalid Rect" ); break; case DDERR_NOBLTHW : strcat( msg, "No Blitter HardWare" ); break; case DDERR_SURFACEBUSY : strcat( msg, "Surface Busy" ); break; case DDERR_SURFACELOST : strcat( msg, "Surface Lost" ); break; case DDERR_UNSUPPORTED : strcat( msg, "This Operation is Unsupported" ); break; default: strcat( msg, "I don\'t know this" ); } strcat( msg, " Error!\n" ); // WriteLogFile( "DDApi.log", msg ); OutputDebugString( msg ); } //////////////////////////////