📄 ddrawdisplay.c
字号:
return false;
}
}
}
return true;
}
//my best guess for best performance is fast, blt, flip
//dma is off for now because it ran horribly on the machine
//I tested it on. If people get 500mhz agp bus action in a few
//years it might be useful perhaps
static bool DDRAWDisplay_SetMode(DDRAWDisplay *D, int width, int height, int bpp, uint flags)
{
HRESULT dDriveral;
DDSURFACEDESC2 ddsd;
DDSCAPS2 ddscaps;
assert( DDRAWDisplay_IsValid(D)!=false );
D->ModeFlags = 0;
dDriveral =D->DLL.lpDD4->lpVtbl->SetDisplayMode(D->DLL.lpDD4, width, height, bpp, 0, 0);
D->Height =height;
D->Width =width;
D->BitsPerPixel =bpp;
if(!(flags & MODEXMODE))
{
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags =DDSD_CAPS;
ddsd.ddsCaps.dwCaps =DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
dDriveral =D->DLL.lpDD4->lpVtbl->CreateSurface(D->DLL.lpDD4, &ddsd, &D->lpDDSPrimary, NULL);
if(dDriveral==DD_OK)
{
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags =DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps =DDSCAPS_SYSTEMMEMORY;
//ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
ddsd.dwHeight =height;
ddsd.dwWidth =width;
dDriveral =D->DLL.lpDD4->lpVtbl->CreateSurface(D->DLL.lpDD4, &ddsd, &D->lpDDSBack, NULL);
if(dDriveral==DD_OK)
{
//both were created, make sure they are in vidram
memset(&ddscaps, 0, sizeof(DDSCAPS2));
D->lpDDSPrimary->lpVtbl->GetCaps(D->lpDDSPrimary, &ddscaps);
if(ddscaps.dwCaps & DDSCAPS_VIDEOMEMORY)
{
memset(&ddscaps, 0, sizeof(DDSCAPS2));
D->lpDDSBack->lpVtbl->GetCaps(D->lpDDSBack, &ddscaps);
if(ddscaps.dwCaps & DDSCAPS_VIDEOMEMORY)
{
//both are good to go
D->ModeFlags |=VIDEO;
//mark fastblt unless it's stretching
if(!(flags & STRETCHMODE))
{
D->ModeFlags |=FASTBLT;
}
}
}
}
}
#pragma message ("this cant be set can it?")
else if(!(D->ModeFlags & VIDEO) && !(D->ModeFlags & STRETCHMODE))
{
if(D->lpDDSBack) D->lpDDSBack->lpVtbl->Release(D->lpDDSBack);
if(D->lpDDSPrimary) D->lpDDSPrimary->lpVtbl->Release(D->lpDDSPrimary);
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags =DDSD_CAPS;
ddsd.ddsCaps.dwCaps =DDSCAPS_PRIMARYSURFACE;
dDriveral =D->DLL.lpDD4->lpVtbl->CreateSurface(D->DLL.lpDD4, &ddsd, &D->lpDDSPrimary, NULL);
if(dDriveral==DD_OK)
{
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags =DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.dwHeight =height;
ddsd.dwWidth =width;
dDriveral =D->DLL.lpDD4->lpVtbl->CreateSurface(D->DLL.lpDD4, &ddsd, &D->lpDDSBack, NULL);
if(dDriveral==DD_OK)
{
//both were created good enough
D->ModeFlags |=SYSTEM|SAFEBLT;
}
}
}
} //flip
if((flags & MODEXMODE) || D->lpDDSBack==NULL)
{
if(D->lpDDSBack) D->lpDDSBack->lpVtbl->Release(D->lpDDSBack);
if(D->lpDDSPrimary) D->lpDDSPrimary->lpVtbl->Release(D->lpDDSPrimary);
//try flip
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags =DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps =DDSCAPS_PRIMARYSURFACE |
DDSCAPS_COMPLEX | DDSCAPS_FLIP;
ddsd.dwBackBufferCount =1;
dDriveral =D->DLL.lpDD4->lpVtbl->CreateSurface(D->DLL.lpDD4, &ddsd, &D->lpDDSPrimary, NULL);
if(dDriveral==DD_OK)
{
memset(&ddscaps, 0, sizeof(DDSCAPS2));
ddscaps.dwCaps =DDSCAPS_BACKBUFFER;
dDriveral =D->lpDDSPrimary->lpVtbl->GetAttachedSurface(D->lpDDSPrimary, &ddscaps, &D->lpDDSBack);
if(dDriveral==DD_OK)
{
D->ModeFlags |=SYSTEM|FLIP;
}
else
{
geErrorLog_AddString(-1,"Unable to create primary buffer",NULL);
return false;
}
}
}
return true;
}
DDRAWDisplay *DDRAWDisplay_Create(HWND hwnd, int Width, int Height, int BPP, uint Flags)
{
DDRAWDisplay *D = NULL;
HRESULT dDriveral = 0;
D = malloc(sizeof(DDRAWDisplay));
if (D == NULL)
{
geErrorLog_AddString(-1,"Failed to create DDRAWDisplay object",NULL);
return NULL;
}
memset(D,0,sizeof(DDRAWDisplay));
if (DDRAWDisplay_LoadDLL(&(D->DLL))==false)
{
geErrorLog_AddString(-1,"failed to load ddraw dll",NULL);
goto Create_ERROR;
}
D->hWnd = hwnd;
D->bActive = false;
dDriveral =D->DLL.lpDD4->lpVtbl->SetCooperativeLevel(D->DLL.lpDD4, hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if(dDriveral!=DD_OK)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Create: failed to set cooperative level. ", D3DErrorToString(dDriveral));
goto Create_ERROR;
}
if (DDRAWDisplay_SetMode(D, Width, Height, BPP, Flags)==false)
{
geErrorLog_AddString(-1,"Failed to create buffers",NULL);
goto Create_ERROR;
}
assert( DDRAWDisplay_IsValid(D)!=false );
return D;
Create_ERROR:
if (D)
{
DDRAWDisplay_UnloadDLL(&(D->DLL));
free(D);
}
return NULL;
}
bool DDRAWDisplay_GetPixelFormat( DDRAWDisplay *D,
//int *pixel_pitch,
int *bytes_per_pixel,
int *R_shift,
uint *R_mask,
int *R_width,
int *G_shift,
uint *G_mask,
int *G_width,
int *B_shift,
uint *B_mask,
int *B_width)
{
DDPIXELFORMAT ddpf;
uint i, j;
assert( DDRAWDisplay_IsValid(D)!=false );
//assert( pixel_pitch != NULL );
assert( bytes_per_pixel != NULL );
assert( R_shift != NULL );
assert( R_mask != NULL );
assert( R_width != NULL );
assert( G_shift != NULL );
assert( G_mask != NULL );
assert( G_width != NULL );
assert( B_shift != NULL );
assert( B_mask != NULL );
assert( B_width != NULL );
ddpf.dwSize =sizeof(ddpf);
D->lpDDSPrimary->lpVtbl->GetPixelFormat(D->lpDDSPrimary, &ddpf);
if(!(ddpf.dwFlags & DDPF_RGB))
{
return false;
}
*bytes_per_pixel =ddpf.dwRGBBitCount / 8;
*R_mask =ddpf.dwRBitMask;
*G_mask =ddpf.dwGBitMask;
*B_mask =ddpf.dwBBitMask;
for(j=0,i=ddpf.dwRBitMask;!(i & 1);i>>=1,j++);
*R_shift =j;
for(j=0,i=ddpf.dwGBitMask;!(i & 1);i>>=1,j++);
*G_shift =j;
for(j=0,i=ddpf.dwBBitMask;!(i & 1);i>>=1,j++);
*B_shift =j;
for(i=(ddpf.dwRBitMask>>*R_shift),*R_width=0;i;i >>= 1, (*R_width)++);
for(i=(ddpf.dwGBitMask>>*G_shift),*G_width=0;i;i >>= 1, (*G_width)++);
for(i=(ddpf.dwBBitMask>>*B_shift),*B_width=0;i;i >>= 1, (*B_width)++);
return true;
}
bool DDRAWDisplay_Wipe(DDRAWDisplay *D,uint color)
{
DDSURFACEDESC2 ddsd;
int Width, Height;
assert( DDRAWDisplay_IsValid(D)!=false );
if(!D->bActive)
{
return false;
}
if (!D->Locked)
{
geErrorLog_AddString(-1,"DDRAWDisplay_Wipe: surface not locked",NULL );
return false;
}
memset(&ddsd, 0, sizeof(DDSCAPS2));
ddsd.dwSize =sizeof(ddsd);
ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
#pragma message ("this may not be necessary")
D->lpDDSBack->lpVtbl->GetSurfaceDesc(D->lpDDSBack, &ddsd);
Width =ddsd.dwWidth;
Height =ddsd.dwHeight;
memset(D->Buffer, color, (Height*D->Pitch));
return true;
}
bool DDRAWDisplay_SetActive(DDRAWDisplay *D, bool wParam)
{
assert( D != NULL );
D->bActive =wParam;
if(D->bActive)
{
if(D->lpDDSPrimary->lpVtbl->IsLost(D->lpDDSPrimary)==DDERR_SURFACELOST)
{
if(DDRAWDisplay_RestoreAll(D)!=false)
{
ShowWindow(D->hWnd, SW_SHOWNORMAL); //dx doesn't restore it
}
else
{
geErrorLog_AddString(-1,"DDRAWDisplay_SetActive: Couldn't restore surfaces",NULL);
return false;
}
}
}
return true;
}
// -----------------------------------------------------------
static HRESULT WINAPI DDRAWDisplay_ModeCallback(LPDDSURFACEDESC2 pdds, LPVOID lParam)
{
DisplayModeInfo *Info =(DisplayModeInfo *)lParam;
#pragma message ("only 16 bit display is supported")
if(pdds->ddpfPixelFormat.dwRGBBitCount==16)
{
DisplayModeInfo_AddEntry(Info,
pdds->dwWidth,
pdds->dwHeight,
pdds->ddpfPixelFormat.dwRGBBitCount,
pdds->ddpfPixelFormat.dwRGBBitCount);
}
return S_FALSE;
}
bool DDRAWDisplay_GetDescriptionString(char *DescriptionString, unsigned int DescriptionStringMaxLength)
{
DDRAWDisplay_DLLHooks DLL={NULL,0};
DDDEVICEIDENTIFIER DDDeviceIdentifier;
HRESULT hRet;
assert( DescriptionString != NULL );
if (DDRAWDisplay_LoadDLL(&DLL)==false)
{
geErrorLog_AddString(-1,"unable to load ddraw dll",NULL);
goto GetDescriptionString_ERROR;
}
memset(&DDDeviceIdentifier, 0, sizeof(DDDeviceIdentifier));
hRet =DLL.lpDD4->lpVtbl->GetDeviceIdentifier(DLL.lpDD4, &DDDeviceIdentifier,0);
if(hRet != DD_OK)
{
geErrorLog_AddString(-1,"DDRAWDisplay_GetDescriptionString: ddraw GetDeviceIdentifier() failed", NULL);
goto GetDescriptionString_ERROR;
}
DDRAWDisplay_UnloadDLL(&DLL);
if (strlen(DDDeviceIdentifier.szDescription) + strlen(DDRAWDISPLAY_DESCRIPTION_STRING) >= DescriptionStringMaxLength)
{
geErrorLog_AddString(-1,"DDRAWDisplay_GetDescriptionString: description string too short",NULL);
goto GetDescriptionString_ERROR;
}
strcpy(DescriptionString,DDRAWDISPLAY_DESCRIPTION_STRING);
//strcat(DescriptionString,DDDeviceIdentifier.szDescription);
return true;
//------
GetDescriptionString_ERROR:
DDRAWDisplay_UnloadDLL(&DLL);
return false;
}
bool DDRAWDisplay_GetDisplayInfo( char *DescriptionString,
unsigned int DescriptionStringMaxLength,
DisplayModeInfo *Info)
{
DDDEVICEIDENTIFIER DDDeviceIdentifier;
DDRAWDisplay_DLLHooks DLL={NULL,0};
HRESULT dDriveral = 0;
assert( Info != NULL );
if (DDRAWDisplay_LoadDLL( &DLL )==false)
{
geErrorLog_AddString(-1,"failed to load DDRAW dll",NULL);
return false;
}
#if 0
{
//test for general dma support
DDCAPS ddcaps;
memset(&ddcaps, 0, sizeof(DDCAPS));
ddcaps.dwSize =sizeof(ddcaps);
DLL.lpDD4->lpVtbl->GetCaps(DLL.lpDD4, &ddcaps, NULL);
if(ddcaps.dwCaps & DDCAPS_CANBLTSYSMEM)
{
//System to video blits supported
if(ddcaps.dwSVBCaps & DDCAPS_BLTQUEUE)
{
D->bDMA =TRUE; // DMA Asynch System to Video blits supported
}
}
}
#endif
#if 0 // need this?
dDriveral =DLL.lpDD4->lpVtbl->SetCooperativeLevel(DLL.lpDD4, ActiveWnd,
DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if(dDriveral != DD_OK)
{
geErrorLog_Add(-1,"Failed to set Cooperative Level",NULL);
goto GetDisplayInfo_ERROR;
}
#endif
memset(&DDDeviceIdentifier, 0, sizeof(DDDeviceIdentifier));
dDriveral =DLL.lpDD4->lpVtbl->GetDeviceIdentifier(DLL.lpDD4, &DDDeviceIdentifier,0);
if(dDriveral != DD_OK)
{
geErrorLog_AddString(-1,"ddraw GetDeviceIdentifier() failed", NULL);
goto GetDisplayInfo_ERROR;
}
if (strlen(DDDeviceIdentifier.szDescription) + strlen(DDRAWDISPLAY_DESCRIPTION_STRING) >= DescriptionStringMaxLength)
{
geErrorLog_AddString(-1,"description string too short",NULL);
goto GetDisplayInfo_ERROR;
}
strcpy(DescriptionString,DDRAWDISPLAY_DESCRIPTION_STRING);
// strcat(DescriptionString,DDDeviceIdentifier.szDescription);
DLL.lpDD4->lpVtbl->EnumDisplayModes(DLL.lpDD4, 0, NULL, (LPVOID)Info, DDRAWDisplay_ModeCallback);
DDRAWDisplay_UnloadDLL(&DLL);
return true;
GetDisplayInfo_ERROR:
DDRAWDisplay_UnloadDLL(&DLL);
return false;
}
bool DDRAWDisplay_UpdateWindow( DDRAWDisplay *D )
{
// can't do this with full screen modes.
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -