// CDirectX.cpp : Defines the entry point for the DLL application.
//
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
//#include "stdafx.h"
#include "CDirectX.hpp"
#include <windows.h>
#include <commctrl.h>
#include "CDirectX\resourceppc.h"
#include "CDirectX\SetDisplayMode.h"
CCDirectX::CCDirectX()
{
register int loop;
lpDirectDraw=NULL;
for (loop=0; loop<MAX_SURFACES; loop++)
{
surfaces[loop]=NULL;
}
memset(&driverCaps,(char) NULL,sizeof(driverCaps));
memset(&emulatorCaps,(char) NULL,sizeof(emulatorCaps));
m_displayWidth=0;
m_displayHeight=0;
m_hasFlipSurface=false;
m_hasBackBuffer=false;
m_usingPortrait=false;
}
CCDirectX::~CCDirectX()
{
destroy();
}
void CCDirectX::destroy(void)
{
register int loop;
for (loop=0; loop<MAX_SURFACES; loop++)
{
if (surfaces[loop])
{
surfaces[loop]->Release();
surfaces[loop]=NULL;
}
}
if (lpDirectDraw)
{
lpDirectDraw->Release();
lpDirectDraw=NULL;
}
}
HRESULT CCDirectX::initialise(HWND hWnd,DWORD flag)
{
HRESULT hRet;
hRet=DirectDrawCreate(NULL, &lpDirectDraw, NULL);
if (SUCCEEDED(hRet))
{
hRet=lpDirectDraw->SetCooperativeLevel((hWnd==NULL ? GetActiveWindow() : hWnd),flag);
if (SUCCEEDED(hRet))
{
lpDirectDraw->GetCaps(&driverCaps,&emulatorCaps);
m_hasBackBuffer=driverCaps.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER ? true : false;
m_hasFlipSurface=driverCaps.ddsCaps.dwCaps & DDSCAPS_FLIP ? true : false;
getDisplayMode();
getOrientation(); // Get the display orientation
setColourKey(0);
}
}
return (hRet);
}
HRESULT CCDirectX::listScreenModes(LPVOID lpContext,
HRESULT (*enumerateFunctions)(LPDDSURFACEDESC lpSurfaceDesc,
LPVOID lpContext))
{
// Change context to a list of structs... To do
return (lpDirectDraw->EnumDisplayModes(0,NULL,lpContext,enumerateFunctions));
}
HRESULT CCDirectX::enumerateSurfaces(LPDIRECTDRAWSURFACE pSurface,
LPDDSURFACEDESC lpSurfaceDesc,
LPVOID lpContext)
{
*((LPDIRECTDRAWSURFACE *) lpContext) = pSurface;
return DDENUMRET_OK;
}
HRESULT CCDirectX::createSurfaces(bool useTriple)
{
DDSURFACEDESC ddsd;
HRESULT hRet;
if (lpDirectDraw==NULL) return (DDERR_NOTFOUND);
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP;
ddsd.dwBackBufferCount = (useTriple ? 2 : 1);
hRet = lpDirectDraw->CreateSurface(&ddsd, &surfaces[PRIMARY_SURFACE], NULL);
if (SUCCEEDED(hRet))
{
// Update the enumerator function later on to be able to handle more surfaces...
hRet=surfaces[PRIMARY_SURFACE]->EnumAttachedSurfaces(&surfaces[SECONDARY_SURFACE],enumerateSurfaces);
}
return (hRet);
}
HRESULT CCDirectX::CLS(DWORD colour)
{
DDBLTFX ddbltfx;
HRESULT hResult;
if (surfaces[SECONDARY_SURFACE]==NULL) return (DDERR_NOTFOUND);
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = colour;
while (surfaces[SECONDARY_SURFACE]->GetFlipStatus(DDGFS_ISFLIPDONE) == DDERR_WASSTILLDRAWING) ;
while (true)
{
hResult=surfaces[SECONDARY_SURFACE]->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx);
if (SUCCEEDED(hResult))
{
return hResult;
}
if(hResult == DDERR_SURFACELOST )
{
if (FAILED(restoreLostSurfaces()))
{
}
break;
}
if(hResult != DDERR_WASSTILLDRAWING )
{
break;
}
}
return hResult;
}
HRESULT CCDirectX::flip(DWORD flag)
{
HRESULT hRet;
if (lpDirectDraw==NULL || surfaces[PRIMARY_SURFACE]==NULL) return (DDERR_NOTFOUND);
while(surfaces[PRIMARY_SURFACE]->GetFlipStatus(DDGFS_ISFLIPDONE) == DDERR_WASSTILLDRAWING) ;
while (true)
{
hRet = surfaces[PRIMARY_SURFACE]->Flip(NULL, flag);
if (SUCCEEDED(hRet))
{
Sleep(13);
break;
}
else
{
if (hRet==DDERR_SURFACELOST)
{
if (FAILED(restoreLostSurfaces()))
{
break;
}
}
if (hRet!=DDERR_WASSTILLDRAWING)
{
break;
}
}
}
return (hRet);
}
HBITMAP CCDirectX::GetBitmapHandle(HINSTANCE hInstance, LPCTSTR szBitmap)
{
register HBITMAP hbm;
hbm = (HBITMAP) LoadImage(hInstance, szBitmap, IMAGE_BITMAP, 0, 0, 0);
if (hbm == NULL)
{
hbm = (HBITMAP) LoadImage(NULL,szBitmap,IMAGE_BITMAP, 0, 0, 0);
}
return (hbm);
}
HRESULT CCDirectX::CopyBitmap(IDirectDrawSurface * pdds, HBITMAP hbm, int x, int y, int dx, int dy)
{
HDC hdcImage;
HDC hdc;
BITMAP bm;
DDSURFACEDESC ddsd;
HRESULT hr;
if (hbm == NULL || pdds == NULL)
{
return E_FAIL;
}
//
// Select bitmap into a memoryDC so we can use it.
//
hdcImage = CreateCompatibleDC(NULL);
if (hdcImage==NULL)
{
return E_FAIL;
}
SelectObject(hdcImage, hbm);
//
// Get size of the bitmap
//
GetObject(hbm, sizeof(bm), &bm);
dx = dx == 0 ? bm.bmWidth : dx; // Use the passed size, unless zero
dy = dy == 0 ? bm.bmHeight : dy;
//
// Get size of surface.
//
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
pdds->GetSurfaceDesc(&ddsd);
if (SUCCEEDED(pdds->GetDC(&hdc)))
{
if (StretchBlt(hdc,0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y,dx, dy, SRCCOPY)==false)
{
hr = E_FAIL;
}
pdds->ReleaseDC(hdc);
}
DeleteDC(hdcImage);
return hr;
}
struct __BLIT *CCDirectX::LoadBlitObject(HINSTANCE hInstance, LPCTSTR szBitmap,DWORD width,DWORD height)
{
HBITMAP hbm;
BITMAP bm;
DDSURFACEDESC ddsd;
IDirectDrawSurface * pdds;
struct __BLIT *blit;
if ((blit=new struct __BLIT)==NULL)
{
return (NULL);
}
//
// Get a handle to the bitmap.
//
hbm = GetBitmapHandle(hInstance,szBitmap);
if (hbm == NULL)
{
return NULL;
}
//
// Get size of the bitmap
//
GetObject(hbm, sizeof(bm), &bm);
//
// Create a DirectDrawSurface for this bitmap
//
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
ddsd.dwWidth = bm.bmWidth;
ddsd.dwHeight = bm.bmHeight;
if (FAILED(lpDirectDraw->CreateSurface(&ddsd, &pdds, NULL)))
{
return NULL;
}
if (FAILED(CopyBitmap(pdds, hbm, 0, 0, width,height)))
{
pdds->Release();
pdds=NULL;
}
//DeleteObject(hbm);
blit->image=pdds;
blit->width=(width==0 ? bm.bmWidth : width);
blit->height=(height==0 ? bm.bmHeight : height);
blit->bitmap=hbm;
return blit;
}
void CCDirectX::FreeBlitObject(struct __BLIT *blit)
{
if (blit)
{
if (blit->bitmap) DeleteObject(blit->bitmap);
if (blit->image) blit->image->Release();
free(blit);
}
}
void CCDirectX::setColourKey(DWORD colour)
{
colourKey.dwColorSpaceHighValue=HIWORD(colour);
colourKey.dwColorSpaceLowValue=LOWORD(colour);
}
HRESULT CCDirectX::Blit(DWORD x,DWORD y,struct __BLIT *source,DWORD flags)
{
DDBLTFX ddbltfx;
RECT pos;
HRESULT hResult;
if ((source==NULL) || (source->image==NULL)) return (DDERR_GENERIC);
pos.top=y;
pos.left=x;
pos.right=pos.left+source->width;
pos.bottom=pos.top+source->height;
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
memcpy(&ddbltfx.ddckSrcColorkey,&colourKey,sizeof(ddbltfx.ddckSrcColorkey));
ddbltfx.dwROP = SRCCOPY;
while (1) {
hResult=surfaces[SECONDARY_SURFACE]->Blt(&pos,source->image,NULL,flags,&ddbltfx);
if (SUCCEEDED(hResult))
{
return hResult;
}
if(hResult == DDERR_SURFACELOST )
{
if (FAILED(restoreLostSurfaces()))
{
}
break;
}
if(hResult != DDERR_WASSTILLDRAWING )
{
break;
}
};
return hResult;
}
HRESULT CCDirectX::Blit(RECT *pos,struct __BLIT *source,RECT *sourceRect,DWORD flags)
{
DDBLTFX ddbltfx;
HRESULT hResult;
if ((source==NULL) || (source->image==NULL) || (lpDirectDraw==NULL)) return (DDERR_GENERIC);
while (surfaces[PRIMARY_SURFACE]->GetBltStatus(DDGBS_ISBLTDONE)==DDERR_WASSTILLDRAWING);
if (pos->right==0) pos->right=pos->left+source->width;
if (pos->bottom==0) pos->bottom=pos->top+source->height;
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
memcpy(&ddbltfx.ddckSrcColorkey,&colourKey,sizeof(ddbltfx.ddckSrcColorkey));
ddbltfx.dwROP = SRCCOPY;
while (1) {
hResult=surfaces[SECONDARY_SURFACE]->Blt(pos,source->image,sourceRect,flags,&ddbltfx);
if (SUCCEEDED(hResult))
{
return hResult;
}
if(hResult == DDERR_SURFACELOST )
{
if (FAILED(restoreLostSurfaces()))
{
break;
}
break;
}
if(hResult != DDERR_WASSTILLDRAWING )
{
break;
}
};
return hResult;
}
HRESULT CCDirectX::restoreLostSurfaces(void)
{
if (surfaces[PRIMARY_SURFACE]==NULL) return (DDERR_NOTFOUND);
return (surfaces[PRIMARY_SURFACE]->Restore());
}
HRESULT CCDirectX::getCaps(void)
{
if (lpDirectDraw==NULL) return (DDERR_NOTFOUND);
return (lpDirectDraw->GetCaps(&m_caps,&m_helCaps));
}
HRESULT CCDirectX::setDisplayMode(DWORD width,DWORD height,DWORD bpp,DWORD refreshRate)
{
HRESULT hRet;
if (lpDirectDraw==NULL) return (DDERR_NOTFOUND);
hRet=lpDirectDraw->SetDisplayMode(width,height,bpp,refreshRate,0);
if (SUCCEEDED(hRet))
{
return (getDisplayMode()); // Update display width, height etc
}
return (hRet);
}
DWORD CCDirectX::setDisplayMode(struct __SURFACEINFO *surfaceInfo,struct __SURFACEINFO *store,
DWORD *isPortrait,DWORD change)
{
CSetDisplayMode displayMode;
if (lpDirectDraw==NULL || surfaceInfo==NULL || store==NULL || isPortrait==false)
{
return (false);
}
displayMode.initialise(surfaceInfo,store,isPortrait);
if (displayMode.DoModal()==IDOK)
{
if (change)
{
// Change the screen mode
if (SUCCEEDED(setDisplayMode(store->width,store->height,
store->bpp,store->refreshRate)))
{
getDisplayMode(); // Update screen details
return (true);
}
return (false);
}
return true;
}
return false;
}
void CCDirectX::getOrientation(void)
{
int theScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN);
int theScreenHeight = GetSystemMetrics(SM_CYFULLSCREEN);
m_usingPortrait=(theScreenWidth > theScreenHeight ? false : true);
}
HRESULT CCDirectX::getDisplayMode(void)
{
DDSURFACEDESC surfaceDesc;
HRESULT hRet;
hRet=lpDirectDraw->GetDisplayMode(&surfaceDesc);
if (SUCCEEDED(hRet))
{
m_displayWidth=surfaceDesc.dwWidth;
m_displayHeight=surfaceDesc.dwHeight;
m_refreshRate=surfaceDesc.dwRefreshRate;
m_bpp=surfaceDesc.ddpfPixelFormat.dwRGBBitCount;
}
return (hRet);
}
HRESULT CCDirectX::Print(TCHAR *text,DWORD x,DWORD y,HWND hWnd)
{
HDC hDC;
HRESULT hResult;
hResult=surfaces[SECONDARY_SURFACE]->GetDC(&hDC);
if (SUCCEEDED(hResult))
{
// SetBkColor(hDC, RGB(0, 0, 255));
// SetTextColor(hDC, RGB(255, 255, 0));
//GetClientRect(hWnd, &rc);
ExtTextOut(hDC,x,y,ETO_OPAQUE,NULL,text,lstrlen(text),NULL);
surfaces[SECONDARY_SURFACE]->ReleaseDC(hDC);
}
return (hResult);
}
and my main game loop looks like :
memset(&msg,(char) NULL,sizeof(msg));
while (msg.message!=WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
directX.CLS(0);
state=processDisplay(state,tileWidth,tileHeight,&level,(struct __SETUP *) &setup,hWnd);
timer.updateTimer();
directX.flip();
}
} |