示例#1
0
//! Load the bitmap and copy it to the overlay surface
bool DrawOverlay()
{
    HRESULT        hRet;       // This is where we put return values from DirectDraw.
    DDSURFACEDESC2 surfDesc;
    // Setup structure
    memset(&surfDesc, 0, sizeof(surfDesc)); surfDesc.dwSize = sizeof(surfDesc);

    hRet = g_pDDSOverlay->Lock(NULL, &surfDesc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY, NULL);
    if (hRet != DD_OK ||  surfDesc.lpSurface == NULL)
        return DisplayError("Can't lock overlay surface", hRet);
    else {
        g_pImg = (unsigned int *)surfDesc.lpSurface;
        //g_pDDSOverlay->Unlock(NULL); is not needed?
    }
    // Setup effects structure
    memset(&g_OverlayFX, 0, sizeof(g_OverlayFX)); g_OverlayFX.dwSize = sizeof(g_OverlayFX);
    // Setup overlay flags.
    g_OverlayFlags = DDOVER_SHOW;
    // Check for destination color keying capability
    if ((g_DDCaps.dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY) && ((g_DDCaps.dwCaps & DDCAPS_OVERLAYCANTCLIP) || (g_DDCaps.dwCKeyCaps & DDCKEYCAPS_NOCOSTOVERLAY) ))
    {
        // If so, we'll use it to clip the bitmap when other windows go on top
        // of us. Just for the record - this color range for color keying (the
        // high/low values) are not heavily supported right now, so for almost
        // all cards, just use the same color for both.
        g_OverlayFX.dckDestColorkey.dwColorSpaceLowValue =
        g_OverlayFX.dckDestColorkey.dwColorSpaceHighValue = DDColorMatch(g_pDDSPrimary, RGBKEY);
        g_OverlayFlags |= DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE;
    } else {
        // If not, we'll setup a clipper for the window.  This will fix the
        // problem on a few video cards - but the ones that don't shouldn't care.
        hRet = g_pDD->CreateClipper(0, &g_pClipper, NULL);
        if (hRet != DD_OK)
            return DisplayError("Can't create clipper", hRet);
        hRet = g_pClipper->SetHWnd(0, g_hAppWnd);
        if (hRet != DD_OK)
            return DisplayError("Can't attach clipper", hRet);
        hRet = g_pDDSPrimary->SetClipper(g_pClipper);
        if (hRet != DD_OK)
            return DisplayError("Can't set clipper", hRet);
    }
    return true;
}
示例#2
0
//-----------------------------------------------------------------------------
// Name: AttachClipper()
// Desc: creates and attaches a clipper to a surface
//-----------------------------------------------------------------------------
LPDIRECTDRAWCLIPPER AttachClipper(LPDIRECTDRAWSURFACE7 lpddsSurface, HWND hWnd)
{
	LPDIRECTDRAWCLIPPER lpddClipper;  //pointer to the newly created dd clipper
	
	//first create the DD clipper
	ddReturnVal = lpddObj->CreateClipper(0,&lpddClipper, NULL);
	if (DDFailedCheck(ddReturnVal, "CreateClipper() failed", cpErrorBuf ))
	{	MessageBox(main_window_handle, cpErrorBuf, "AttachClipper()", MB_ICONEXCLAMATION);   return(NULL); }
	
	ddReturnVal = lpddClipper->SetHWnd(NULL,hWnd);
	if (DDFailedCheck(ddReturnVal, "lpddClipper->SetHWnd() failed", cpErrorBuf ))
	{	MessageBox(main_window_handle, cpErrorBuf, "AttachClipper()", MB_ICONEXCLAMATION);   return(NULL); }

	// now attach the clipper to the surface
	ddReturnVal = lpddsSurface->SetClipper(lpddClipper);
	if (DDFailedCheck(ddReturnVal, "SetClipper() failed", cpErrorBuf ))
	{	
		MessageBox(main_window_handle, cpErrorBuf, "AttachClipper()", MB_ICONEXCLAMATION);   
		// release memory and return error
		return(NULL); 
	}

	return(lpddClipper);
}
示例#3
0
int DDInit(void)
{
        HRESULT hRet;

        hWnd = Form1->Handle;

        DDEnd();
        hRet = DirectDrawCreateEx(NULL, (VOID**)&m_pDD, IID_IDirectDraw7, NULL);
        if(DDError(hRet != DD_OK,"DDCreateEX")) return(false);

        if (Form1->FullScreen)
        {
                hRet = m_pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
                hRet = m_pDD->SetDisplayMode(FScreen.Width, FScreen.Height, FScreen.Bpp,NULL,NULL);

        }
        else    hRet = m_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
        if(DDError(hRet != DD_OK,"DDSetCoop")) return(false);

        HRESULT hr;

        DDSURFACEDESC2 ddsd;
        ZeroMemory( &ddsd, sizeof( ddsd ) );
        ddsd.dwSize = sizeof( ddsd );
        ddsd.dwFlags = DDSD_CAPS;
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

        if(DDError(hr = m_pDD->CreateSurface(&ddsd, &m_pddsFrontBuffer, NULL)
                ,"CreateFrontSurface")) return(false);

        // Create the backbuffer surface
        ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
        ddsd.dwWidth = 1024;
        ddsd.dwHeight = 768;

        hr = m_pDD->CreateSurface(&ddsd, &m_pddsFrame, NULL);
        if (hr)
        {
                ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
                ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
                ddsd.dwWidth = 460;
                ddsd.dwHeight = 400;
                hr = m_pDD->CreateSurface(&ddsd, &m_pddsFrame, NULL);
                if(DDError(hr,"CreateBackSurface")) return(false);
                tv.DisableAdvanced=1;
        }

        if (!Form1->FullScreen)
        {
                if(DDError(hr = m_pDD->CreateClipper(0, &pcClipper, NULL)
                        ,"CreateClipper")) return(false);

                if(DDError(hr = pcClipper->SetHWnd(0, hWnd)
                        ,"SetClipperHwnd"))
                {
                        pcClipper->Release();
                        return(false);
                }


                if(DDError(hr = m_pddsFrontBuffer->SetClipper(pcClipper)
                        ,"SetClipperSurface"))
                {
                        pcClipper->Release();
                        return(false);
                }
        }

        return(true);
}
示例#4
0
//-----------------------------------------------------------------------------
// Name: AttachClipper()
// Desc: creates and attaches a clipper to a surface
//-----------------------------------------------------------------------------
LPDIRECTDRAWCLIPPER AttachClipper(LPDIRECTDRAWSURFACE7 lpddsSurface, int iNumRects, LPRECT cliplist)
{
	int index;                        //loop va
	LPDIRECTDRAWCLIPPER lpddClipper;  //pointer to the newly created dd clipper
	LPRGNDATA regionData;             //pointer to the region data that contains the header and clip list

	//first create the DD clipper
	ddReturnVal = lpddObj->CreateClipper(0,&lpddClipper, NULL);
	if (DDFailedCheck(ddReturnVal, "CreateClipper() failed", cpErrorBuf ))
	{	MessageBox(main_window_handle, cpErrorBuf, "AttachClipper()", MB_ICONEXCLAMATION);   return(NULL); }
	
	//now create the clip list from the sent data
	//first allocate memory for region data
	regionData = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + iNumRects*sizeof(RECT));
	//now copy the rects into region data
	memcpy(regionData->Buffer, cliplist, sizeof(RECT)*iNumRects);
	
	// set up fields of header
	regionData->rdh.dwSize          = sizeof(RGNDATAHEADER);
	regionData->rdh.iType           = RDH_RECTANGLES;
	regionData->rdh.nCount          = iNumRects;
	regionData->rdh.nRgnSize        = iNumRects*sizeof(RECT);

	regionData->rdh.rcBound.left    =  -64000;
	regionData->rdh.rcBound.top     =  -64000;
	regionData->rdh.rcBound.right   = 64000;
	regionData->rdh.rcBound.bottom  = 64000;

	// find bounds of all clipping regions
	for (index=0; index<iNumRects; index++)
    {
		// test if the next rectangle unioned with the current bound is larger
		if (cliplist[index].top < regionData->rdh.rcBound.top)
			regionData->rdh.rcBound.top = cliplist[index].top;

		if (cliplist[index].left < regionData->rdh.rcBound.left)
			 regionData->rdh.rcBound.left = cliplist[index].left;

		if (cliplist[index].bottom > regionData->rdh.rcBound.bottom)
			regionData->rdh.rcBound.bottom = cliplist[index].bottom;

		if (cliplist[index].right > regionData->rdh.rcBound.right)
			regionData->rdh.rcBound.right = cliplist[index].right;

    } // end for index

	// now we have computed the bounding rectangle region and set up the data
	// now let's set the clipping list
	
	ddReturnVal = lpddClipper->SetClipList(regionData, 0); //can also give lpddClipper a hWnd
	if (DDFailedCheck(ddReturnVal, "SetClipList() failed", cpErrorBuf ))
	{	
		MessageBox(main_window_handle, cpErrorBuf, "AttachClipper()", MB_ICONEXCLAMATION);   
		// release memory and return error
		free(regionData);
		return(NULL); 
	}
	
	// now attach the clipper to the surface
	ddReturnVal = lpddsSurface->SetClipper(lpddClipper);
	if (DDFailedCheck(ddReturnVal, "SetClipper() failed", cpErrorBuf ))
	{	
		MessageBox(main_window_handle, cpErrorBuf, "AttachClipper()", MB_ICONEXCLAMATION);   
		// release memory and return error
		free(regionData);
		return(NULL); 
	}
	
	// all is well, so release memory and send back the pointer to the new clipper
	free(regionData);
	return(lpddClipper);

} // end AttachClipper
示例#5
0
	BOOL jcdd_createClipper(LPDIRECTDRAW7 lpdd, LPDIRECTDRAWSURFACE7 lpdds, LPDIRECTDRAWCLIPPER* lplpddc, INT numRect, LPRECT rectList)
	{
		if(lpdd == NULL)
		{
			return FALSE;
		}

		if(lpdds == NULL)
		{
			return FALSE;
		}

		if(FAILED(lpdd->CreateClipper(0, lplpddc, NULL)))
		{
			return FALSE;
		}

		LPRGNDATA regionData;
		regionData = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + numRect * sizeof(RECT));
		memcpy(regionData->Buffer, rectList, numRect * sizeof(RECT));

		regionData->rdh.dwSize = sizeof(RGNDATAHEADER);
		regionData->rdh.iType = RDH_RECTANGLES;
		regionData->rdh.nCount = numRect;
		regionData->rdh.nRgnSize = sizeof(RECT) * numRect;
		regionData->rdh.rcBound.left = LONG_MAX;
		regionData->rdh.rcBound.top = LONG_MAX;
		regionData->rdh.rcBound.right = LONG_MIN;
		regionData->rdh.rcBound.bottom = LONG_MIN;

		for (INT i = 0; i < numRect; ++i)
		{
			if(rectList[i].left < regionData->rdh.rcBound.left)
			{
				regionData->rdh.rcBound.left = rectList[i].left;
			}
			if(rectList[i].top < regionData->rdh.rcBound.top)
			{
				regionData->rdh.rcBound.top = rectList[i].top;
			}
			if(rectList[i].right > regionData->rdh.rcBound.right)
			{
				regionData->rdh.rcBound.right = rectList[i].right;
			}
			if(rectList[i].bottom > regionData->rdh.rcBound.bottom)
			{
				regionData->rdh.rcBound.bottom = rectList[i].bottom;
			}
		}

		if(FAILED((*lplpddc)->SetClipList(regionData, 0)))
		{
			free(regionData);
			return NULL;
		}
		if(FAILED(lpdds->SetClipper(*lplpddc)))
		{
			free(regionData);
			return NULL;
		}
		free(regionData);

		return TRUE;
	}
LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,
                                         int num_rects,
                                         LPRECT clip_list)

{
// this function creates a clipper from the sent clip list and attaches
// it to the sent surface

int index;                         // looping var
LPDIRECTDRAWCLIPPER lpddclipper;   // pointer to the newly created dd clipper
LPRGNDATA region_data;             // pointer to the region data that contains
                                   // the header and clip list

// first create the direct draw clipper
if (FAILED(lpdd->CreateClipper(0,&lpddclipper,NULL)))
   return(NULL);

// now create the clip list from the sent data

// first allocate memory for region data
region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));

// now copy the rects into region data
memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);

// set up fields of header
region_data->rdh.dwSize          = sizeof(RGNDATAHEADER);
region_data->rdh.iType           = RDH_RECTANGLES;
region_data->rdh.nCount          = num_rects;
region_data->rdh.nRgnSize        = num_rects*sizeof(RECT);

region_data->rdh.rcBound.left    =  64000;
region_data->rdh.rcBound.top     =  64000;
region_data->rdh.rcBound.right   = -64000;
region_data->rdh.rcBound.bottom  = -64000;

// find bounds of all clipping regions
for (index=0; index<num_rects; index++)
    {
    // test if the next rectangle unioned with the current bound is larger
    if (clip_list[index].left < region_data->rdh.rcBound.left)
       region_data->rdh.rcBound.left = clip_list[index].left;

    if (clip_list[index].right > region_data->rdh.rcBound.right)
       region_data->rdh.rcBound.right = clip_list[index].right;

    if (clip_list[index].top < region_data->rdh.rcBound.top)
       region_data->rdh.rcBound.top = clip_list[index].top;

    if (clip_list[index].bottom > region_data->rdh.rcBound.bottom)
       region_data->rdh.rcBound.bottom = clip_list[index].bottom;

    } // end for index

// now we have computed the bounding rectangle region and set up the data
// now let's set the clipping list

if (FAILED(lpddclipper->SetClipList(region_data, 0)))
   {
   // release memory and return error
   free(region_data);
   return(NULL);
   } // end if

// now attach the clipper to the surface
if (FAILED(lpdds->SetClipper(lpddclipper)))
   {
   // release memory and return error
   free(region_data);
   return(NULL);
   } // end if

// all is well, so release memory and send back the pointer to the new clipper
free(region_data);
return(lpddclipper);

} // end DDraw_Attach_Clipper
示例#7
0
static HRESULT CreateWindowedDisplay(HWND hWnd, DWORD dwWidth, DWORD dwHeight)
{
	// Set cooperative level
	if (FAILED(lpdd->SetCooperativeLevel(hWnd, DDSCL_NORMAL)))
	{
		return E_FAIL;
	}

	RECT  rcWork;
	RECT  rc;
	DWORD dwStyle;
	// If we are still a WS_POPUP window
	// We should convert to a normal app window so we look like a windows app.
	dwStyle = GetWindowLong(hWnd, GWL_STYLE);
	dwStyle &= ~WS_POPUP;
	dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
	SetWindowLong(hWnd, GWL_STYLE, dwStyle);
	// Adapt window size
	SetRect(&rc, 0, 0, dwWidth, dwHeight);
	AdjustWindowRectEx(&rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, GetWindowExStyle(hWnd));
	SetWindowPos(hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
	SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
	// Make sure our window does not hang outside of the work area
	SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
	GetWindowRect(hWnd, &rc);
	if (rc.left < rcWork.left) rc.left = rcWork.left;
	if (rc.top < rcWork.top)  rc.top = rcWork.top;
	SetWindowPos(hWnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

	// Create the primary surface
	DDSURFACEDESC2 ddsd;
	DDRAW_INIT_STRUCT(ddsd);
	ddsd.dwFlags = DDSD_CAPS;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
	if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsMain, NULL)))
	{
		return E_FAIL;
	}
	// Create the backbuffer surface
	ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT;
	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
	ddsd.dwWidth = dwWidth;
	ddsd.dwHeight = dwHeight;
	if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsBack, NULL)))
	{
		return E_FAIL;
	}

	// Set surface color key
	DDCOLORKEY ddCK;
	ddCK.dwColorSpaceLowValue = 0;
	ddCK.dwColorSpaceHighValue = 0;
	if (lpddsBack->SetColorKey(DDCKEY_SRCBLT, &ddCK))
	{
		return E_FAIL;
	}

	// Create clipper for the primary surface
	LPDIRECTDRAWCLIPPER lpClipper;
	if (FAILED(lpdd->CreateClipper(0, &lpClipper, NULL)))
	{
		return E_FAIL;
	}
	if (FAILED(lpClipper->SetHWnd(0, hWnd)))
	{
		lpClipper->Release();
		return E_FAIL;
	}
	if (FAILED(lpddsMain->SetClipper(lpClipper)))
	{
		lpClipper->Release();
		return E_FAIL;
	}
	lpClipper->Release();
	lpClipper = NULL;

	// Update window flag
	SetClassLong(hWnd, GCL_HICONSM, (LONG)LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICONSM)));
	SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LONG)LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICONSM)));
	UpdateWindow(hWnd);

	return S_OK;
}
示例#8
0
/**
 * vdraw_ddraw_init(): Initialize the DirectDraw video subsystem.
 * @return 0 on success; non-zero on error.
 */
int vdraw_ddraw_init(void)
{
	DDSURFACEDESC2 ddsd;
	
	vdraw_ddraw_end();
	
	mdp_render_t *rendMode = get_mdp_render_t();
	const int scale = rendMode->scale;
	
	// Determine the window size using the scaling factor.
	if (scale <= 0)
		return -1;
	const int w = 320 * scale;
	const int h = 240 * scale;
	
	if (vdraw_get_fullscreen())
	{
		Res_X = w;
		Res_Y = h;
	}
	
	// Return value.
	int rval;
	
	// Initialize DirectDraw.
	// TODO: Initialize DirectDraw on the monitor with most of Gens/GS onscreen.
	LPDIRECTDRAW lpDD_Init;
	rval = DirectDrawCreate(NULL, &lpDD_Init, NULL);
	if (FAILED(rval))
	{
		LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
			"DirectDrawCreate() failed: 0x%08X", rval);
		return -2;
	}
	
	rval = lpDD_Init->QueryInterface(IID_IDirectDraw7, (LPVOID*)&lpDD);
	if (FAILED(rval))
	{
		if (lpDD_Init)
			lpDD_Init->Release();
		
		LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
			"lpDD_Init->QueryInterface(IID_IDirectDraw4) failed: 0x%08X", rval);
		LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
			"This can usually be fixed by upgrading DirectX.");
		return -3;
	}
	
	// Free the DirectDraw initialization object.
	lpDD_Init->Release();
	
	// Set the cooperative level.
	vdraw_ddraw_set_cooperative_level();
	
	// TODO: 15-bit color override. ("Force 555" or "Force 565" in the config file.)
	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	
	// TODO: Figure out what FS_No_Res_Change is for.
	// TODO: Figure out if this is correct.
	if (vdraw_get_fullscreen() /* && !FS_No_Res_Change*/)
	{
		// Use the color depth setting.
		// NOTE: "15-bit" color requires 16-bit to be specified.
		rval = lpDD->SetDisplayMode(Res_X, Res_Y, (bppOut == 15 ? 16 : bppOut), 0, 0);
		if (FAILED(rval))
		{
			vdraw_ddraw_free_all(false);
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"lpDD->SetDisplayMode() failed: 0x%08X", rval);
			
			// If render mode is set to Normal, try using Double instead.
			if (rendMode_FS == RenderMgr::begin() && rendMode_FS != RenderMgr::end())
			{
				LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
					"Renderer is set to Normal; attempting to use Double instead.");
				rendMode_FS++;
				vdraw_set_renderer(rendMode_FS);
				vdraw_text_write("Normal rendering failed. Using Double.", 1500);
				Sync_Gens_Window_GraphicsMenu();
			}
			
			return -4;
		}
	}
	
#if 0
	// Check the current color depth.
	unsigned char newBpp;
	lpDD->GetDisplayMode(&ddsd);
	switch (ddsd.ddpfPixelFormat.dwGBitMask)
	{
		case 0x03E0:
			// 15-bit color.
			newBpp = 15;
			break;
		case 0x07E0:
			// 16-bit color.
			newBpp = 16;
			break;
		case 0x00FF00:
		default:
			// 32-bit color.
			newBpp = 32;
			break;
	}
	
	if (newBpp != bppOut)
		vdraw_set_bpp(newBpp, false);
#endif
	
	// Clear ddsd.
	memset(&ddsd, 0x00, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	
	if (vdraw_get_fullscreen() && Video.VSync_FS)
	{
		ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
		ddsd.dwBackBufferCount = 2;
	}
	else
	{
		ddsd.dwFlags = DDSD_CAPS;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
	}
	
	// Create the primary surface.
	rval = lpDD->CreateSurface(&ddsd, &lpDDS_Primary, NULL);
	if (FAILED(rval))
	{
		vdraw_ddraw_free_all(false);
		LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
			"lpDD->CreateSurface(&lpDDS_Primary) failed: 0x%08X", rval);
		return -5;
	}
	
	if (vdraw_get_fullscreen())
	{
		if (Video.VSync_FS)
		{
			ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
			
			rval = lpDDS_Primary->GetAttachedSurface(&ddsd.ddsCaps, &lpDDS_Flip);
			if (FAILED(rval))
			{
				vdraw_ddraw_free_all(false);
				LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
					"lpDDS_Primary->GetAttachSurface() failed: 0x%08X", rval);
				return -6;
			}
			
			lpDDS_Blit = lpDDS_Flip;
		}
		else
		{
			lpDDS_Blit = lpDDS_Primary;
		}
	}
	else
	{
		rval = lpDD->CreateClipper(0, &lpDDC_Clipper, NULL);
		if (FAILED(rval))
		{
			vdraw_ddraw_free_all(false);
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"lpDD->CreateClipper() failed: 0x%08X", rval);
			return -7;
		}
		
		rval = lpDDC_Clipper->SetHWnd(0, gens_window);
		if (FAILED(rval))
		{
			vdraw_ddraw_free_all(false);
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"lpDDC_Clipper->SetHWnd() failed: 0x%08X", rval);
			return -8;
		}
		
		rval = lpDDS_Primary->SetClipper(lpDDC_Clipper);
		if (FAILED(rval))
		{
			vdraw_ddraw_free_all(false);
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"lpDDC_Primary->SetClipper() failed: 0x%08X", rval);
			return -9;
		}
	}
	
	// Clear ddsd again.
	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
	
	// Determine the width and height.
	// NOTE: For DirectDraw, the actual 336 width is used.
	if (vdraw_ddraw_is_hw_render())
	{
		// Normal render mode. 320x240 [336x240]
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
		ddsd.dwWidth = 336;
		ddsd.dwHeight = 240;
	}
	else
	{
		// Larger than 1x.
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
		ddsd.dwWidth = w;
		ddsd.dwHeight = h;
	}
	
	// Set the pixel format.
	ddsd.dwFlags |= DDSD_PIXELFORMAT;
	ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
	ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
	ddsd.ddpfPixelFormat.dwFourCC = 0; // RGB
	ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
	
	// Bits per component.
	switch (bppOut)
	{
		case 15:
			// 15-bit color. (555)
			ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
			ddsd.ddpfPixelFormat.dwRBitMask = 0x7C00;
			ddsd.ddpfPixelFormat.dwGBitMask = 0x03E0;
			ddsd.ddpfPixelFormat.dwBBitMask = 0x001F;
			break;
		
		case 16:
			// 16-bit color. (555)
			ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
			ddsd.ddpfPixelFormat.dwRBitMask = 0xF800;
			ddsd.ddpfPixelFormat.dwGBitMask = 0x07E0;
			ddsd.ddpfPixelFormat.dwBBitMask = 0x001F;
			break;
		
		case 32:
		default:
			// 32-bit color.
			ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
			ddsd.ddpfPixelFormat.dwRBitMask = 0xFF0000;
			ddsd.ddpfPixelFormat.dwGBitMask = 0x00FF00;
			ddsd.ddpfPixelFormat.dwBBitMask = 0x0000FF;
			break;
	}
	
	// Create the back surface.
	rval = lpDD->CreateSurface(&ddsd, &lpDDS_Back, NULL);
	if (FAILED(rval))
	{
		// Failed to create the back surface.
		// If we attempted to create it in video memory, try system memory instead.
		if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
		{
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_VIDEOMEMORY) failed: 0x%08X", rval);
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"Attempting to use DDSCAPS_SYSTEMMEMORY instead.");
			ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
			ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
			rval = lpDD->CreateSurface(&ddsd, &lpDDS_Back, NULL);
			if (FAILED(rval))
			{
				// Failed to create the back surface in system memory.
				vdraw_ddraw_free_all(false);
				LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
					"lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_SYSTEMMEMORY) failed: 0x%08X", rval);
				return -10;
			}
		}
		else
		{
			vdraw_ddraw_free_all(false);
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_SYSTEMMEMORY) failed: 0x%08X", rval);
			return -11;
		}
	}
	
	// TODO: Check if this is right.
	// I think this might be causing the frame counter flicker in full screen mode.
	//if (!vdraw_get_fullscreen() || (rendMode >= 1 && (/*FS_No_Res_Change ||*/ Res_X != 640 || Res_Y != 480)))
	if (!vdraw_get_fullscreen() || !vdraw_ddraw_is_hw_render())
		lpDDS_Blit = lpDDS_Back;
	
	if (vdraw_ddraw_is_hw_render())
	{
		// Normal rendering mode uses MD_Screen directly.
		memset(&ddsd, 0, sizeof(ddsd));
		ddsd.dwSize = sizeof(ddsd);
		
		// TODO: This causes issues if the selected color depth isn't the
		// same as the desktop color depth. This only affects windowed mode,
		// since in fullscreen, the desktop color depth is changed.
		rval = lpDDS_Back->GetSurfaceDesc(&ddsd);
		if (FAILED(rval))
		{
			vdraw_ddraw_free_all(false);
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"lpDDS_Back->GetSurfaceDesc() failed: 0x%08X", rval);
			return -12;
		}
		
		ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE | DDSD_PIXELFORMAT;
		ddsd.dwWidth = 336;
		ddsd.dwHeight = 240;
		
		if (ddsd.ddpfPixelFormat.dwRGBBitCount > 16)
		{
			// 32-bit color.
			ddsd.lpSurface = MD_Screen.u32;
			ddsd.lPitch = 336 * 4;
		}
		else
		{
			// 15-bit or 16-bit color.
			ddsd.lpSurface = MD_Screen.u16;
			ddsd.lPitch = 336 * 2;
		}
		
		rval = lpDDS_Back->SetSurfaceDesc(&ddsd, 0);
		if (FAILED(rval))
		{
			vdraw_ddraw_free_all(false);
			LOG_MSG(video, LOG_MSG_LEVEL_ERROR,
				"lpDDS_Back->SetSurfaceDesc() failed: 0x%08X", rval);
			return -13;
		}
	}
	
	// Initialize the destination rectangle.
	vdraw_ddraw_adjust_RectDest();
	
	// Reset the render mode.
	vdraw_reset_renderer(false);
	
	// Synchronize menus.
	Sync_Gens_Window();
	
	// vdraw_ddraw initialized.
	return 0;
}
示例#9
0
//-----------------------------------------------------------------------------
// Name: dx_Initialise (...)
// Desc: Initialise et configure DirectX (DirectDraw)
//-----------------------------------------------------------------------------
bool dx_Initialise (uint8  pNombreSurfaces,
                    HWND   pFenetre,
                    uint16 pResolutionX,
                    uint16 pResolutionY,
                    uint16 pBitsParPixel,
                    uint16 pFrequence,
                    bool   pPleinEcran,
                    bool   pTailleFenetre,
                    void   (*pRestaure)())
{
    // InitialiseDX a déjà été appelé

    if (DirectDraw7 != NULL) {
        return dx_Finalise (ERR_NO_UTILISATEUR);
    }

    dx_InitVars ();

    // Initialise toutes les variables

    Fenetre = pFenetre;

    NombreSurfaces = pNombreSurfaces;

    ResolutionX   = pResolutionX;
    ResolutionY   = pResolutionY;
    BitsParPixel  = pBitsParPixel;
    Frequence     = pFrequence;
    PleinEcran    = pPleinEcran;
    TailleFenetre = pTailleFenetre;

    Restaure = pRestaure;

    Surfaces = new LPDIRECTDRAWSURFACE7[NombreSurfaces];

    // Initialisation de directdraw

    ErrDd = DirectDrawCreateEx (0,(LPVOID*)&DirectDraw7,IID_IDirectDraw7,0);

    if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_CREATION);

    ModeCoop = PleinEcran ? COOP_PLEIN_ECRAN : COOP_FENETRE;

    // Utilisation de la résolution active ou donnée

    if (ResolutionX  == 0 || ResolutionY == 0 ||
            BitsParPixel == 0 || Frequence   == 0)
    {
        DDSURFACEDESC2 ModeActif;
        ZeroMemory (&ModeActif, sizeof(ModeActif));
        ModeActif.dwSize = sizeof(ModeActif);

        ErrDd = DirectDraw7->GetDisplayMode (&ModeActif);

        if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_MODE_ACTIF);

        if (ResolutionX  == 0) ResolutionX = ModeActif.dwWidth;
        if (ResolutionY  == 0) ResolutionY = ModeActif.dwHeight;
        if (BitsParPixel == 0) BitsParPixel = ModeActif.
                                                  ddpfPixelFormat.dwRGBBitCount;
        if (Frequence == 0) Frequence = ModeActif.dwRefreshRate;
    }

    // Sélection du mode de coopération

    ErrDd = DirectDraw7->SetCooperativeLevel (Fenetre, ModeCoop);

    if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_COOPERATION);

    ErrDd = DirectDraw7->SetDisplayMode (ResolutionX,
                                         ResolutionY,BitsParPixel,0,0);

    if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_MODE_AFFICHAGE);

    // Création des surfaces d'affichage

    SurfaceDesc.dwFlags = DDSD_CAPS;
    SurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

    if (PleinEcran)
    {   // Surface avec backbuffer
        SurfaceDesc.dwFlags	|= DDSD_BACKBUFFERCOUNT;
        SurfaceDesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
        SurfaceDesc.dwBackBufferCount = 1;
    }

    ErrDd = DirectDraw7->CreateSurface (&SurfaceDesc,&SurfacePrimaire,NULL);

    if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_PRIMAIRE);

    if (PleinEcran)
    {
        SurfaceCaps.dwCaps = DDSCAPS_BACKBUFFER;

        ErrDd = SurfacePrimaire->GetAttachedSurface (&SurfaceCaps,&SurfaceBack);

        if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_BACKBUFFER);
    }
    else
    {
        // Surface avec clipper pour dessiner que dans la fenêtre
        ErrDd = DirectDraw7->CreateClipper (0, &SurfaceClipper, NULL);

        if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_CLIPPER);

        // Coordonnées de la fenêtre dans le clipper
        ErrDd = SurfaceClipper->SetHWnd (0, Fenetre);

        if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_CLIPPER_HWND);

        // Attache le clipper à la surface primaire
        ErrDd = SurfacePrimaire->SetClipper (SurfaceClipper);

        if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_CLIPPER_PRIMAIRE);

        ZeroMemory (&SurfaceDesc, sizeof(SurfaceDesc));
        SurfaceDesc.dwSize = sizeof(SurfaceDesc);
        SurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
        SurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
        SurfaceDesc.dwWidth  = ResolutionX;
        SurfaceDesc.dwHeight = ResolutionY;

        // Création du backbuffer séparément
        ErrDd = DirectDraw7->CreateSurface (&SurfaceDesc,&SurfaceBack,NULL);

        if (ErrDd != DD_OK) return dx_Finalise (ERR_NO_BACKBUFFER);
    }

    if (PleinEcran) ShowCursor (false);

    return true;
}