//! 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; }
//----------------------------------------------------------------------------- // 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); }
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); }
//----------------------------------------------------------------------------- // 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
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
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; }
/** * 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; }
//----------------------------------------------------------------------------- // 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; }