📄 ddrawdisplay.c
字号:
/****************************************************************************************/
/* DDRAWDisplay.C */
/* */
/* Author: Mike Sandige */
/* Description: display surface manager for full screen Direct Draw using a direct */
/* draw surface for the the frame buffer */
/* */
/* The contents of this file are subject to the Genesis3D Public License */
/* Version 1.0 (the "License"); you may not use this file except in */
/* compliance with the License. You may obtain a copy of the License at */
/* http://www.genesis3d.com */
/* */
/* Software distributed under the License is distributed on an "AS IS" */
/* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */
/* the License for the specific language governing rights and limitations */
/* under the License. */
/* */
/* The Original Code is Genesis3D, released March 25, 1999. */
/* Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved */
/* */
/****************************************************************************************/
#define DIRECTDRAW_VERSION 0x0400
#pragma warning(disable : 4201 4214 4115)
#include <windows.h>
#include <assert.h>
#include "ddraw.h"
#include <stdio.h>
#pragma warning(default : 4201 4214 4115; disable : 4514)
#include "driver.h"
#include "DDRAWDisplay.h"
#include "errorlog.h"
#include "d3d_err.h"
#undef DEFINE_GUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
DEFINE_GUID( IID_IDirectDraw4, 0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 );
static const char * DDRAWDISPLAY_DESCRIPTION_STRING = "Full Screen ";
typedef struct
{
LPDIRECTDRAW4 lpDD4;
HANDLE ddrawinst;
} DDRAWDisplay_DLLHooks;
typedef struct DDRAWDisplay
{
DDRAWDisplay_DLLHooks DLL;
LPDIRECTDRAWSURFACE4 lpDDSPrimary; // DirectDraw primary surface
LPDIRECTDRAWSURFACE4 lpDDSBack; // DirectDraw back surface
BOOL bActive;
int Width;
int Height;
int BitsPerPixel;
int ModeFlags;
HWND hWnd;
bool Locked;
ubyte *Buffer;
int Pitch;
} DDRAWDisplay;
typedef HRESULT (WINAPI *LPDIRECTDRAWCREATE)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
static bool DDRAWDisplay_IsValid(DDRAWDisplay *D)
{
if ( D == NULL )
return false;
if (D->DLL.ddrawinst == NULL )
return false;
if (D->DLL.lpDD4 == NULL)
return false;
if (D->hWnd == NULL )
return false;
return true;
}
static void DDRAWDisplay_UnloadDLL( DDRAWDisplay_DLLHooks *H )
{
assert( H != NULL );
if (H->lpDD4)
{
H->lpDD4->lpVtbl->Release(H->lpDD4);
H->lpDD4 = NULL;
}
if (H->ddrawinst)
{
FreeLibrary(H->ddrawinst);
H->ddrawinst = NULL;
}
}
static bool DDRAWDisplay_LoadDLL( DDRAWDisplay_DLLHooks *H )
{
LPDIRECTDRAW lpDD = NULL; // DirectDraw object
LPDIRECTDRAWCREATE lpDDCreate = NULL;
HRESULT dDriveral;
assert( H != NULL );
H->ddrawinst = NULL;
H->lpDD4 = NULL;
H->ddrawinst =LoadLibrary("ddraw.dll");
if(!H->ddrawinst)
{
geErrorLog_AddString(-1,"failed to load","ddraw.dll");
goto LoadDLL_ERROR;
}
lpDDCreate =(LPDIRECTDRAWCREATE)GetProcAddress(H->ddrawinst, "DirectDrawCreate");
if(lpDDCreate)
{
dDriveral =lpDDCreate(NULL, &(lpDD), NULL);
if((dDriveral != DD_OK) || ((lpDD)==NULL))
{
geErrorLog_AddString(-1,"ddraw lpDDCreate failed. ", D3DErrorToString(dDriveral));
goto LoadDLL_ERROR;
}
}
else
{
geErrorLog_AddString(-1 ,"Unable to find DirectDrawCreate entry into ddraw.dll",NULL);
goto LoadDLL_ERROR;
}
dDriveral = lpDD->lpVtbl->QueryInterface(lpDD, &IID_IDirectDraw4, (LPVOID *)&(H->lpDD4));
if(dDriveral!=DD_OK)
{
geErrorLog_AddString(-1,"QueryInterface failed. ", D3DErrorToString(dDriveral));
goto LoadDLL_ERROR;
}
lpDD->lpVtbl->Release(lpDD);
lpDD =NULL;
return true;
LoadDLL_ERROR:
if (lpDD != NULL )
{
lpDD->lpVtbl->Release(lpDD);
lpDD =NULL;
}
DDRAWDisplay_UnloadDLL(H);
return false;
}
void DDRAWDisplay_GetDisplayFormat( const DDRAWDisplay *D,
int *Width,
int *Height,
int *BitsPerPixel,
uint *Flags)
{
assert( D != NULL );
assert( Width != NULL );
assert( Height != NULL );
assert( BitsPerPixel != NULL );
assert( Flags != NULL );
*Width = D->Width;
*Height = D->Height;
*BitsPerPixel = D->BitsPerPixel;
*Flags = D->ModeFlags;
}
void DDRAWDisplay_Destroy(DDRAWDisplay **pD)
{
DDRAWDisplay *D;
assert( pD );
assert( DDRAWDisplay_IsValid(*pD)!=false );
D = *pD;
if (D->Locked == true)
DDRAWDisplay_Unlock(D);
if (D->ModeFlags & FLIP)
{
D->lpDDSBack =NULL;
}
else
{
if(D->lpDDSBack)
{
D->lpDDSBack->lpVtbl->Release(D->lpDDSBack);
D->lpDDSBack =NULL;
}
}
if(D->lpDDSPrimary)
{
D->lpDDSPrimary->lpVtbl->Release(D->lpDDSPrimary);
D->lpDDSPrimary =NULL;
}
DDRAWDisplay_UnloadDLL(&(D->DLL));
free(D);
*pD = NULL;
}
static bool DDRAWDisplay_RestoreAll(DDRAWDisplay *D)
{
HRESULT dDriveral;
assert( DDRAWDisplay_IsValid(D)!=false );
dDriveral =D->DLL.lpDD4->lpVtbl->SetCooperativeLevel(D->DLL.lpDD4, D->hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if(dDriveral!=DD_OK)
{
geErrorLog_AddString(-1,"DDRAWDisplay_RestoreAll(): ddraw SetCooperativeLevel. ", D3DErrorToString(dDriveral));
return false;
}
dDriveral =D->DLL.lpDD4->lpVtbl->SetDisplayMode(D->DLL.lpDD4, D->Width, D->Height, D->BitsPerPixel, 0, 0);
if(dDriveral!=DD_OK)
{
geErrorLog_AddString(-1,"DDRAWDisplay_RestoreAll: ddraw SetDisplayMode. ", D3DErrorToString(dDriveral));
return false;
}
dDriveral =D->DLL.lpDD4->lpVtbl->RestoreAllSurfaces(D->DLL.lpDD4);
if(dDriveral!=DD_OK)
{
geErrorLog_AddString(-1,"DDRAWDisplay_RestoreAll: ddraw RestoreAllSurfaces. ", D3DErrorToString(dDriveral));
return false;
}
return true;
}
bool DDRAWDisplay_Lock(DDRAWDisplay *D, ubyte **Buffer, int *Pitch)
{
HRESULT dDriveral;
DDSURFACEDESC2 ddsd;
RECT wrect;
int Forever = 1;
assert( DDRAWDisplay_IsValid(D)!=false );
if(!D->bActive)
return true;
// <> should probably be false, but this stays compatible with the existing convention
assert( Buffer != NULL );
assert( Pitch != NULL );
if (D->Locked != false)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Lock: already locked",NULL );
return false;
}
memset(&ddsd, 0, sizeof(DDSCAPS2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
D->lpDDSBack->lpVtbl->GetSurfaceDesc(D->lpDDSBack, &ddsd);
wrect.left = 0;
wrect.top = 0;
wrect.right = ddsd.dwWidth-1;
wrect.bottom = ddsd.dwHeight-1;
while(Forever)
{
dDriveral =D->lpDDSBack->lpVtbl->Lock(D->lpDDSBack, &wrect, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
if(dDriveral==DD_OK)
{
break;
}
if(dDriveral==DDERR_SURFACELOST)
{
if (DDRAWDisplay_RestoreAll(D) == false)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Lock: lost ddraw surface", NULL);
return false;
}
}
else if(dDriveral!=DDERR_WASSTILLDRAWING)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Lock: was still drawing. ",D3DErrorToString(dDriveral));
return false;
}
}
*Buffer = (ubyte *)ddsd.lpSurface;
*Pitch = ddsd.lPitch;
D->Locked = true;
D->Buffer = *Buffer;
D->Pitch = *Pitch;
return true;
}
bool DDRAWDisplay_Unlock(DDRAWDisplay *D)
{
int Forever=1;
HRESULT dDriveral =DD_OK;
assert( DDRAWDisplay_IsValid(D)!=false );
if(!D->bActive)
return true;
// <> should probably be false, but this stays compatible with the existing convention
if (D->Locked != true)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Unlock: surface not locked",NULL);
return false;
}
D->Locked = false;
while(Forever)
{
dDriveral =D->lpDDSBack->lpVtbl->Unlock(D->lpDDSBack, NULL);
if(dDriveral==DD_OK)
break;
#pragma message (" can you loose a locked surface?")
if(dDriveral==DDERR_SURFACELOST)
{
if (DDRAWDisplay_RestoreAll(D) == false)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Unlock: surface lost\n",NULL);
return false;
}
}
else if(dDriveral!=DDERR_WASSTILLDRAWING)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Unlock: was still drawing. ",D3DErrorToString(dDriveral));
return false;
}
}
D->Locked = false;
return true;
}
bool DDRAWDisplay_Blit(DDRAWDisplay *D)
{
HRESULT dDriveral;
DDSURFACEDESC2 ddsd;
RECT rDest, rSrc;
int Forever=1;
assert( DDRAWDisplay_IsValid(D)!=false );
if(!D->bActive)
{
return true;
}
memset(&ddsd, 0, sizeof(DDSCAPS2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
D->lpDDSBack->lpVtbl->GetSurfaceDesc(D->lpDDSBack, &ddsd);
rDest.left =rDest.top =0;
rDest.right =ddsd.dwWidth-1;
rDest.bottom=ddsd.dwHeight-1;
memset(&ddsd, 0, sizeof(DDSCAPS2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
D->lpDDSPrimary->lpVtbl->GetSurfaceDesc(D->lpDDSPrimary, &ddsd);
rSrc.left =rSrc.top =0;
rSrc.right =ddsd.dwWidth-1;
rSrc.bottom =ddsd.dwHeight-1;
dDriveral =DD_OK;
if((D->ModeFlags & VIDEO) && (D->ModeFlags & FASTBLT))
{
while(Forever)
{
dDriveral =D->lpDDSPrimary->lpVtbl->BltFast(D->lpDDSPrimary, 0, 0, D->lpDDSBack, NULL, 0);
if(dDriveral==DD_OK)
{
break;
}
if(dDriveral==DDERR_SURFACELOST)
{
if (DDRAWDisplay_RestoreAll(D) == false)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Blit: lost surface",NULL);
return false;
}
}
else if(dDriveral!=DDERR_WASSTILLDRAWING)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Blit: was still drawing",NULL);
return false;
}
}
}
else if(D->ModeFlags & FLIP)
{
while(Forever)
{
dDriveral =D->lpDDSPrimary->lpVtbl->Flip(D->lpDDSPrimary, D->lpDDSBack, DDFLIP_NOVSYNC);
if(dDriveral==DD_OK)
{
break;
}
if(dDriveral==DDERR_SURFACELOST)
{
if (DDRAWDisplay_RestoreAll(D)==false)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Blit: lost surface",NULL);
return false;
}
}
else if(dDriveral!=DDERR_WASSTILLDRAWING)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Blit: was still drawing",NULL);
return false;
}
}
}
else //safe blt
{
while(Forever)
{
dDriveral =D->lpDDSPrimary->lpVtbl->Blt(D->lpDDSPrimary, NULL, D->lpDDSBack, NULL, DDBLT_WAIT, NULL);
if(dDriveral==DD_OK)
break;
if(dDriveral==DDERR_SURFACELOST)
{
if (DDRAWDisplay_RestoreAll(D)==false)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Blit: lost surface",NULL);
return false;
}
}
else if(dDriveral!=DDERR_WASSTILLDRAWING)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Blit: was still drawing",NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -