From 2186d5f3f95cd74a070a490d899291648d58667a Mon Sep 17 00:00:00 2001 From: Steven Fuller Date: Sun, 1 Jul 2001 00:55:22 +0000 Subject: Initial revision --- 3dc/win95/DD_FUNC.CPP | 2260 ------------------------------------------------- 1 file changed, 2260 deletions(-) delete mode 100644 3dc/win95/DD_FUNC.CPP (limited to '3dc/win95/DD_FUNC.CPP') diff --git a/3dc/win95/DD_FUNC.CPP b/3dc/win95/DD_FUNC.CPP deleted file mode 100644 index 3be2188..0000000 --- a/3dc/win95/DD_FUNC.CPP +++ /dev/null @@ -1,2260 +0,0 @@ -extern "C" { - -#include "3dc.h" -#include "vramtime.h" -#include "dxlog.h" -#include "inline.h" -#include "scrshot.hpp" -#include "awTexLd.h" // to set the surface format for Aw gfx dd surface loads - -#define UseLocalAssert No -#include "ourasert.h" - - -// for 640x480x8 experiment -#define InterlaceExperiment No - - -// In as separate define to debug because we -// might want to leave it even in a published -// game. -#define AllowReboot Yes - -// In as #define since there is no -// obvious good behaviour on failure -#define CheckForModeXInSubWindow No - -// Temporary hack! -#define NoPalette No -extern void TimeStampedMessage(char *s); - -// Nasty hack to try and fix non-appearance of font -// on some machines, probably due to there not being -// enough video memory for the font and BltFast -// not working outside display memory. -// According to Roxby, source colour keying won't work -// on Blt in the Beta 3, so expect a grotty font with this on. -// PS Source colour keying works, but the font -// still doesn't appear on my machine in SubWindow -// mode... Ho hum... -#define NoBltFastOnFont No - - -// Check to see if video mode is valid -// and rewrite it if it isn't reported - -#define CheckVideoMode No - -/* - Globals -*/ - -LPDIRECTDRAW lpDD; // DirectDraw object -LPDIRECTDRAWSURFACE lpDDSPrimary; // DirectDraw primary surface -LPDIRECTDRAWSURFACE lpDDSBack; // DirectDraw back surface -LPDIRECTDRAWSURFACE lpDDSHiddenBack; // for system memory rendering target, stable configuration -LPDIRECTDRAWPALETTE lpDDPal[MaxPalettes]; // DirectDraw palette -#if debug || PreBeta -LPDIRECTDRAWSURFACE lpDDDbgFont; // Debugging font, specific to current video mode -#endif -// For SubWindow mode -LPDIRECTDRAWCLIPPER lpDDClipper; -// DirectDraw gdi surface -LPDIRECTDRAWSURFACE lpDDGDI; -int VideoModeColourDepth; -long BackBufferPitch; -// To describe available video hardware -int TotalVideoMemory; -int NumAvailableVideoModes; -VIDEOMODEINFO AvailableVideoModes[MaxAvailableVideoModes]; -// Must be kept up to date with jump table!!!! -VIDEOMODEINFO EngineVideoModes[] = { - // Mode 320x200x8 - 320, // width - 200, // height - 8, // colour depth (bits per pixel) - // Mode 320x200x8T - 320, // width - 200, // height - 8, // colour depth (bits per pixel) - // Mode 320x200x15 - 320, // width - 200, // height - 16, // colour depth (bits per pixel) - // Mode 320x240x8 - 320, // width - 240, // height - 8, // colour depth (bits per pixel) - // Mode 640x480x8 - 640, // width - 480, // height - 8, // colour depth (bits per pixel) - // Mode 640x480x8T - 640, // width - 480, // height - 8, // colour depth (bits per pixel) - // Mode 640x480x15 - 640, // width - 480, // height - 16, // colour depth (bits per pixel) - // Mode 640x480x24 - 640, // width - 480, // height - 24 // colour depth (bits per pixel) - }; - -// Flag for backdrop composition - -// for 640x480x8 experiment -#if InterlaceExperiment -int oddDraw; -#endif - - -// Surface for Backdrop composition -LPDIRECTDRAWSURFACE lpDDBackdrop; -// Pointer into Backdrop DD surface -unsigned char* BackScreenBuffer; -// Pitch on auxilliary backdrop surface -static long BackScreenPitch; -DDPIXELFORMAT DisplayPixelFormat; - -// For locking against other processes, e.g. -// mouse pointer display -unsigned char GlobalFlipLock = No; - -/* Externs */ - -extern int VideoMode; -extern int VideoModeTypeScreen; -extern int VideoModeType; -extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock; -extern unsigned char *ScreenBuffer; -extern HWND hWndMain; -extern unsigned char LPTestPalette[]; -extern unsigned char TestPalette[]; -extern int WindowMode; -extern WINSCALEXY TopLeftSubWindow; -extern WINSCALEXY ExtentXYSubWindow; -extern int WinWidth; -extern int WinHeight; -extern int WinLeftX; -extern int WinTopY; -extern int WinRightX; -extern int WinBotY; -extern int DXMemoryMode; -extern int RasterisationRequestMode; -extern int DXMemoryRequestMode; -extern int WindowRequestMode; -extern int VideoRequestMode; -extern int ZBufferRequestMode; -extern int SoftwareScanDrawRequestMode; -extern unsigned char AttemptVideoModeRestart; -extern VIDEORESTARTMODES VideoRestartMode; -extern BOOL MMXAvailable; -extern BOOL D3DHardwareAvailable; -extern int cosine[]; -extern int sine[]; - -BOOL really_32_bit = 0; - -void GenerateDirectDrawSurface() - -{ - - DDCAPS ddcaps; - HRESULT ddrval; - DDSURFACEDESC ddsd; - DDSCAPS ddscaps; - unsigned char Mode8T; - - // Check for combination of a MODEX type mode - // and SubWindowing - - #if AllowReboot - // THIS MAY NOT WORK!!! - if (WindowMode == WindowModeSubWindow) - ddrval = lpDD->SetCooperativeLevel(hWndMain, - DDSCL_NORMAL); - else - ddrval = lpDD->SetCooperativeLevel(hWndMain, - DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT ); - - LOGDXERR(ddrval); - #else - // More stable even if crashes cannot be booted - // out of? - if (WindowMode == WindowModeSubWindow) - ddrval = lpDD->SetCooperativeLevel(hWndMain, - DDSCL_NORMAL); - else - ddrval = lpDD->SetCooperativeLevel(hWndMain, - DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX); - LOGDXERR(ddrval); - #endif - - TimeStampedMessage("Allow reboot thingy"); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x2); - } - #else - return; - #endif - - switch (ScreenDescriptorBlock.SDB_ScreenDepth) - { - case VideoModeType_8: - VideoModeColourDepth = 8; - Mode8T = No; - break; - case VideoModeType_15: - VideoModeColourDepth = 16; - Mode8T = No; - break; - case VideoModeType_24: - if (really_32_bit) - VideoModeColourDepth = 32; - else - VideoModeColourDepth = 24; - Mode8T = No; - break; - case VideoModeType_8T: - VideoModeColourDepth = 8; - Mode8T = Yes; - break; - default: - VideoModeColourDepth = 16; // default is 16 bit colour - break; - } - - // Note that SetDisplayMode is now technically part - // of the DirectDraw2 COM interface, not DirectDraw. - // However, as long as we do not wish to change - // monitor refresh rates we do not need to use the - // DirectDraw2 version or set up a separate secondary - // DD interface object, which be just plain fiddly. - - // MAY NOT WORK LIKE THIS IN SUBWINDOW MODE!!!! - if (WindowMode == WindowModeFullScreen) - { - ddrval = lpDD->SetDisplayMode(ScreenDescriptorBlock.SDB_Width, - ScreenDescriptorBlock.SDB_Height, VideoModeColourDepth); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - { - if ((ddrval == DDERR_INVALIDMODE) || - (ddrval == DDERR_GENERIC) || - (ddrval == DDERR_INVALIDPIXELFORMAT)) - { - AttemptVideoModeRestart = Yes; - VideoRestartMode = RestartDisplayModeNotAvailable; - } - return; - } - #endif - } - TimeStampedMessage("after SetDisplayMode"); - - // Create primary surface and back buffer - // IMPORTANT!!! Currently no support for triple - // buffering in SubWindow mode!!! - - if (WindowMode == WindowModeSubWindow) - { - // Create primary - memset(&ddsd,0,sizeof(DDSURFACEDESC)); - ddsd.dwSize = sizeof(DDSURFACEDESC); - ddsd.dwFlags = DDSD_CAPS; - - // Request a 3D capable device so that - // Direct3D accesses will work - // note primary must be in video memory - ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE); - - ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x41); - } - #else - return; - #endif - - // Create back buffer - memset(&ddsd,0,sizeof(DDSURFACEDESC)); - ddsd.dwSize = sizeof(DDSURFACEDESC); - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; - ddsd.dwHeight = ScreenDescriptorBlock.SDB_Height; - ddsd.dwWidth = ScreenDescriptorBlock.SDB_Width; - - // Request a 3D capable device so that - // Direct3D accesses will work - if (DXMemoryMode == SystemMemoryPreferred) - ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE); - else // video memory if possible - ddsd.ddsCaps.dwCaps= (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE); - - ddrval = lpDD->CreateSurface(&ddsd, &lpDDSBack, NULL); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x5); - } - #else - return; - #endif - - // Create clipper objects - ddrval = lpDD->CreateClipper(0, &lpDDClipper, NULL); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x55); - } - #else - return; - #endif - - ddrval = lpDDClipper->SetHWnd(0, hWndMain); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x51); - } - #else - return; - #endif - - ddrval = lpDDSPrimary->SetClipper(lpDDClipper); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x52); - } - #else - return; - #endif - } - else // default to FullScreen... - { - TimeStampedMessage("after 'default to FullScreen'"); - if (DXMemoryMode == VideoMemoryPreferred) - { - ddcaps.dwSize = sizeof (ddcaps); - memset (&ddsd, 0, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - - // Request a 3D capable device so that - // Direct3D accesses will work - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | - DDSCAPS_FLIP | - DDSCAPS_COMPLEX | - DDSCAPS_3DDEVICE; - - ddsd.dwBackBufferCount = 1; - - ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL); - LOGDXERR(ddrval); - TimeStampedMessage("after vm CreateSurface"); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x41); - } - #else - { - // For dubious modex emulation - // problem fix and dubious driver - // cannot change to different bit depths - // fix. - // Note that this must be kept up to date!!!! - if ((ddrval == DDERR_OUTOFVIDEOMEMORY) && - ((VideoMode == VideoMode_DX_320x200x8) || - (VideoMode == VideoMode_DX_320x200x8T) || - (VideoMode == VideoMode_DX_320x240x8) || - (VideoMode == VideoMode_DX_320x200x15))) - { - AttemptVideoModeRestart = Yes; - VideoRestartMode = RestartOutOfVidMemForPrimary; - } - else if ((ddrval == DDERR_INVALIDMODE) || - (ddrval == DDERR_GENERIC) || - (ddrval == DDERR_INVALIDPIXELFORMAT)) - { - AttemptVideoModeRestart = Yes; - VideoRestartMode = RestartDisplayModeNotAvailable; - } - - return; - } - #endif - - // get a pointer to the back buffer - // DO I NEED TO SET A SIZE FIELD HERE?? - // SEEMS I _CAN'T_, ANYWAY... - ddscaps.dwCaps = DDSCAPS_BACKBUFFER; - - ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBack); - LOGDXERR(ddrval); - TimeStampedMessage("after vm GetAttachedSurface"); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x5); - } - #else - return; - #endif - } - // assume we want a system memory - // rendering target, e.g. for MMX - else - { - DDPIXELFORMAT TempPixelFormat; - - // Make primary, with back buffer in video memory - ddcaps.dwSize = sizeof (ddcaps); - memset (&ddsd, 0, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - - // Request a 3D capable device so that - // Direct3D accesses will work - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | - DDSCAPS_FLIP | - DDSCAPS_COMPLEX | - DDSCAPS_3DDEVICE; - - ddsd.dwBackBufferCount = 1; - - ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL); - LOGDXERR(ddrval); - TimeStampedMessage("after vm CreateSurface"); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - { - return; - } - #endif - - // get a pointer to the back buffer - // Note that in this configuration the back - // buffer is hidden from the rendering system, - // since other configurations do not seem to be - // stable in ModeX emulation modes - ddscaps.dwCaps = DDSCAPS_BACKBUFFER; - - ddrval = lpDDSPrimary->GetAttachedSurface( - &ddscaps, - &lpDDSHiddenBack); - LOGDXERR(ddrval); - TimeStampedMessage("after vm GetAttachedSurface"); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - return; - #endif - - // Save pixel format of primary - memcpy(&TempPixelFormat, &ddsd.ddpfPixelFormat, - sizeof(DDPIXELFORMAT)); - TimeStampedMessage("after memcpy 1"); - - // Create rendering target - memset(&ddsd,0,sizeof(DDSURFACEDESC)); - ddsd.dwSize = sizeof(DDSURFACEDESC); - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; - ddsd.dwHeight = ScreenDescriptorBlock.SDB_Height; - ddsd.dwWidth = ScreenDescriptorBlock.SDB_Width; - - // Ensure rendering target has same format as primary - memcpy(&ddsd.ddpfPixelFormat, &TempPixelFormat, - sizeof(DDPIXELFORMAT)); - TimeStampedMessage("after memcpy 2"); - - // Request a 3D capable device so that - // Direct3D accesses will work - ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE); - - ddrval = lpDD->CreateSurface(&ddsd, &lpDDSBack, NULL); - TimeStampedMessage("after CreateSurface"); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - return; - #endif - } - } - - // Set the Colour Palette (paletted modes only) - #if NoPalette - #else - if (VideoModeColourDepth == 8) - { - - TimeStampedMessage("SHOULD NEVER GET HERE"); - - if (WindowMode == WindowModeSubWindow) - // Use system palette in a SubWindow case - { - // Standard windows RGB + flags palette - // structure prototyped in various versions - // (Though not, apparently, others) of objbase.h - PALETTEENTRY SystemPalette[256]; - // Get system palette via GDI device context - HDC hdc = GetDC(NULL); - GetSystemPaletteEntries(hdc, 0, (1 << 8), SystemPalette); - // Restrict system to two palette entries only. - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - ReleaseDC(NULL, hdc); - - // Flag system palette entries - // Will this work? - // I sure hope so... - { - int i; - // Take all but 20 basic entries for our - // greedy little sod of a game window - for (i=0; i<1; i++) - SystemPalette[i].peFlags = PC_EXPLICIT; - for (i=1; i<(256-1); i++) - { - SystemPalette[i].peRed = LPTestPalette[i*4]; - SystemPalette[i].peGreen = LPTestPalette[(i*4)+1]; - SystemPalette[i].peBlue = LPTestPalette[(i*4)+2]; - SystemPalette[i].peFlags = PC_RESERVED; - } - for (i=(256-1); i<256; i++) - SystemPalette[i].peFlags = PC_EXPLICIT; - } - - // Create the palette within DirectDraw, using - // DD palette initialisation rather than ours - ddrval = lpDD->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, - SystemPalette, &lpDDPal[0], NULL); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x7); - } - #else - return; - #endif - - // Set palette on both buffers - ddrval = lpDDSBack->SetPalette(lpDDPal[0]); - LOGDXERR(ddrval); - ddrval = lpDDSPrimary->SetPalette(lpDDPal[0]); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - return; - #endif - // Save palette in internal format for - // use later - // Out because it causes problems with - // window mode swapping. - // ConvertDDToInternalPalette((unsigned char*) SystemPalette, TestPalette, 256); - } - else // default to FullScreen - { - if ((ScreenDescriptorBlock.SDB_Flags - & SDB_Flag_Raw256) || (Mode8T))// full 256 colours - ddrval = lpDD->CreatePalette((DDPCAPS_8BIT | DDPCAPS_ALLOW256), - (LPPALETTEENTRY)(LPTestPalette), - &lpDDPal[0], - NULL); - else // default is 222 - ddrval = lpDD->CreatePalette((DDPCAPS_8BIT), - (LPPALETTEENTRY)(LPTestPalette), - &lpDDPal[0], - NULL); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x7); - } - #else - return; - #endif - - ddrval = lpDDSPrimary->SetPalette(lpDDPal[0]); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x8); - } - #else - return; - #endif - -// Set palette on BOTH buffers to work around -// bug in Direct3D initialisation!!! - ddrval = lpDDSBack->SetPalette(lpDDPal[0]); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(0x8); - } - #else - return; - #endif - } - } - #endif // for NoPalette - - // Get the surface desc for AW DDSurface loads - - memset(&ddsd,0,sizeof ddsd); - ddsd.dwSize = sizeof ddsd; - ddrval = lpDDSPrimary->GetSurfaceDesc(&ddsd); - LOGDXERR(ddrval); - GLOBALASSERT(DD_OK==ddrval); - TimeStampedMessage("after memset"); - AwSetSurfaceFormat(&ddsd); - TimeStampedMessage("after AwSetSurfaceFormat"); - - // Do an initial lock and unlock on the back buffer - // to pull out vital information such as the - // surface description - LockSurfaceAndGetBufferPointer(); - UnlockSurface(); - TimeStampedMessage("after Lock & Unlock"); - -} - -// Lock back buffer and get screen pointer - -void LockSurfaceAndGetBufferPointer() -{ - DDSURFACEDESC ddsdback; - HRESULT ddrval; - int count = 0; - - #if optimiseblit - while (lpDDSBack->GetBltStatus(DDGBS_ISBLTDONE) != DD_OK); - #endif - - memset(&ddsdback, 0, sizeof(ddsdback)); - ddsdback.dwSize = sizeof(ddsdback); - - // DDLOCK_WAIT is another safety option that - // should in theory be removable by using - // the GetBltStatus call above. - // Or of course the while loop... - while ((ddrval = lpDDSBack->Lock(NULL, &ddsdback, DDLOCK_WAIT, NULL)) == DDERR_WASSTILLDRAWING) - { - count++; - if (count>1) // was 10000, for test purposes ONLY!!! - { - LOGDXERR(ddrval); - ReleaseDirect3D(); - exit(0x2001); - } - } - - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - #if debug - ReleaseDirect3D(); - exit(ddrval); - #else - return; - #endif - } - - /* ddsdback now contains my lpSurface)*/ - - ScreenBuffer = (unsigned char *)ddsdback.lpSurface; - BackBufferPitch = ddsdback.lPitch; - - // Get pixel format description of - // rendering target - memcpy(&DisplayPixelFormat, &ddsdback.ddpfPixelFormat, - sizeof(DDPIXELFORMAT)); -} - -void UnlockSurface(void) -{ - HRESULT ddrval; - - ddrval = lpDDSBack->Unlock((LPVOID)ScreenBuffer); - LOGDXERR(ddrval); - - #if debug - if (ddrval != DD_OK) - { - ReleaseDirect3D(); - exit(ddrval); - } - #endif -} - -void FlipBuffers(void) -{ - HRESULT ddrval; - - // for locking against other draw processes, - // e.g. mouse pointer - GlobalFlipLock = Yes; - - // IMPORTANT!!! OptimiseFlip, Blit are - // not supported in SubWindow mode!!! - - if (WindowMode == WindowModeSubWindow) - { - RECT dest; - - // For SubWindow mode, we cannot flip, but - // must instead do a (stretched, in principle) - // blit to the front buffer to combine with GDI - // surfaces. - // The whole back buffer should be taken. - dest.left = WinLeftX; - dest.top = WinTopY; - dest.right = WinRightX; - dest.bottom = WinBotY; - ddrval = lpDDSPrimary->Blt(&dest, lpDDSBack, - NULL, DDBLT_WAIT, NULL); - } - else // default to FullScreen - { - // we hope to flip, and flip to hope - // we are the tumbling jongleurs... - if (DXMemoryMode == VideoMemoryPreferred) - { - #if optimiseflip - while (lpDDSBack->GetFlipStatus(DDGFS_ISFLIPDONE) == DDERR_WASSTILLDRAWING) - ProcessProjectWhileWaitingToBeFlippable(); - #endif - - // we are going to flip with DDFLIP_WAIT on - // even if optimiseflip is set. - // IT'S THE ONLY WAY TO BE SURE. - ddrval = lpDDSPrimary->Flip(NULL, DDFLIP_WAIT); - - while(1) - { - if (ddrval == DD_OK) - break; - if (ddrval == DDERR_SURFACELOST) - { - ddrval = lpDDSPrimary->Restore(); - if (ddrval != DD_OK) - break; - } - if (ddrval != DDERR_WASSTILLDRAWING) - break; - } - } - else // assume system memory rendering target - { - // Take rendering target to back buffer - // Rendering target should map fully onto back buffer - ddrval = lpDDSHiddenBack->Blt(NULL, lpDDSBack, - NULL, DDBLT_WAIT, NULL); - - // And now do a standard flip - #if optimiseflip - while (lpDDSBack->GetFlipStatus(DDGFS_ISFLIPDONE) == DDERR_WASSTILLDRAWING) - ProcessProjectWhileWaitingToBeFlippable(); - #endif - - // we are going to flip with DDFLIP_WAIT on - // even if optimiseflip is set. - // IT'S THE ONLY WAY TO BE SURE. - ddrval = lpDDSPrimary->Flip(NULL, DDFLIP_WAIT); - - while(1) - { - if (ddrval == DD_OK) - break; - if (ddrval == DDERR_SURFACELOST) - { - ddrval = lpDDSPrimary->Restore(); - if (ddrval != DD_OK) - break; - } - if (ddrval != DDERR_WASSTILLDRAWING) - break; - } - } - } - - GlobalFlipLock = No; - - ProjectSpecificBufferFlipPostProcessing(); - - HandleScreenShot(); - - #if InterlaceExperiment - oddDraw ^= 1; - #endif -} - -void InGameFlipBuffers(void) -{ - FlipBuffers(); - return; - HRESULT ddrval; - - // for locking against other draw processes, - // e.g. mouse pointer - GlobalFlipLock = Yes; - - // IMPORTANT!!! OptimiseFlip, Blit are - // not supported in SubWindow mode!!! - - if (WindowMode == WindowModeSubWindow) - { - RECT dest; - - // For SubWindow mode, we cannot flip, but - // must instead do a (stretched, in principle) - // blit to the front buffer to combine with GDI - // surfaces. - // The whole back buffer should be taken. - dest.left = WinLeftX; - dest.top = WinTopY; - dest.right = WinRightX; - dest.bottom = WinBotY; - ddrval = lpDDSPrimary->Blt(&dest, lpDDSBack, - NULL, DDBLT_WAIT, NULL); - } - else // default to FullScreen - { - // we hope to flip, and flip to hope - // we are the tumbling jongleurs... - if (DXMemoryMode == VideoMemoryPreferred) - { - #if optimiseflip - while (lpDDSBack->GetFlipStatus(DDGFS_ISFLIPDONE) == DDERR_WASSTILLDRAWING) - ProcessProjectWhileWaitingToBeFlippable(); - #endif - - // we are going to flip with DDFLIP_WAIT on - // even if optimiseflip is set. - // IT'S THE ONLY WAY TO BE SURE. - ddrval = lpDDSPrimary->Flip(NULL, 0); - - while(0) - { - if (ddrval == DD_OK) - break; - if (ddrval == DDERR_SURFACELOST) - { - ddrval = lpDDSPrimary->Restore(); - if (ddrval != DD_OK) - break; - } - if (ddrval != DDERR_WASSTILLDRAWING) - break; - } - } - else // assume system memory rendering target - { - LOCALASSERT(0); - // Take rendering target to back buffer - // Rendering target should map fully onto back buffer - ddrval = lpDDSHiddenBack->Blt(NULL, lpDDSBack, - NULL, DDBLT_WAIT, NULL); - - // And now do a standard flip - #if optimiseflip - while (lpDDSBack->GetFlipStatus(DDGFS_ISFLIPDONE) == DDERR_WASSTILLDRAWING) - ProcessProjectWhileWaitingToBeFlippable(); - #endif - - // we are going to flip with DDFLIP_WAIT on - // even if optimiseflip is set. - // IT'S THE ONLY WAY TO BE SURE. - ddrval = lpDDSPrimary->Flip(NULL, DDFLIP_WAIT); - - while(1) - { - if (ddrval == DD_OK) - break; - if (ddrval == DDERR_SURFACELOST) - { - ddrval = lpDDSPrimary->Restore(); - if (ddrval != DD_OK) - break; - } - if (ddrval != DDERR_WASSTILLDRAWING) - break; - } - } - } - - GlobalFlipLock = No; - - ProjectSpecificBufferFlipPostProcessing(); - - HandleScreenShot(); - - #if InterlaceExperiment - oddDraw ^= 1; - #endif -} - -// As of 29/4/96, slightly later in the day, -// it now deallocates NOTHING explcitly, but -// just calls Release on the entire DD object, -// which seems a better approach. Ho hum. - -// This function is now OBSOLETE (25 / 7 / 96) -// CALL RELEASEDIRECT3D INSTEAD!!! - -void finiObjects(void) -{ - if (lpDD != NULL) - { - lpDD->Release(); - lpDD = NULL; - } -} - -// Release ONE direct draw surface, to be used -// when replacing images via imageheader array, -// e.g. in LoadBackdrop. - -void ReleaseDDSurface(void* DDSurface) - -{ - LPDIRECTDRAWSURFACE lpSurface; - - WaitForVRamReady(VWS_DDRELEASE); - - lpSurface = (LPDIRECTDRAWSURFACE) DDSurface; - - if (lpSurface != NULL) - { - lpSurface->Release(); - lpSurface = NULL; - } -} - - -// Blt member is used rather BltFast because BltFast does not -// allow a colour fill - -void ColourFillBackBuffer(int FillColour) - -{ - HRESULT ddrval; - DDBLTFX ddbltfx; - - memset(&ddbltfx, 0, sizeof(ddbltfx)); - ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwFillColor = FillColour; - - /* lets blt a color to the surface*/ - #if optimiseblit - while (lpDDSBack->GetBltStatus(DDGBS_CANBLT) != DD_OK); - #endif - - #if optimiseblit - ddrval = lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &ddbltfx); - - if (ddrval == DDERR_WASSTILLDRAWING) - ddrval = lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, - &ddbltfx); - #else - ddrval = lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); - #endif - - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - #if debug - ReleaseDirect3D(); - exit(ddrval); - #else - return; - #endif - } -} - -// Blt member is used rather BltFast because BltFast does not -// allow a colour fill - -void ColourFillBackBufferQuad(int FillColour, int LeftX, - int TopY, int RightX, int BotY) - -{ - HRESULT ddrval; - DDBLTFX ddbltfx; - RECT destRect; - - destRect.left = LeftX; - destRect.top = TopY; - destRect.right = RightX; - destRect.bottom = BotY; - - memset(&ddbltfx, 0, sizeof(ddbltfx)); - ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwFillColor = FillColour; - - /* lets blt a color to the surface*/ - #if optimiseblit - while (lpDDSBack->GetBltStatus(DDGBS_CANBLT) != DD_OK); - #endif - - #if optimiseblit - ddrval = lpDDSBack->Blt(&destRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &ddbltfx); - - if (ddrval == DDERR_WASSTILLDRAWING) - ddrval = lpDDSBack->Blt(&destRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); - #else - ddrval = lpDDSBack->Blt(&destRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); - #endif - - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - #if debug - ReleaseDirect3D(); - exit(ddrval); - #else - return; - #endif - } -} - -// Note Blt is used rather than BltFast because BltFast will -// always attempt to invoke an asynchronous blit and this appears -// to be unstable at present (cf. problems with optimiseblit) -// CHECK THIS -- WITH DDBLTFASTWAIT??? -// COMMENT ABOVE NOW OBSOLETE... - -void BlitToBackBuffer(void* lpBackground, RECT* destRectPtr, RECT* srcRectPtr) - -{ - HRESULT ddrval; - - #if optimiseblit - while (lpDDSBack->GetBltStatus(DDGBS_CANBLT) != DD_OK); - #endif - - #if optimiseblit - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_ASYNC, NULL); - - if (ddrval == DDERR_WASSTILLDRAWING) - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_WAIT, NULL); - #else - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_WAIT, NULL); - #endif - - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - #if debug - ReleaseDirect3D(); - exit(ddrval); - #else - return; - #endif - } -} - -// Note Blt is used rather than BltFast because BltFast does not -// support DDBLTFX and therefore cannot be used to attempt to -// prevent tearing - -void BlitToBackBufferWithoutTearing(void* lpBackground, RECT* destRectPtr, RECT* srcRectPtr) - -{ - HRESULT ddrval; - DDBLTFX ddbltfx; - - memset(&ddbltfx, 0, sizeof(ddbltfx)); - ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwDDFX = DDBLTFX_NOTEARING; - - #if optimiseblit - while (lpDDSBack->GetBltStatus(DDGBS_CANBLT) != DD_OK); - #endif - - #if optimiseblit - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_ASYNC | DDBLT_DDFX, &ddbltfx); - - if (ddrval == DDERR_WASSTILLDRAWING) - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_WAIT | DDBLT_DDFX, &ddbltfx); - #else - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_WAIT | DDBLT_DDFX, &ddbltfx); - #endif - - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - #if debug - ReleaseDirect3D(); - exit(ddrval); - #else - return; - #endif - } -} - -#if 0 - -// Note Blt is used rather than BltFast because BltFast does -// not support the DDBLTFX structure and therefore cannot accept -// a rotated blit - -void RotatedBlitToBackBuffer(void* lpBackground, RECT* destRectPtr, RECT* srcRectPtr, int RollZ) - -{ - HRESULT ddrval; - DDBLTFX ddbltfx; - - memset(&ddbltfx, 0, sizeof(ddbltfx)); - ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwRotationAngle = RollZ; - - #if optimiseblit - while (lpDDSBack->GetBltStatus(DDGBS_CANBLT) != DD_OK); - #endif - - #if optimiseblit - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_ASYNC | DDBLT_ROTATIONANGLE, &ddbltfx); - - if (ddrval == DDERR_WASSTILLDRAWING) - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_WAIT | DDBLT_ROTATIONANGLE, &ddbltfx); - #else - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_WAIT | DDBLT_ROTATIONANGLE, &ddbltfx); - #endif - - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - #if debug - ReleaseDirect3D(); - exit(ddrval); - #else - return; - #endif - } -} - -// Note Blt is used rather than BltFast because BltFast does not -// support DDBLTFX and therefore cannot be used to attempt to -// prevent tearing - -void RotatedBlitToBackBufferWithoutTearing(void* lpBackground, RECT* destRectPtr, RECT* srcRectPtr, int RollZ) - -{ - HRESULT ddrval; - DDBLTFX ddbltfx; - - memset(&ddbltfx, 0, sizeof(ddbltfx)); - ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwDDFX = DDBLTFX_NOTEARING; - ddbltfx.dwRotationAngle = RollZ; - - #if optimiseblit - while (lpDDSBack->GetBltStatus(DDGBS_CANBLT) != DD_OK); - #endif - - #if optimiseblit - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_ASYNC | DDBLT_DDFX | DDBLT_ROTATIONANGLE, &ddbltfx); - - if (ddrval == DDERR_WASSTILLDRAWING) - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_WAIT | DDBLT_DDFX | DDBLT_ROTATIONANGLE, &ddbltfx); - #else - ddrval = lpDDSBack->Blt(destRectPtr, (LPDIRECTDRAWSURFACE) lpBackground, - srcRectPtr, DDBLT_WAIT | DDBLT_DDFX | DDBLT_ROTATIONANGLE, &ddbltfx); - #endif - - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - #if debug - ReleaseDirect3D(); - exit(ddrval); - #else - return; - #endif - } -} - -#endif - - -// Note x, y are assumed to be TOP LEFT of character -// BltFast is used here, partially as an experiment (ahem...) - -// THIS FUNCTION ASSUMES A VERTICAL FONT BRUSH!!! - -// FIXME!!! This function does not always seem to -// produce visible text in SubWindow mode; i.e. -// as of 29/4/96 it works on Roxby's and fails on -// mine. I suspect this is because we are using -// BltFast, which 'works only on display memory', -// and there isn't enough video RAM on my card -// to put the debug font in video memory in SubWindow -// mode. Or something. -// At present I have done nothing about this, since Roxby -// claims that as of Beta 3 he can't get source colour -// keying working on the blitter without using BltFast, and -// we need source colour keying to get the font to -// look right. -// Will have to be looked at at some stage, 'tho. - -#if debug || PreBeta -void BlitWin95Char(int x, int y, unsigned char toprint) - -{ - static int bltwin95char_ok=1; - if (!bltwin95char_ok) return; - - int FontIndex; - RECT source; - HRESULT ddrval; - #if NoBltFastOnFont - RECT destination; - #endif - - // Check for data out of range for font - if ((toprint < FontStart) || (toprint > FontEnd)) - return; - - // Check for character being on screen - if ((x < ScreenDescriptorBlock.SDB_ClipLeft) || - ((x + CharWidth) > ScreenDescriptorBlock.SDB_ClipRight) || - (y < ScreenDescriptorBlock.SDB_ClipUp) || - ((y + CharHeight) > ScreenDescriptorBlock.SDB_ClipDown)) - return; - - // Generate font index and source rectangle - // Assumes vertical brush - FontIndex = (toprint - FontStart); - - source.left = 0; - source.top = (FontIndex * CharHeight); - source.right = CharWidth; - source.bottom = ((FontIndex + 1) * CharHeight); - - // Do blit - #if NoBltFastOnFont - destination.left = x; - destination.top = y; - destination.right = (x+CharWidth); - destination.bottom = (y+CharHeight); - ddrval = lpDDSBack->Blt(&destination, lpDDDbgFont, - &source, DDBLT_WAIT | DDBLT_KEYSRC, NULL); - #else - ddrval = lpDDSBack->BltFast(x, y, - lpDDDbgFont, &source, - DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY); - #endif - - LOGDXERR(ddrval); - if (ddrval != DD_OK) - #if debug && 0 - { - ReleaseDirect3D(); - exit(0x11); - } - #else - bltwin95char_ok = 0; - return; - #endif -} - -#else -void BlitWin95Char(int x, int y, unsigned char toprint) -{ -} -#endif - -// IMPORTANT!!! FIXME!!!! - -// This function has been hacked to FORCE images into -// system memory due to what appears to be a bug in -// DirectDraw's defaulting to system memory... - -// Has HOPEFULLY now been fixed to deal with non 8 bit -// images... but I wouldn't count on it... - -// If SysMem is TRUE, the image should go into system memory. If it is -// FALSE, we will try for video memory. And may God walk at our side in -// the valley of the shadow. - - - -// This callback enumerates all the DirectDraw -// devices present on a system searching for one -// with hardware 3D support available. If such -// a device is present, it will always be selected. -// Otherwise, no valid device will be returned. - -static BOOL bHardwareDDObj = FALSE; -static BOOL bNoHardwareDD = FALSE; - - -BOOL FAR PASCAL EnumDDObjectsCallback(GUID FAR* lpGUID, LPSTR lpDriverDesc, - LPSTR lpDriverName, LPVOID lpContext) -{ - LPDIRECTDRAW lpDDTest; - DDCAPS DriverCaps, HELCaps; - HRESULT ddrval; - - /* - A NULL GUID* indicates the DirectDraw HEL which we are not interested - in at the moment, because we are cruel and heartless and really - really nasty people, after all. - */ - - if (lpGUID) - { - // Create the DirectDraw device using this driver. If it fails, - // just move on to the next driver. - - ddrval = DirectDrawCreate(lpGUID, &lpDDTest, NULL); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - return DDENUMRET_OK; - - // Get the capabilities of this DirectDraw driver. If it fails, - // just move on to the next driver. - - memset(&DriverCaps, 0, sizeof(DDCAPS)); - DriverCaps.dwSize = sizeof(DDCAPS); - memset(&HELCaps, 0, sizeof(DDCAPS)); - HELCaps.dwSize = sizeof(DDCAPS); - - ddrval = lpDDTest->GetCaps(&DriverCaps, &HELCaps); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - lpDDTest->Release(); - return DDENUMRET_OK; - } - - // JH - changed so that debugging in a window works if you've got two cards or something - if (DriverCaps.dwCaps & DDCAPS_3D && WindowRequestMode != WindowModeSubWindow) - { - // We have found a 3d hardware device. Return the DD object - // and stop enumeration. - // This assumes that 3d capable DD hardware - // drivers cannot operate in a window. - // True? CHECKME!!! - WindowMode = WindowModeFullScreen; - *(LPDIRECTDRAW*)lpContext = lpDDTest; - return DDENUMRET_CANCEL; - } - lpDDTest->Release(); - } - return DDENUMRET_OK; -} - - -// Set up the DirectDraw object for the -// system. Using this we can determine the -// system capabilities. The DirectDraw object -// in question should never be released until -// ExitSystem, even if window or video modes -// are changed. Note that as well as checking -// for valid video modes etc, this function will -// also search for hardware DirectDraw objects -// and use one if appropriate. - -// Note that GenerateDirectDrawSurface and -// SetVideoMode now just set a video mode, -// rather than (as previously) initialising the -// DirectDraw model. - -// This function should be called -// during InitialiseSystem, so that we can -// be sure that SetVideoMode (called later) -// will be setting a valid mode. The function -// must be called after InitialVideoMode (which -// sets the mode it validates) and before -// InitialiseWindowsSystem, since in the -// current version that needs to know the -// WindowMode, not the VideoMode. Note that -// InitialiseWindowsSystem itself must be called -// after InitialVideoMode (it is currently -// called at the start of InitialiseSystem). - -DDCAPS direct_draw_caps; - -BOOL InitialiseDirectDrawObject(void) - -{ - HRESULT ddrval; - LPDIRECTDRAW lpDDHardware = NULL; - - // Set up DirectDraw object. - - // If we are not in emulation only mode, - // search for a hardware 3D capable DirectDraw - // driver and use it. If this fails, or if we - // are in emulation, go straight for the HEL. - if (RasterisationRequestMode != RequestSoftwareRasterisation) - { - ddrval = DirectDrawEnumerate(EnumDDObjectsCallback, &lpDDHardware); - LOGDXERR(ddrval); - if (ddrval != DD_OK) - { - #if debug - ReleaseDirect3D(); - exit(ddrval); - #else - return FALSE; - #endif - } - } - - // If we don't have a hardware driver, either - // because there wasn't one or because we are in - // HEL... then make one. - - if (!lpDDHardware) - { - if (RasterisationRequestMode != RequestSoftwareRasterisation) - bNoHardwareDD = TRUE; - bHardwareDDObj = FALSE; - ddrval = DirectDrawCreate(NULL, &lpDD, NULL); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - { - ReleaseDirect3D(); // for safety - return FALSE; - } - #endif - } - else - { - bHardwareDDObj = TRUE; - lpDD = lpDDHardware; - } - - AwSetDDObject(lpDD); - - // Get caps for hardware DD driver/HEL layer - memset(&direct_draw_caps, 0, sizeof(direct_draw_caps)); - direct_draw_caps.dwSize = sizeof(direct_draw_caps); - ddrval = lpDD->GetCaps(&direct_draw_caps, NULL); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - { - ReleaseDirect3D(); // for safety - return FALSE; - } - #endif - - // Put statistics into globals - TotalVideoMemory = (int) (direct_draw_caps.dwVidMemTotal); - // At some stage, we should set up a proper - // structure here with the general system - // capabilities in it. - // Notably, we may need to check DD surface - // alignment values and the stride. - - // NOTE THAT AS GARRY HAS POINTED OUT, TOTAL - // FREE VIDMEM CAN CHANGE AFTER SETTING THE - // VIDEO MODE OR COOPERATIVE LEVEL, SO WE - // SHOULD REALLY BE RUNNING THIS GETCAPS MEMBER - // ON THE DDOBJECT AGAIN AFTER GENERATESURFACE, OR - // POSSIBLY WHENEVER THE USER WANTS. - // ***FIXME!!!*** - - // Run the display modes enumerator - // Note that NULL in the second entry - // means enumerate all available display - // modes on the driver. - NumAvailableVideoModes = 0; - ddrval = lpDD->EnumDisplayModes(0, NULL, 0, EnumDisplayModesCallback); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - { - ReleaseDirect3D(); // for safety - return FALSE; - } - #endif - - // Check that the video mode asked - // for (initially at least in - // InitialVideoMode) is actually - // available. If it is not, attempt to - // default to 640x480x8 and 640x480x15 - // (liable to be the most common modes) - // and if that fails, exit altogether - // with a failure code. - - // Note!!! This only matters in FullScreen - // mode. In SubWindow mode we must use the - // Windows display mode anyway. Obviously - // initialisation of the video mode will fail - // in SubWindow mode if the colour depth of - // the Windows display is different to the - // VideoMode colour depth, but I have not bothered - // to check for this since SubWindow mode is - // only intended for debugging and the failure - // case exits with an appropriate DirectDraw - // error anyway. - #if CheckVideoMode - if (WindowMode == WindowModeFullScreen) - { - if (!(CheckForVideoModes(VideoMode))) - { - VideoMode = VideoMode_DX_640x480x8; - if (!(CheckForVideoModes(VideoMode))) - { - VideoMode = VideoMode_DX_640x480x15; - if (!(CheckForVideoModes(VideoMode))) - { - ReleaseDirect3D(); // for safety - return FALSE; - } - } - } - } - #endif // for CheckVideoMode - - return TRUE; // Successful completion -} - - -// return TRUE on success - -static BOOL ReallyChangeDDObj(void) -{ - finiObjects(); - - if (InitialiseDirectDrawObject() - == FALSE) - /* - If we cannot get a video mode, - fail. No point in a non debugging option - for this. - */ - { - #if debug - ReleaseDirect3D(); - exit(0x997798); - #else - return FALSE; - #endif - } - - /* - Initialise global to say whether - we think there is an onboard 3D - acceleration card / motherboard - built-in - */ - #if 0 - TestInitD3DObject(); - -/* - This is (HOPEFULLY!!) now the right - place to put this call. Note that it is - not absolutely certain that we can do test - blits from DirectDraw without setting - a cooperative level, however... And note also - that MMX works better with the back buffer in - system memory... -*/ - TestMemoryAccess(); - #endif - return TRUE; -} - -int SelectDirectDrawObject(LPGUID pGUID) -{ - HRESULT ddrval; - LPDIRECTDRAW lpDDHardware = NULL; - - // Set up DirectDraw object. - bNoHardwareDD = TRUE; - bHardwareDDObj = FALSE; - ddrval = DirectDrawCreate(pGUID, &lpDD, NULL); - - AwSetDDObject(lpDD); - - // Get caps for hardware DD driver/HEL layer - memset(&direct_draw_caps, 0, sizeof(direct_draw_caps)); - direct_draw_caps.dwSize = sizeof(direct_draw_caps); - ddrval = lpDD->GetCaps(&direct_draw_caps, NULL); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - { - ReleaseDirect3D(); // for safety - return FALSE; - } - #endif - - // Put statistics into globals - TotalVideoMemory = (int) (direct_draw_caps.dwVidMemTotal); - // At some stage, we should set up a proper - // structure here with the general system - // capabilities in it. - // Notably, we may need to check DD surface - // alignment values and the stride. - - // NOTE THAT AS GARRY HAS POINTED OUT, TOTAL - // FREE VIDMEM CAN CHANGE AFTER SETTING THE - // VIDEO MODE OR COOPERATIVE LEVEL, SO WE - // SHOULD REALLY BE RUNNING THIS GETCAPS MEMBER - // ON THE DDOBJECT AGAIN AFTER GENERATESURFACE, OR - // POSSIBLY WHENEVER THE USER WANTS. - // ***FIXME!!!*** - - // Run the display modes enumerator - // Note that NULL in the second entry - // means enumerate all available display - // modes on the driver. - NumAvailableVideoModes = 0; - ddrval = lpDD->EnumDisplayModes(0, NULL, 0, EnumDisplayModesCallback); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - { - ReleaseDirect3D(); // for safety - return FALSE; - } - #endif - - // Check that the video mode asked - // for (initially at least in - // InitialVideoMode) is actually - // available. If it is not, attempt to - // default to 640x480x8 and 640x480x15 - // (liable to be the most common modes) - // and if that fails, exit altogether - // with a failure code. - - // Note!!! This only matters in FullScreen - // mode. In SubWindow mode we must use the - // Windows display mode anyway. Obviously - // initialisation of the video mode will fail - // in SubWindow mode if the colour depth of - // the Windows display is different to the - // VideoMode colour depth, but I have not bothered - // to check for this since SubWindow mode is - // only intended for debugging and the failure - // case exits with an appropriate DirectDraw - // error anyway. - #if CheckVideoMode - if (WindowMode == WindowModeFullScreen) - { - if (!(CheckForVideoModes(VideoMode))) - { - VideoMode = VideoMode_DX_640x480x8; - if (!(CheckForVideoModes(VideoMode))) - { - VideoMode = VideoMode_DX_640x480x15; - if (!(CheckForVideoModes(VideoMode))) - { - ReleaseDirect3D(); // for safety - return FALSE; - } - } - } - } - #endif // for CheckVideoMode - - return TRUE; // Successful completion -} - - - -BOOL ChangeDirectDrawObject(void) -{ - if (RequestSoftwareRasterisation==RasterisationRequestMode) - { - // software modes required - if (bHardwareDDObj) - { - // but was previously hardware DD - return ReallyChangeDDObj(); - } - } - else - { - // hardware modes requested if available - if (!bHardwareDDObj && !bNoHardwareDD) - { - // but was previously software DD and - // we haven't established that hardware isn't available - return ReallyChangeDDObj(); - } - } - - return TRUE; -} - - - -BOOL CheckForVideoModes(int TestVideoMode) - -{ - int i=0; - BOOL EarlyExit = FALSE; - - do - { - if ((EngineVideoModes[TestVideoMode].Width - == AvailableVideoModes[i].Width) && - (EngineVideoModes[TestVideoMode].Height - == AvailableVideoModes[i].Height) && - (EngineVideoModes[TestVideoMode].ColourDepth - == AvailableVideoModes[i].ColourDepth)) - EarlyExit = TRUE; - else - i++; - } - while ((i < NumAvailableVideoModes) && - (!EarlyExit)); - - return(EarlyExit); -} - -HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context) -{ - AvailableVideoModes[NumAvailableVideoModes].Width = pddsd->dwWidth; - AvailableVideoModes[NumAvailableVideoModes].Height = pddsd->dwHeight; - AvailableVideoModes[NumAvailableVideoModes].ColourDepth = pddsd->ddpfPixelFormat.dwRGBBitCount; - NumAvailableVideoModes++; - - if (NumAvailableVideoModes < MaxAvailableVideoModes) - return DDENUMRET_OK; - else - return DDENUMRET_CANCEL; -} - -// Deallocate all objects except the basic -// DirectDraw objects, which we want to do -// before shifting display modes or window -// mode. Note that ExitWindowsSystem must be -// called separately. Note also that ExitSystem -// should be called for a full system shutdown. - -// FIXME!!! BACKDROPS?!?!? -- done in -// DeallocateAllImages (called from ReleaseDirect3D -// and ReleaseDirect3DNotDD) - -// Note that getting the right sequence for releases -// here is CRUCIAL. Note also that the font surface -// is NOT explicitly deallocated; hopefully it will just -// go when we kill the primary (as an offscreen surface). -// Could this cause problems for DeallocateAllImages?? -// Um, err, I sure hope not... - - -void finiObjectsExceptDD(void) -{ - if (WindowMode == WindowModeSubWindow) - { - if (lpDDClipper != NULL) - { - lpDDClipper->Release(); - lpDDClipper = NULL; - } - } - - if (lpDDPal[0] != NULL) // should be killed neway??? - { - lpDDPal[0]->Release(); - lpDDPal[0] = NULL; - } - - if (lpDDSBack != NULL) - { - lpDDSBack->Release(); - lpDDSBack = NULL; - } - - if (lpDDSPrimary != NULL) - { - lpDDSPrimary->Release(); - lpDDSPrimary = NULL; - } -} - - -// This will hopefully allow us to change -// the palette at runtime, assuming that -// we are in a palettised mode. It will -// wait for vertical blank to make it work -// on all video cards (I hope). Note that -// the palette should be passed in engine -// internal format, i.e. 6 bits, and will be -// converted to the DirectDraw format internally. - -// Note we assume entry 0 in the lpDDPal array!!! - -// Note for 222 mode we set the FIRST 64 entries!!! -// Not certain that's right, actually... - -int ChangePalette (unsigned char* NewPalette) - -{ - unsigned char DDPalette[1024]; // 256 colours, 4 bytes each - int NumEntries; - - // Check for palettised mode - // Note we must use VideoModeTypeScreen - // due to nature of Direct3D ramp driver - // interface. - - if ((VideoModeTypeScreen != VideoModeType_8) && - (VideoModeTypeScreen != VideoModeType_8T)) - return No; - - // Check for FullScreen mode - // if (WindowMode != WindowModeFullScreen) - // return No; - - // Set up number of entries to change - if (ScreenDescriptorBlock.SDB_Flags & SDB_Flag_222) - NumEntries = 256; // actually, this seems to be right... - else if ((ScreenDescriptorBlock.SDB_Flags & SDB_Flag_Raw256) - || (VideoModeTypeScreen == VideoModeType_8T)) - NumEntries = 256; - else - return No; // undefined behaviour - - // Convert to DirectDraw 4 bytes, 8 bit format - // with all flag entries set to zero - - ConvertToDDPalette(NewPalette, DDPalette, NumEntries, 0); - - // Wait for beginning of next vertical - // blanking interval - lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL); - - // Set all entries in palette to new values - lpDDPal[0]->SetEntries(0,0,NumEntries,(LPPALETTEENTRY) - DDPalette); - - return Yes; -} - -// At some stage it may be worth expanding this function -// to get more than video memory, or replacing it -// with one that uses GetCaps to fill out a general -// structure. - -int GetAvailableVideoMemory(void) -{ - DDCAPS ddcaps; - HRESULT ddrval; - - // Get caps for DirectDraw object - memset(&ddcaps, 0, sizeof(ddcaps)); - ddcaps.dwSize = sizeof(ddcaps); - ddrval = lpDD->GetCaps(&ddcaps, NULL); - LOGDXERR(ddrval); - - if (ddrval != DD_OK) - #if debug - { - ReleaseDirect3D(); - exit(ddrval); - } - #else - return -1; - #endif - - return (int) (ddcaps.dwVidMemFree); -} - -/* - This is designed to allow for ModeX - emulation failures where the system - boots up in a low memory cost mode - which actually takes up much more than - a high cost mode because GDI cannot be - evicted. Note that the VideoMode reset - done here is in any case a last ditch - measure, since the higher res version will - be much slower as well as (normally) more - costly in terms of memory. - - It will also now do start errors due to the - driver not being able to change to a mode of - a different colour depth, and this not being reported - by the DirectDraw object's enum display modes - callback. Hopefully. - - NOTE THAT THIS MUST BE CALLED FROM YOUR WINMAIN - AFTER SETVIDEOMODE IF IT IS TO WORK. - - NOTE ALSO THAT THE ACTIVATION CODE FOR THIS IS - IN GENERATEDIRECTDRAWSURFACE AND WILL NOT BE TURNED - ON UNLESS -->DEBUG<-- IS -->OFF<--. -*/ - -void HandleVideoModeRestarts(HINSTANCE hInstance, int nCmdShow) -{ - if (AttemptVideoModeRestart) - { - switch (VideoRestartMode) - { - case RestartDisplayModeNotAvailable: - { - // Rewrite mode as equivalent resolution, - // different bit depth, before trying again. - // Note this must be kept up to date!!! - switch (VideoMode) - { - case VideoMode_DX_320x200x8: - { - ReleaseDirect3D(); - exit(0xfedd); - } - VideoMode = VideoMode_DX_320x200x15; - break; - - case VideoMode_DX_320x200x8T: - VideoMode = VideoMode_DX_320x200x15; - break; - - case VideoMode_DX_320x200x15: - VideoMode = VideoMode_DX_320x200x8T; - break; - - case VideoMode_DX_320x240x8: - VideoMode = VideoMode_DX_320x200x15; - break; - - case VideoMode_DX_640x480x8: - VideoMode = VideoMode_DX_640x480x15; - break; - - case VideoMode_DX_640x480x8T: - VideoMode = VideoMode_DX_640x480x15; - break; - - case VideoMode_DX_640x480x15: - VideoMode = VideoMode_DX_640x480x8T; - break; - - case VideoMode_DX_640x480x24: - VideoMode = VideoMode_DX_640x480x15; - break; - - default: // hmm... - break; - } - - // Clear variables - AttemptVideoModeRestart = No; - VideoRestartMode = NoRestartRequired; - - ChangeDisplayModes(hInstance, nCmdShow, - VideoMode, WindowRequestMode, - ZBufferRequestMode, RasterisationRequestMode, - SoftwareScanDrawRequestMode, DXMemoryRequestMode); - } - break; - - case RestartOutOfVidMemForPrimary: - { - // Guess mode reset - // Note this must be kept up to date!!! - if ((VideoMode == VideoMode_DX_320x200x8) || - (VideoMode == VideoMode_DX_320x200x8T) || - (VideoMode == VideoMode_DX_320x240x8)) - VideoMode = VideoMode_DX_640x480x8; - else if (VideoMode == VideoMode_DX_320x200x15) - VideoMode = VideoMode_DX_640x480x15; - - // Clear variables - AttemptVideoModeRestart = No; - VideoRestartMode = NoRestartRequired; - - ChangeDisplayModes(hInstance, nCmdShow, - VideoMode, WindowRequestMode, - ZBufferRequestMode, RasterisationRequestMode, - SoftwareScanDrawRequestMode, DXMemoryRequestMode); - } - break; - - default: // err... - break; - } - } -} - - -// Take a 24 bit RGB colour and return it in the -// correct format for the current primary surface -// We will assume that the primary is NOT in a -// palettised mode, since the mapping if we have -// already set a palette is undefined. - -int GetSingleColourForPrimary(int Colour) - -{ - unsigned long m; - int s; - int red_shift, red_scale; - int green_shift, green_scale; - int blue_shift, blue_scale; - int RetVal = 0; - int r, g ,b; - - // Fail for palettised modes - if ((VideoModeTypeScreen == VideoModeType_8) - || (VideoModeTypeScreen == VideoModeType_8T)) - return -1; - - // Extra! check for palettised modes - if ((DisplayPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) - || (DisplayPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)) - return -1; - - // Determine r, g, b masks and scale - for (s = 0, m = DisplayPixelFormat.dwRBitMask; - !(m & 1); s++, m >>= 1); - - red_shift = s; - red_scale = 255 / (DisplayPixelFormat.dwRBitMask >> s); - - for (s = 0, m = DisplayPixelFormat.dwGBitMask; - !(m & 1); s++, m >>= 1); - - green_shift = s; - green_scale = 255 / (DisplayPixelFormat.dwGBitMask >> s); - - for (s = 0, m = DisplayPixelFormat.dwBBitMask; - !(m & 1); s++, m >>= 1); - - blue_shift = s; - blue_scale = 255 / (DisplayPixelFormat.dwBBitMask >> s); - - // Extract r,g,b components from input colour - r = (Colour >> 16) & 0xff; - g = (Colour >> 8) & 0xff; - b = Colour & 0xff; - - // Scale and shift each value - r /= red_scale; - g /= green_scale; - b /= blue_scale; - RetVal = (r << red_shift) | (g << green_shift) - | (b << blue_shift); - - return(RetVal); -} - -#if triplebuffer -// NOTE TRIPLE BUFFERING SUPPORT HAS BEEN -->REMOVED<-- -// ON THE GROUNDS THAT THE SECOND BACK BUFFER TAKES UP -// EXTRA MEMORY AND IT'S NOT GOING TO GO ANY FASTER -// ANYWAY UNLESS YOUR VIDEO CARD FLIPS IN HARDWARE AND -// TAKES MORE THAN ABOUT 10 MILLISECONDS TO DO IT. -// WHICH I CERTAINLY HOPE ISN'T TRUE... - -// NOTE ALSO: THIS FUNCTION DOESN'T WORK! (DESPITE -// THE DOCUMENTATION). YOU NEED TO USE GETATTACHEDSURFACE -// TWICE INSTEAD. SEE ARSEWIPE CODE FOR A WORKING -// EXAMPLE (NOTE THAT TRIPLE BUFFERING CAN BE OPTIMAL -// IN ARSEWIPE BECAUSE IT'S 2D, AND THE TIME TO THE NEXT -// SURFACE LOCK IN A RENDERING CYCLE CAN THUS BE MUCH LESS -// THAN IN 3DC). - -// defines this function as FAR PASCAL, i.e. -// using Windows standard parameter passing convention, -// which will be neecessary for all callbacks - -HRESULT WINAPI InitTripleBuffers(LPDIRECTDRAWSURFACE lpdd, - LPDDSURFACEDESC lpsd, LPVOID lpc) -{ - if ((lpsd->ddsCaps.dwCaps & DDSCAPS_FLIP) && - (!(lpsd->ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)) - && (BackBufferEnum < MaxBackBuffers)) - lpDDSBack[BackBufferEnum++] = lpdd; - - if (BackBufferEnum == MaxBackBuffers) - return(DDENUMRET_CANCEL); - else - return(DDENUMRET_OK); -} -#endif - - - -/* new versions of these functions, provided by neil */ -static GDIObjectReferenceCount = 0; -BOOL GetGDISurface(void) -{ - HRESULT hr = DD_OK; - - if(WindowMode == WindowModeSubWindow) return TRUE; - - if(!lpDDGDI) - { - hr = lpDD->GetGDISurface(&lpDDGDI); - if(hr != DD_OK) - { - ReleaseDirect3D(); - exit(hr); - } - } - - // flip the buffer to the GDI surface - hr = lpDD->FlipToGDISurface(); - if(hr != DD_OK) - { - ReleaseDirect3D(); - exit(hr); - } - - GDIObjectReferenceCount++; - - // release windows palette entries - - // whenever we flip to the GDI surface, - // we will want the full palette. - - if (VideoModeColourDepth == 8) - { - HDC hdc = GetDC(NULL); - SetSystemPaletteUse(hdc, SYSPAL_STATIC); - ReleaseDC(NULL, hdc); - } - - return TRUE; -} - - -BOOL LeaveGDISurface(void) -{ - HRESULT hr = DD_OK; - - if(WindowMode == WindowModeSubWindow) return TRUE; - - if (GDIObjectReferenceCount <= 1) - { - ReleaseDDSurface(lpDDGDI); - } - - // recapture system static palette - // entries (see note above in - // GetGDISurface... ) - - if (VideoModeColourDepth == 8) - { - HDC hdc = GetDC(NULL); - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - ReleaseDC(NULL, hdc); - } - - return TRUE; -} - -/************ for extern "C"*****************/ - -}; - -- cgit v1.3