bool SetupDDraw() { logOutput << CurrentTimeString() << "called SetupDDraw()" << endl; if (!g_ddInterface) { logOutput << CurrentTimeString() << "SetupDDraw: DirectDraw interface not set, returning" << endl; return false; } bool bSuccess = true; bKillThread = false; if (hCopyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CopyDDrawTextureThread, NULL, 0, NULL)) { if (!(hCopyEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) { logOutput << CurrentTimeString() << "SetupDDraw: CreateEvent failed, GetLastError = " << GetLastError() << endl; bSuccess = false; } } else { logOutput << CurrentTimeString() << "SetupDDraw: CreateThread failed, GetLastError = " << GetLastError() << endl; bSuccess = false; } if (bSuccess) { if (!ddUnlockFctMutex) { ddUnlockFctMutex = CreateMutex(NULL, FALSE, mutexName); if (!ddUnlockFctMutex) { RUNEVERYRESET logOutput << CurrentTimeString() << "SetupDDraw: CreateMutex failed, GetLastError = " << GetLastError() << endl; bSuccess = false; } } } if (bSuccess && !g_frontSurface) { RUNEVERYRESET logOutput << "SetupDDraw: frontSurface and surface descriptor not set, returning" << endl; CleanUpDDraw(); return false; } else if (bSuccess) { LPDIRECTDRAWPALETTE palette = NULL; HRESULT err; if (SUCCEEDED(err = g_frontSurface->GetPalette(&palette))) { if (palette) SetupPalette(palette); } else if (err == DDERR_NOPALETTEATTACHED) { //logOutput << CurrentTimeString() << "No palette attached to primary surface" << endl; } else { logOutput << CurrentTimeString() << "Error retrieving palette" << endl; printDDrawError(err, "getFrontSurface"); } } if (bSuccess && !g_surfaceDesc) { logOutput << CurrentTimeString() << "SetupDDraw: no surface descriptor found, creating a new one (not an error)" << endl; g_surfaceDesc = new DDSURFACEDESC2; g_surfaceDesc->dwSize = sizeof(DDSURFACEDESC); HRESULT hr; if (FAILED(hr = ((LPDIRECTDRAWSURFACE)g_frontSurface)->GetSurfaceDesc((LPDDSURFACEDESC)g_surfaceDesc))) { g_surfaceDesc->dwSize = sizeof(DDSURFACEDESC2); if (FAILED(g_frontSurface->GetSurfaceDesc(g_surfaceDesc))) { logOutput << CurrentTimeString() << "SetupDDraw: error getting surface descriptor" << endl; printDDrawError(hr, "SetupDDraw"); bSuccess = false; } } } if (bSuccess && g_surfaceDesc) { const DDPIXELFORMAT& pf = g_surfaceDesc->ddpfPixelFormat; if (pf.dwFlags & DDPF_RGB) { if (pf.dwRGBBitCount == 16) { logOutput << CurrentTimeString() << "SetupDDraw: found 16bit format (using R5G6B5 conversion)" << endl; g_bConvert16to32 = true; } else if (pf.dwRGBBitCount == 32) { logOutput << CurrentTimeString() << "SetupDDraw: found 32bit format (using plain copy)" << endl; g_bUse32bitCapture = true; } } else if (pf.dwFlags & (DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXED1)) { logOutput << CurrentTimeString() << "SetupDDraw: front surface uses palette indices" << endl; } } if (bSuccess) { logOutput << CurrentTimeString() << "SetupDDraw: primary surface width = " << g_surfaceDesc->dwWidth << ", height = " << g_surfaceDesc->dwHeight << endl; g_dwSize = g_surfaceDesc->lPitch*g_surfaceDesc->dwHeight; ddrawCaptureInfo.captureType = CAPTURETYPE_MEMORY; ddrawCaptureInfo.cx = g_surfaceDesc->dwWidth; ddrawCaptureInfo.cy = g_surfaceDesc->dwHeight; ddrawCaptureInfo.pitch = 4 * ddrawCaptureInfo.cx; ddrawCaptureInfo.hwndCapture = (DWORD)hwndSender; ddrawCaptureInfo.format = GS_BGRA; DWORD g_dwCaptureSize = ddrawCaptureInfo.pitch*ddrawCaptureInfo.cy; ddrawCaptureInfo.bFlip = FALSE; ddrawCaptureInfo.mapID = InitializeSharedMemoryCPUCapture(g_dwCaptureSize, &ddrawCaptureInfo.mapSize, ©Data, textureBuffers); memcpy(infoMem, &ddrawCaptureInfo, sizeof(CaptureInfo)); DDSURFACEDESC2 captureDesc; ZeroMemory(&captureDesc, sizeof(captureDesc)); captureDesc.dwSize = sizeof(DDSURFACEDESC2); captureDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_PITCH; captureDesc.dwWidth = g_surfaceDesc->dwWidth; captureDesc.dwHeight = g_surfaceDesc->dwHeight; captureDesc.lPitch = g_surfaceDesc->lPitch; captureDesc.ddpfPixelFormat = g_surfaceDesc->ddpfPixelFormat; captureDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; HRESULT err; ddrawSurfaceCreate.Unhook(); for (int i = 0; i < NUM_BUFFERS && bSuccess; i++) { if (FAILED(err = g_ddInterface->CreateSurface(&captureDesc, &ddCaptures[i], NULL))) { logOutput << CurrentTimeString() << "SetupDDraw: Could not create offscreen capture" << endl; printDDrawError(err, "SetupDDraw"); bSuccess = false; break; } } ddrawSurfaceCreate.Rehook(); if (bSuccess) { bHasTextures = true; SetEvent(hSignalReady); OSInitializeTimer(); } } if (bSuccess) { logOutput << CurrentTimeString() << "SetupDDraw successfull" << endl; HookAll(); return true; } else { logOutput << CurrentTimeString() << "SetupDDraw failed" << endl; CleanUpDDraw(); return false; } }
//----------------------------------------------------------------------------- // 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].left < regionData->rdh.rcBound.left) regionData->rdh.rcBound.left = cliplist[index].left; if (cliplist[index].right > regionData->rdh.rcBound.right) regionData->rdh.rcBound.right = cliplist[index].right; if (cliplist[index].top < regionData->rdh.rcBound.top) regionData->rdh.rcBound.top = cliplist[index].top; if (cliplist[index].bottom > regionData->rdh.rcBound.bottom) regionData->rdh.rcBound.bottom = cliplist[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 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
HRESULT CTextureHolder::Restore( LPDIRECT3DDEVICE7 pd3dDevice ) { // Release any previously created objects SAFE_RELEASE( m_pddsSurface ); // Check params if( NULL == pd3dDevice ) return DDERR_INVALIDPARAMS; // Get the device caps D3DDEVICEDESC7 ddDesc; if( FAILED( pd3dDevice->GetCaps( &ddDesc) ) ) return E_FAIL; // Setup the new surface desc DDSURFACEDESC2 ddsd; D3DUtil_InitSurfaceDesc( ddsd ); ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH| DDSD_PIXELFORMAT|DDSD_TEXTURESTAGE; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; ddsd.dwTextureStage = 0; //m_dwStage; ddsd.dwWidth = m_dwWidth; ddsd.dwHeight = m_dwHeight; // Turn on texture management for hardware devices if( ddDesc.deviceGUID == IID_IDirect3DHALDevice ) ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE; else if( ddDesc.deviceGUID == IID_IDirect3DTnLHalDevice ) ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE; else ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; // Adjust width and height to be powers of 2, if the device requires it if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 ) { for( ddsd.dwWidth=1; m_dwWidth>ddsd.dwWidth; ddsd.dwWidth<<=1 ); for( ddsd.dwHeight=1; m_dwHeight>ddsd.dwHeight; ddsd.dwHeight<<=1 ); } // Limit max texture sizes, if the driver can't handle large textures DWORD dwMaxWidth = ddDesc.dwMaxTextureWidth; DWORD dwMaxHeight = ddDesc.dwMaxTextureHeight; ddsd.dwWidth = min( ddsd.dwWidth, ( dwMaxWidth ? dwMaxWidth : 256 ) ); ddsd.dwHeight = min( ddsd.dwHeight, ( dwMaxHeight ? dwMaxHeight : 256 ) ); // Make the texture square, if the driver requires it if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) { if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth; else ddsd.dwWidth = ddsd.dwHeight; } // Setup the structure to be used for texture enumration. TEXTURESEARCHINFO tsi; tsi.bFoundGoodFormat = FALSE; tsi.pddpf = &ddsd.ddpfPixelFormat; tsi.dwDesiredBPP = m_dwBPP; tsi.bUsePalette = ( m_dwBPP <= 8 ); tsi.bUseAlpha = m_bHasMyAlpha; if( m_dwFlags & D3DTEXTR_16BITSPERPIXEL ) tsi.dwDesiredBPP = 16; else if( m_dwFlags & D3DTEXTR_32BITSPERPIXEL ) tsi.dwDesiredBPP = 32; if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) { if( tsi.bUsePalette ) { if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE ) { tsi.bUseAlpha = TRUE; tsi.bUsePalette = TRUE; } else { tsi.bUseAlpha = TRUE; tsi.bUsePalette = FALSE; } } } // Enumerate the texture formats, and find the closest device-supported // texture pixel format pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi ); // If we couldn't find a format, let's try a default format if( FALSE == tsi.bFoundGoodFormat ) { tsi.bUsePalette = FALSE; tsi.dwDesiredBPP = 16; pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi ); // If we still fail, we cannot create this texture if( FALSE == tsi.bFoundGoodFormat ) return E_FAIL; } // Get the DirectDraw interface for creating surfaces LPDIRECTDRAW7 pDD; LPDIRECTDRAWSURFACE7 pddsRender; pd3dDevice->GetRenderTarget( &pddsRender ); pddsRender->GetDDInterface( (VOID**)&pDD ); pddsRender->Release(); // Create a new surface for the texture HRESULT hr = pDD->CreateSurface( &ddsd, &m_pddsSurface, NULL ); // Done with DDraw pDD->Release(); if( FAILED(hr) ) return hr; // For bitmap-based textures, copy the bitmap image. if( m_hbmBitmap ) return CopyBitmapToSurface(); // At this point, code can be added to handle other file formats (such as // .dds files, .jpg files, etc.). return S_OK; }
//------------------------------------------------------------------------- // InitializeEnvironment // creates default allocator-presenter and sets D3D environment //------------------------------------------------------------------------- HRESULT CMultiSAP::InitializeEnvironment() { HRESULT hr; // m_hMonitor = MonitorFromWindow(m_hwndApp, MONITOR_DEFAULTTOPRIMARY); hr = CreateDefaultAllocatorPresenter(); if (hr != S_OK) return hr; BITMAPINFOHEADER bi = { sizeof(BITMAPINFOHEADER), // biSize 640, // biWidth 480, // biHeight 1, // biPlanes 0, // biBitCount BI_RGB, // biCompression 0, // biSizeImage, 0, // biXpelsPerMeter 0, // biYPelsPerMeter 0, // biClrUsed 0 // biClrImportant }; VMRALLOCATIONINFO ai = { AMAP_3D_TARGET, // dwFlags &bi, // lpHdr NULL, // lpPicFmt {4, 3}, // szAspectRatio 1, // dwMinBuffers 1, // dwMaxBuffers 0, // dwInterlaceFlags {640, 480} // szNativeSize }; DWORD dwBuffers = 0; LPDIRECTDRAWSURFACE7 lpDDSurf; hr = m_pAlloc->AllocateSurface(0, &ai, &dwBuffers, &lpDDSurf); if (hr != DD_OK) return hr; DDSURFACEDESC2 ddsd = {sizeof(DDSURFACEDESC2)}; hr = lpDDSurf->GetSurfaceDesc(&ddsd); if (hr != DD_OK) { return hr; } // // Overlay surfaces have these flags set, we need to remove // these flags prior to calling GetAttachedSurface // ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FRONTBUFFER | DDSCAPS_VISIBLE); hr = lpDDSurf->GetAttachedSurface(&ddsd.ddsCaps, &m_lpBackBuffer); m_lpBackBuffer->GetDDInterface((LPVOID *)&m_lpDDObj); // // get the h/w caps for this device // INITDDSTRUCT(m_ddHWCaps); m_lpDDObj->GetCaps(&m_ddHWCaps, NULL); // // Create the device. The device is created off of our back buffer, which // becomes the render target for the newly created device. Note that the // z-buffer must be created BEFORE the device // m_pD3DHelper = new CD3DHelper(m_lpBackBuffer, &hr); if(m_pD3DHelper == NULL || hr != DD_OK) { if(m_pD3DHelper == NULL) { hr = E_OUTOFMEMORY; } delete m_pD3DHelper; } SetRect(&m_rcDst, 0, 0, 640, 480); #ifdef SPARKLE m_pSparkle = new CSparkle(m_lpDDObj); if (m_pSparkle) m_pSparkle->InitializeSparkle(); #endif return hr; }
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // set the backbuffer count field to 1, use 2 for triple buffering ddsd.dwBackBufferCount = 1; // request a complex, flippable ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); // now query for attached surface from the primary surface // this line is needed by the call ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; // get the attached back buffer surface if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) return(0); // build up the palette data array for (int color=1; color < 255; color++) { // fill with random RGB values palette[color].peRed = rand()%256; palette[color].peGreen = rand()%256; palette[color].peBlue = rand()%256; // set flags field to PC_NOCOLLAPSE palette[color].peFlags = PC_NOCOLLAPSE; } // end for color // now fill in entry 0 and 255 with black and white palette[0].peRed = 0; palette[0].peGreen = 0; palette[0].peBlue = 0; palette[0].peFlags = PC_NOCOLLAPSE; palette[255].peRed = 255; palette[255].peGreen = 255; palette[255].peBlue = 255; palette[255].peFlags = PC_NOCOLLAPSE; // make color 1 yellow palette[1].peRed = 255; palette[1].peGreen = 255; palette[1].peBlue = 0; palette[1].peFlags = PC_NOCOLLAPSE; // create the palette object if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, palette,&lpddpal, NULL))) return(0); // finally attach the palette to the primary surface if (FAILED(lpddsprimary->SetPalette(lpddpal))) return(0); // initialize all the happy faces for (int face = 0; face < 100; face++) { // set random position happy_faces[face].x = rand()%SCREEN_WIDTH; happy_faces[face].y = rand()%SCREEN_HEIGHT; // set random velocity (-2,+2) happy_faces[face].xv = -2 + rand()%5; happy_faces[face].yv = -2 + rand()%5; } // end for face // return success or failure or your own return code here return(1); } // end Game_Init
/******************************Public*Routine******************************\ * PresentImage * \**************************************************************************/ STDMETHODIMP CMpegMovie::PresentImage( DWORD_PTR dwUserID, VMRPRESENTATIONINFO* lpPresInfo ) { #if 0 LPDIRECTDRAWSURFACE7 lpSurface = lpPresInfo->lpSurf; const REFERENCE_TIME rtNow = lpPresInfo->rtStart; const DWORD dwSurfaceFlags = lpPresInfo->dwFlags; if(m_iDuration > 0) { HRESULT hr; RECT rs, rd; DDSURFACEDESC2 ddsdV; INITDDSTRUCT(ddsdV); hr = lpSurface->GetSurfaceDesc(&ddsdV); DDSURFACEDESC2 ddsdP; INITDDSTRUCT(ddsdP); hr = m_pddsPriText->GetSurfaceDesc(&ddsdP); FLOAT fPos = (FLOAT)m_iDuration / 30.0F; FLOAT fPosInv = 1.0F - fPos; SetRect(&rs, 0, 0, MulDiv((int)ddsdV.dwWidth, 30 - m_iDuration, 30), ddsdV.dwHeight); SetRect(&rd, 0, 0, MulDiv((int)ddsdP.dwWidth, 30 - m_iDuration, 30), ddsdP.dwHeight); hr = m_pddsRenderT->Blt(&rd, lpSurface, &rs, DDBLT_WAIT, NULL); SetRect(&rs, 0, 0, MulDiv((int)ddsdP.dwWidth, m_iDuration, 30), ddsdP.dwHeight); SetRect(&rd, (int)ddsdP.dwWidth - MulDiv((int)ddsdP.dwWidth, m_iDuration, 30), 0, ddsdP.dwWidth, ddsdP.dwHeight); hr = m_pddsRenderT->Blt(&rd, m_pddsPriText, &rs, DDBLT_WAIT, NULL); // // need to wait for VBlank before blt-ing // { LPDIRECTDRAW lpdd; hr = m_pddsPrimary->GetDDInterface((LPVOID*)&lpdd); if(SUCCEEDED(hr)) { DWORD dwScanLine; for(; ;) { hr = lpdd->GetScanLine(&dwScanLine); if(hr == DDERR_VERTICALBLANKINPROGRESS) { break; } if(FAILED(hr)) { break; } if((LONG)dwScanLine>= rd.top) { if((LONG)dwScanLine <= rd.bottom) { continue; } } break; } RELEASE(lpdd); } } hr = m_pddsPrimary->Blt(NULL, m_pddsRenderT, NULL, DDBLT_WAIT, NULL); m_iDuration--; if(m_iDuration == 0 && (ddsdV.ddsCaps.dwCaps & DDSCAPS_OVERLAY)) { // need to get the color key visible again. InvalidateRect(m_hwndApp, NULL, FALSE); } return hr; } else { return m_lpDefIP->PresentImage(dwUserID, lpPresInfo); } #endif return m_lpDefIP->PresentImage(dwUserID, lpPresInfo); }
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; }
int Game_Main(void *parms = NULL, int num_parms = 0) { // this is the main loop of the game, do all your processing // here // lookup for proper walking sequence static int animation_seq[4] = {0,1,0,2}; int index; // general looping variable // make sure this isn't executed again if (window_closed) return(0); // for now test if user is hitting ESC and send WM_CLOSE if (KEYDOWN(VK_ESCAPE)) { PostMessage(main_window_handle,WM_CLOSE,0,0); window_closed = 1; } // end if // copy background to back buffer DDraw_Draw_Surface(lpddsbackground,0,0, SCREEN_WIDTH,SCREEN_HEIGHT, lpddsback,0); // move objects around for (index=0; index < 3; index++) { // move each object to the right at its given velocity aliens[index].x++; // =aliens[index].velocity; // test if off screen edge, and wrap around if (aliens[index].x > SCREEN_WIDTH) aliens[index].x = - 80; // animate bot if (++aliens[index].counter >= (8 - aliens[index].velocity)) { // reset counter aliens[index].counter = 0; // advance to next frame if (++aliens[index].current_frame > 3) aliens[index].current_frame = 0; } // end if } // end for index // draw all the bots for (index=0; index < 3; index++) { // draw objects DDraw_Draw_Surface(aliens[index].frames[animation_seq[aliens[index].current_frame]], aliens[index].x, aliens[index].y, 72,80, lpddsback); } // end for index // flip pages while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); // wait a sec Sleep(30); // return success or failure or your own return code here return(1); } // end Game_Main
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x8 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // we need a complex surface system with a primary and backbuffer // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // set the backbuffer count field to 1, use 2 for triple buffering ddsd.dwBackBufferCount = 1; // request a complex, flippable ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); // now query for attached surface from the primary surface // this line is needed by the call ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; // get the attached back buffer surface if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) return(0); // build up the palette data array for (int color=1; color < 255; color++) { // fill with random RGB values palette[color].peRed = rand()%256; palette[color].peGreen = rand()%256; palette[color].peBlue = rand()%256; // set flags field to PC_NOCOLLAPSE palette[color].peFlags = PC_NOCOLLAPSE; } // end for color // now fill in entry 0 and 255 with black and white palette[0].peRed = 0; palette[0].peGreen = 0; palette[0].peBlue = 0; palette[0].peFlags = PC_NOCOLLAPSE; palette[255].peRed = 255; palette[255].peGreen = 255; palette[255].peBlue = 255; palette[255].peFlags = PC_NOCOLLAPSE; // create the palette object if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, palette,&lpddpal, NULL))) return(0); // finally attach the palette to the primary surface if (FAILED(lpddsprimary->SetPalette(lpddpal))) return(0); // set clipper up on back buffer since that's where well clip RECT screen_rect= {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1}; lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect); // load the 8-bit image if (!Load_Bitmap_File(&bitmap,"alley8.bmp")) return(0); // load it's palette into directdraw if (FAILED(lpddpal->SetEntries(0,0,MAX_COLORS_PALETTE,bitmap.palette))) return(0); // clean the surfaces DDraw_Fill_Surface(lpddsprimary,0); DDraw_Fill_Surface(lpddsback,0); // create the buffer to hold the background lpddsbackground = DDraw_Create_Surface(640,480,0,-1); // copy the background bitmap image to the background surface // lock the surface lpddsbackground->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer to primary surfce UCHAR *image_buffer = (UCHAR *)ddsd.lpSurface; // test if memory is linear if (ddsd.lPitch == SCREEN_WIDTH) { // copy memory from double buffer to primary buffer memcpy((void *)image_buffer, (void *)bitmap.buffer, SCREEN_WIDTH*SCREEN_HEIGHT); } // end if else { // non-linear // make copy of source and destination addresses UCHAR *dest_ptr = image_buffer; UCHAR *src_ptr = bitmap.buffer; // memory is non-linear, copy line by line for (int y=0; y < SCREEN_HEIGHT; y++) { // copy line memcpy((void *)dest_ptr, (void *)src_ptr, SCREEN_WIDTH); // advance pointers to next line dest_ptr+=ddsd.lPitch; src_ptr +=SCREEN_WIDTH; } // end for } // end else // now unlock the primary surface if (FAILED(lpddsbackground->Unlock(NULL))) return(0); // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // seed random number generator srand(GetTickCount()); // initialize all the aliens // alien on level 1 of complex aliens[0].x = rand()%SCREEN_WIDTH; aliens[0].y = 116 - 72; aliens[0].velocity = 2+rand()%4; aliens[0].current_frame = 0; aliens[0].counter = 0; // alien on level 2 of complex aliens[1].x = rand()%SCREEN_WIDTH; aliens[1].y = 246 - 72; aliens[1].velocity = 2+rand()%4; aliens[1].current_frame = 0; aliens[1].counter = 0; // alien on level 3 of complex aliens[2].x = rand()%SCREEN_WIDTH; aliens[2].y = 382 - 72; aliens[2].velocity = 2+rand()%4; aliens[2].current_frame = 0; aliens[2].counter = 0; // now load the bitmap containing the alien imagery // then scan the images out into the surfaces of alien[0] // and copy then into the other two, be careful of reference counts! // load the 8-bit image if (!Load_Bitmap_File(&bitmap,"dedsp0.bmp")) return(0); // create each surface and load bits for (int index = 0; index < 3; index++) { // create surface to hold image aliens[0].frames[index] = DDraw_Create_Surface(72,80,0); // now load bits... Scan_Image_Bitmap(&bitmap, // bitmap file to scan image data from aliens[0].frames[index], // surface to hold data index, 0); // cell to scan image from } // end for index // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // now for the tricky part. There is no need to create more surfaces with the same // data, so I'm going to copy the surface pointers member for member to each alien // however, be careful, since the reference counts do NOT go up, you still only need // to release() each surface once! for (index = 0; index < 3; index++) aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index]; // return success or failure or your own return code here return(1); } // end Game_Init
/** * vdraw_ddraw_clear_primary_screen(): Clear the primary screen. * @return 0 on success; non-zero on error. */ int WINAPI vdraw_ddraw_clear_primary_screen(void) { if (!lpDD || !lpDDS_Primary) return -1; DDSURFACEDESC2 ddsd; DDBLTFX ddbltfx; RECT rd; POINT p; memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); ddbltfx.dwFillColor = 0; // Black if (vdraw_get_fullscreen()) { if (Video.VSync_FS) { lpDDS_Flip->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); lpDDS_Primary->Flip(NULL, DDFLIP_WAIT); lpDDS_Flip->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); lpDDS_Primary->Flip(NULL, DDFLIP_WAIT); lpDDS_Flip->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); lpDDS_Primary->Flip(NULL, DDFLIP_WAIT); } else { lpDDS_Primary->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); } } else { p.x = p.y = 0; GetClientRect(gens_window, &rd); ClientToScreen(gens_window, &p); rd.left = p.x; rd.top = p.y; rd.right += p.x; rd.bottom += p.y; // Clip the destination rectangle to the screen. if (rd.bottom > vdraw_rectDisplay.bottom) rd.bottom += (vdraw_rectDisplay.bottom - rd.bottom); if (rd.top < vdraw_rectDisplay.top) rd.top += (vdraw_rectDisplay.top - rd.top); if (rd.left < vdraw_rectDisplay.left) rd.left += (vdraw_rectDisplay.left - rd.left); if (rd.right > vdraw_rectDisplay.right) rd.right += (vdraw_rectDisplay.right - rd.right); if (rd.top < rd.bottom) lpDDS_Primary->Blt(&rd, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx); } return 0; }
/** * vdraw_ddraw_flip(): Flip the screen buffer. [Called by vdraw_flip().] * @return 0 on success; non-zero on error. */ int vdraw_ddraw_flip(void) { if (!lpDD) return -1; HRESULT rval = DD_OK; DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); RECT RectSrc; // Calculate the source rectangle. vdraw_ddraw_calc_RectSrc(RectSrc); if (vdraw_get_fullscreen()) { // Fullscreen. if (vdraw_ddraw_is_hw_render()) { // Hardware rendering. // 1x rendering. // TODO: Test this with border color stuff. // Wine doesn't seem to have a 320x240 fullscreen mode available... // TODO: Test this on a system that supports 1x in fullscreen on DirectDraw. vdraw_ddraw_draw_text(&ddsd, lpDDS_Back, true); if (Video.VSync_FS) { lpDDS_Flip->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC, NULL); lpDDS_Primary->Flip(NULL, DDFLIP_WAIT); } else { lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC, NULL); //lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, NULL, NULL); } } else { // Software rendering. LPDIRECTDRAWSURFACE7 curBlit = lpDDS_Blit; rval = curBlit->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); if (FAILED(rval)) goto cleanup_flip; vdraw_rInfo.destScreen = (void*)ddsd.lpSurface; vdraw_rInfo.width = 320; vdraw_rInfo.height = 240; vdraw_rInfo.destPitch = ddsd.lPitch; if (vdraw_needs_conversion) { // Color depth conversion is required. vdraw_rgb_convert(&vdraw_rInfo); } else { // Color conversion is not required. vdraw_blitFS(&vdraw_rInfo); } // Draw the text. vdraw_ddraw_draw_text(&ddsd, curBlit, false); curBlit->Unlock(NULL); if (curBlit == lpDDS_Back) // note: this can happen in windowed fullscreen, or if CORRECT_256_ASPECT_RATIO is defined and the current display mode is 256 pixels across { if (Video.VSync_FS) { int vb; lpDD->GetVerticalBlankStatus(&vb); if (!vb) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); } lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC, NULL); } else { if (Video.VSync_FS) { lpDDS_Primary->Flip(NULL, DDFLIP_WAIT); } } } } else { // Windowed mode. if (!vdraw_ddraw_is_hw_render()) { rval = lpDDS_Blit->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); if (FAILED(rval)) goto cleanup_flip; vdraw_rInfo.destScreen = (void*)ddsd.lpSurface; vdraw_rInfo.width = 320; vdraw_rInfo.height = 240; vdraw_rInfo.destPitch = ddsd.lPitch; if (vdraw_needs_conversion) { // Color depth conversion is required. vdraw_rgb_convert(&vdraw_rInfo); } else { // Color conversion is not required. vdraw_blitW(&vdraw_rInfo); } // Draw the text. vdraw_ddraw_draw_text(&ddsd, lpDDS_Blit, false); lpDDS_Blit->Unlock(NULL); } else { // Draw the text. vdraw_ddraw_draw_text(&ddsd, lpDDS_Blit, true); } if (RectDest.top < RectDest.bottom) { if (Video.VSync_W) { int vb; lpDD->GetVerticalBlankStatus(&vb); if (!vb) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); } // Blit the image. rval = lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC, NULL); //rval = lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, NULL, NULL); } } cleanup_flip: if (rval == DDERR_SURFACELOST) rval = vdraw_ddraw_restore_graphics(); return 1; }
/** * 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; }
static inline void WINAPI vdraw_ddraw_draw_text(DDSURFACEDESC2* pddsd, LPDIRECTDRAWSURFACE7 lpDDS_Surface, const BOOL lock) { if (lock) lpDDS_Surface->Lock(NULL, pddsd, DDLOCK_WAIT, NULL); // Determine the window size using the scaling factor. const int curHPix = vdp_getHPix(); // +(8*bytespp) is needed for the lpSurface pointer because the DDraw module // includes the entire 336x240 MD_Screen. The first 8 pixels are offscreen, // so they won't show up at all. uint8_t bytespp = (bppOut == 15 ? 2 : bppOut / 8); // NOTE: fullW must be (pddsd->lPitch / bytespp). // DirectDraw likes to use absurdly large line lengths in full screen mode. // (pddsd->lPitch / bytespp) does match pddsd->dwWidth in windowed mode, though. uint8_t *start = (uint8_t*)pddsd->lpSurface; int msg_height; int msg_width; if (vdraw_ddraw_is_hw_render()) { // Hardware rendering uses 1x internally. msg_height = VDP_Lines.Visible.Total; msg_width = curHPix; start += (pddsd->lPitch * VDP_Lines.Visible.Border_Size); if (curHPix < 320) start += (vdp_getHPixBegin() * bytespp); // DirectDraw's hardware rendering uses MD_Screen / MD_Screen32 directly. // Thus, it has an invisible 8px column at the beginning. start += (8 * bytespp); } else { // Software rendering. msg_height = VDP_Lines.Visible.Total * vdraw_scale; msg_width = curHPix * vdraw_scale; start += (pddsd->lPitch * (VDP_Lines.Visible.Border_Size * vdraw_scale)); if (curHPix < 320) start += (vdp_getHPixBegin() * vdraw_scale * bytespp); } if (vdraw_msg_visible) { // Message is visible. draw_text(start, pddsd->lPitch / bytespp, msg_width, msg_height, vdraw_msg_text, &vdraw_msg_style); } else if (vdraw_fps_enabled && (Game != NULL) && Settings.Active && !Settings.Paused && !IS_DEBUGGING()) { // FPS is enabled. draw_text(start, pddsd->lPitch / bytespp, msg_width, msg_height, vdraw_msg_text, &vdraw_fps_style); } if (lock) lpDDS_Surface->Unlock(NULL); }
HRESULT CTextureHolder::CopyBitmapToSurface(){ // Get a DDraw object to create a temporary surface LPDIRECTDRAW7 pDD; m_pddsSurface->GetDDInterface( (VOID**)&pDD ); // Get the bitmap structure (to extract width, height, and bpp) BITMAP bm; GetObject( m_hbmBitmap, sizeof(BITMAP), &bm ); // Setup the new surface desc DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); m_pddsSurface->GetSurfaceDesc( &ddsd ); ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT| DDSD_TEXTURESTAGE; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY; ddsd.ddsCaps.dwCaps2 = 0L; ddsd.dwWidth = bm.bmWidth; ddsd.dwHeight = bm.bmHeight; // Create a new surface for the texture LPDIRECTDRAWSURFACE7 pddsTempSurface; HRESULT hr; if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) ) { pDD->Release(); return hr; } // Get a DC for the bitmap HDC hdcBitmap = CreateCompatibleDC( NULL ); if( NULL == hdcBitmap ) { pddsTempSurface->Release(); pDD->Release(); return hr; // bug? return E_FAIL? } SelectObject( hdcBitmap, m_hbmBitmap ); // Handle palettized textures. Need to attach a palette if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) { LPDIRECTDRAWPALETTE pPalette; DWORD dwPaletteFlags = DDPCAPS_8BIT|DDPCAPS_ALLOW256; DWORD pe[256]; WORD wNumColors = GetDIBColorTable( hdcBitmap, 0, 256, (RGBQUAD*)pe ); // Create the color table for( WORD i=0; i<wNumColors; i++ ) { pe[i] = RGB( GetBValue(pe[i]), GetGValue(pe[i]), GetRValue(pe[i]) ); // Handle textures with transparent pixels if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) { // Set alpha for opaque pixels if( m_dwFlags & D3DTEXTR_TRANSPARENTBLACK ) { if( pe[i] != 0x00000000 ) pe[i] |= 0xff000000; } else if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE ) { if( pe[i] != 0x00ffffff ) pe[i] |= 0xff000000; } } } // Add DDPCAPS_ALPHA flag for textures with transparent pixels if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) dwPaletteFlags |= DDPCAPS_ALPHA; // Create & attach a palette pDD->CreatePalette( dwPaletteFlags, (PALETTEENTRY*)pe, &pPalette, NULL ); pddsTempSurface->SetPalette( pPalette ); m_pddsSurface->SetPalette( pPalette ); SAFE_RELEASE( pPalette ); } // Copy the bitmap image to the surface. HDC hdcSurface; if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) ) { BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0, SRCCOPY ); pddsTempSurface->ReleaseDC( hdcSurface ); } DeleteDC( hdcBitmap ); // Copy the temp surface to the real texture surface m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL ); // Done with the temp surface pddsTempSurface->Release(); // For textures with real alpha (not palettized), set transparent bits if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask ) { if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) ) { // Lock the texture surface DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) == DDERR_WASSTILLDRAWING ); DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask; DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask | ddsd.ddpfPixelFormat.dwGBitMask | ddsd.ddpfPixelFormat.dwBBitMask ); DWORD dwColorkey = 0x00000000; // Colorkey on black if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE ) dwColorkey = dwRGBMask; // Colorkey on white // Add an opaque alpha value to each non-colorkeyed pixel for( DWORD y=0; y<ddsd.dwHeight; y++ ) { WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch); DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch); for( DWORD x=0; x<ddsd.dwWidth; x++ ) { if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 ) { if( ( *p16 &= dwRGBMask ) != dwColorkey ) *p16 |= dwAlphaMask; p16++; } if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 ) { if( ( *p32 &= dwRGBMask ) != dwColorkey ) *p32 |= dwAlphaMask; p32++; } } } m_pddsSurface->Unlock( NULL ); } else if( m_bHasMyAlpha ){ DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) == DDERR_WASSTILLDRAWING ); DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask | ddsd.ddpfPixelFormat.dwGBitMask | ddsd.ddpfPixelFormat.dwBBitMask ); DWORD rMask = ddsd.ddpfPixelFormat.dwRBitMask; DWORD gMask = ddsd.ddpfPixelFormat.dwGBitMask; DWORD bMask = ddsd.ddpfPixelFormat.dwBBitMask; DWORD aMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask; DWORD rShift = GetShift( rMask ); DWORD gShift = GetShift( gMask ); DWORD bShift = GetShift( bMask ); DWORD aShift = GetShift( aMask ); DWORD maxRVal = rMask >> rShift; DWORD maxGVal = gMask >> gShift; DWORD maxBVal = bMask >> bShift; DWORD maxAVal = aMask >> aShift; DWORD rVal, gVal, bVal, aVal; FLOAT min, max; // Add an opaque alpha value to each non-colorkeyed pixel for( DWORD y=0; y<ddsd.dwHeight; y++ ){ WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch); DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch); for( DWORD x=0; x<ddsd.dwWidth; x++ ){ if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 ){ *p32 &= dwRGBMask; // set alpha to zero if( *p32 == 0 ){} // black is 100% transparent, so leave alpha at 0% else if( *p32 == dwRGBMask ){ // white is opaque, so set alpha to 100% *p32 |= aMask; } else{ // set alpha to equal intensity of brightest hue rVal = ( *p32 & rMask ) >> rShift; gVal = ( *p32 & gMask ) >> gShift; bVal = ( *p32 & bMask ) >> bShift; max = max( (FLOAT)rVal / maxRVal, max( (FLOAT)gVal / maxGVal, (FLOAT)bVal / maxBVal ) ); // min = min( (FLOAT)rVal / maxRVal, min( (FLOAT)gVal / maxGVal, (FLOAT)bVal / maxBVal ) ); aVal = max * 255; //if( rVal == gVal && gVal == bVal ){ // white fading to black // *p32 = dwRGBMask; // set color to white //} // maximize luminosity and saturation rVal /= max; gVal /= max; bVal /= max; *p32 = ( aVal << aShift ) | ( rVal << rShift ) | ( gVal << gShift ) | ( bVal << bShift ); } p32++; } else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 ){ *p16 &= dwRGBMask; // set alpha to zero if( *p16 == 0 ){} // black is 100% transparent, so leave alpha at 0% else if( *p16 == dwRGBMask ){ // white is opaque, so set alpha to 100% *p16 |= aMask; } else{ // set alpha to equal intensity of brightest hue rVal = ( *p16 & rMask ) >> rShift; gVal = ( *p16 & gMask ) >> gShift; bVal = ( *p16 & bMask ) >> bShift; aVal = STATSTEXTURE_ALPHA * max( (FLOAT)rVal / maxRVal, max( (FLOAT)gVal / maxGVal, (FLOAT)bVal / maxBVal ) ); if( aVal < STATSTEXTURE_ALPHA ){ // semi-tranparent white *p16 = dwRGBMask; } *p16 |= aVal << aShift; } p16++; } } }
// set frontSurface to lpDDSurface if lpDDSurface is primary // returns true if frontSurface is set // returns false if frontSurface is NULL and lpDDSurface is not primary bool getFrontSurface(LPDIRECTDRAWSURFACE7 lpDDSurface) { //logOutput << CurrentTimeString() << "called getFrontSurface" << endl; if (!lpDDSurface) { //logOutput << CurrentTimeString() << "lpDDSurface null" << endl; return false; } if (!g_ddInterface) { LPDIRECTDRAWSURFACE7 dummy; if (lpDDSurface->QueryInterface(IID_IDirectDrawSurface7, (LPVOID*)&dummy) == S_OK) { IUnknown* Unknown; HRESULT err; if (FAILED(err = dummy->GetDDInterface((LPVOID*)&Unknown))) { logOutput << CurrentTimeString() << "getFrontSurface: could not get DirectDraw interface" << endl; printDDrawError(err, "getFrontSurface"); } else { if (Unknown->QueryInterface(IID_IDirectDraw7, (LPVOID*)&g_ddInterface) == S_OK) { logOutput << CurrentTimeString() << "Got DirectDraw interface pointer" << endl; } else { logOutput << CurrentTimeString() << "Query of DirectDraw interface failed" << endl; } } ddrawSurfaceRelease.Unhook(); dummy->Release(); ddrawSurfaceRelease.Rehook(); } } if (!bTargetAcquired) { DDSCAPS2 caps; if (SUCCEEDED(lpDDSurface->GetCaps(&caps))) { //logOutput << CurrentTimeString() << "checking if surface is primary" << endl; if (caps.dwCaps & DDSCAPS_PRIMARYSURFACE) { logOutput << CurrentTimeString() << "found primary surface" << endl; g_frontSurface = lpDDSurface; if (!SetupDDraw()) { return false; } else { bTargetAcquired = true; } } } else { logOutput << CurrentTimeString() << "could not retrieve caps" << endl; } } return lpDDSurface == g_frontSurface; }
BOOL CH264Decode::PreviewDraw(H264_DEC_FRAME_S DecodeData) { if (!m_bPreEnable) { return true; } DDSURFACEDESC2 ddsd; const HI_U8 *pY = DecodeData.pY; const HI_U8 *pU = DecodeData.pU; const HI_U8 *pV = DecodeData.pV; HI_U32 width = DecodeData.uWidth; HI_U32 height = DecodeData.uHeight; HI_U32 yStride = DecodeData.uYStride; HI_U32 uvStride = DecodeData.uUVStride; if (0 == width || 0 == height) { return true; } ZeroMemory(&ddsd,sizeof(DDSURFACEDESC2)); ddsd.dwSize = sizeof(DDSURFACEDESC2); HRESULT hr; hr = m_pOffscreenSurface->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,NULL); if (FAILED(hr)) { m_dwLastError = hr;//GetLastError(); switch(hr) { case DDERR_SURFACELOST: g_pDirectDraw7->RestoreAllSurfaces(); break; case DDERR_SURFACEBUSY: m_pOffscreenSurface->Unlock(NULL); break; default: break; } return FALSE; } PBYTE pDestY = (PBYTE)ddsd.lpSurface; PBYTE pDestV = (PBYTE)ddsd.lpSurface + ddsd.lPitch * ddsd.dwHeight; PBYTE pDestU = (PBYTE)ddsd.lpSurface + ddsd.lPitch * ddsd.dwHeight*5/4; for (HI_U32 i = 0;i<height;i++) { memcpy(pDestY,pY,yStride); pDestY += ddsd.lPitch; pY += yStride; } for (i = 0;i<height/2;i++) { memcpy(pDestU,pU,uvStride); pDestU += ddsd.lPitch/2; pU += uvStride; } for (i = 0;i<height/2;i++) { memcpy(pDestV,pV,uvStride); pDestV += ddsd.lPitch/2; pV += uvStride; } hr = m_pOffscreenSurface->Unlock(NULL); EnterCriticalSection(&m_csCritial); if (m_PlayWnd != NULL) { RECT rcDsp; ::GetClientRect( m_PlayWnd,&rcDsp); POINT ptTL; POINT ptRB; ptTL.x = rcDsp.left + 1; ptTL.y = rcDsp.top + 1; ptRB.x = rcDsp.right - 1; ptRB.y = rcDsp.bottom - 1; ::ClientToScreen( m_PlayWnd,&ptTL); ::ClientToScreen( m_PlayWnd,&ptRB); SetRect(&rcDsp,ptTL.x,ptTL.y,ptRB.x,ptRB.y); //写OSD /* HDC dcTemp; hr = m_pOSDSurface->GetDC(&dcTemp); DDSURFACEDESC2 ddsdOsd = {0}; ddsdOsd.dwSize = sizeof(ddsdOsd); m_pOSDSurface->GetSurfaceDesc(&ddsdOsd); HBRUSH BackBrush = CreateSolidBrush(RGB(0,0,0)); RECT rcOsd; SetRect(&rcOsd,0,0,ddsdOsd.dwWidth,ddsdOsd.dwHeight); FillRect(dcTemp,&rcOsd,BackBrush); DeleteObject(BackBrush); EnterCriticalSection(&m_csDcCallback); if (NULL != dccallbackFun) { dccallbackFun(dcTemp,m_nDcChl,lpDcUser); } LeaveCriticalSection(&m_csDcCallback); m_pOSDSurface->ReleaseDC(dcTemp); DDSURFACEDESC2 ddsdFin = {0}; ddsdFin.dwSize = sizeof(ddsdFin); m_pFinSurface->GetSurfaceDesc(&ddsdFin); RECT rcFin; SetRect(&rcFin,0,0,ddsdFin.dwWidth,ddsdFin.dwHeight); hr = m_pFinSurface->Blt(&rcFin,m_pOffscreenSurface,&rcSrc,DDBLT_WAIT,NULL); hr = m_pFinSurface->Blt(&rcFin,m_pOSDSurface,NULL,DDBLT_WAIT | DDBLT_KEYSRC,NULL);*/ RECT rcSrc; SetRect(&rcSrc,0,0,width,height); EnterCriticalSection(&g_csClipper); g_pClipper->SetHWnd(NULL,m_PlayWnd); if (::IsWindowVisible(m_PlayWnd)) { g_pPrimarySurface->Blt(&rcDsp,m_pOffscreenSurface,&rcSrc,DDBLT_WAIT,0); } LeaveCriticalSection(&g_csClipper); } LeaveCriticalSection(&m_csCritial); return TRUE; }
////////////////////////////////////////////////////////////////////////////// //INITIALIZATION ////////////////////////////////////////////////////////////////////////////// bool Prog_Init() { lpdd=LPDD_Create(hWndMain,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT); //set the display mode lpdd->SetDisplayMode(SCREENWIDTH,SCREENHEIGHT,SCREENBPP,0,0); //create primary surface DDSURFACEDESC2 ddsd; memset(&ddsd,0,sizeof(DDSURFACEDESC2)); ddsd.dwSize=sizeof(DDSURFACEDESC2); ddsd.dwFlags=DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount=1; ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; lpdd->CreateSurface(&ddsd,&lpddsPrime,NULL); //create back buffer DDSCAPS2 ddscaps; memset(&ddscaps,0,sizeof(DDSCAPS2)); ddscaps.dwCaps=DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE; lpddsPrime->GetAttachedSurface(&ddscaps,&lpddsBack); //create the texture surface memset(&ddsd,0,sizeof(DDSURFACEDESC2)); ddsd.dwSize=sizeof(DDSURFACEDESC2); ddsd.dwFlags=DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.dwWidth=64; ddsd.dwHeight=64; ddsd.ddsCaps.dwCaps=DDSCAPS_TEXTURE; lpdd->CreateSurface(&ddsd,&lpddsTex,NULL); //used ddfuncs to load a bitmap onto the texture LPDDS_ReloadFromFile(lpddsTex,"texture.bmp"); //get the idirect3d pointer lpdd->QueryInterface(IID_IDirect3D7,(void**)&lpd3d);//ICKY COM STUFF! //create the idirect3ddevice(hack method) if(FAILED(lpd3d->CreateDevice(IID_IDirect3DTnLHalDevice,lpddsBack,&lpd3ddev)))//try tnl if(FAILED(lpd3d->CreateDevice(IID_IDirect3DHALDevice,lpddsBack,&lpd3ddev)))//no tnl, try hal if(FAILED(lpd3d->CreateDevice(IID_IDirect3DMMXDevice,lpddsBack,&lpd3ddev)))//no hal, try mmp if(FAILED(lpd3d->CreateDevice(IID_IDirect3DRGBDevice,lpddsBack,&lpd3ddev)))//no mmx, resort to rgb return(false);//problem, return false //set up viewport D3DVIEWPORT7 vp; vp.dwX=0; vp.dwY=0; vp.dwWidth=SCREENWIDTH; vp.dwHeight=SCREENHEIGHT; vp.dvMinZ=0.0; vp.dvMaxZ=1.0; //set viewport for device lpd3ddev->SetViewport(&vp); //initialize the vertices(partially, anyway) vert[0].color=D3DRGB(0.25,0.25,0.25);//set the color for this vertex vert[0].specular=0;//zero for specular vert[0].rhw=1.0;//rhw is 1.0 vert[0].tu=0.0;//0.0 for both texture coordinates vert[0].tv=0.0; vert[0].sz=0.5;//static z value vert[1].color=D3DRGB(0.5,0.5,0.5);//set the color for this vertex vert[1].specular=0;//zero for specular vert[1].rhw=1.0;//rhw is 1.0 vert[1].tu=1.0;//0.0 for both texture coordinates vert[1].tv=0.0; vert[1].sz=0.5;//static z value vert[2].color=D3DRGB(0.5,0.5,0.5);//set the color for this vertex vert[2].specular=0;//zero for specular vert[2].rhw=1.0;//rhw is 1.0 vert[2].tu=0.0;//0.0 for both texture coordinates vert[2].tv=1.0; vert[2].sz=0.5;//static z value vert[3].color=D3DRGB(1.0,1.0,1.0);//set the color for this vertex vert[3].specular=0;//zero for specular vert[3].rhw=1.0;//rhw is 1.0 vert[3].tu=1.0;//0.0 for both texture coordinates vert[3].tv=1.0; vert[3].sz=0.5;//static z value //set the texture lpd3ddev->SetTexture(0,lpddsTex); return(true);//return success }
LPDIRECTDRAWCLIPPER DD_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 ((lpdd->CreateClipper(0,&lpddclipper,NULL))!=DD_OK) 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 ((lpddclipper->SetClipList(region_data, 0))!=DD_OK) { // release memory and return error free(region_data); return(NULL); } // end if // now attach the clipper to the surface if ((lpdds->SetClipper(lpddclipper))!=DD_OK) { // 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 DD_Attach_Clipper
static HRESULT CreateFullScreenDisplay(HWND hWnd, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) { RECT rc; DWORD dwStyle; // Set app window's style to WS_POPUP so that it can fit for full screen mode. dwStyle = GetWindowLong(hWnd, GWL_STYLE); dwStyle &= ~(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); dwStyle |= WS_POPUP; SetWindowLong(hWnd, GWL_STYLE, dwStyle); // Adapt window size SetRect(&rc, 0, 0, dwWidth, dwHeight); AdjustWindowRectEx(&rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, GetWindowExStyle(hWnd)); // Set cooperative level if (FAILED(lpdd->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT))) { return E_FAIL; } // Set the display mode if (FAILED(lpdd->SetDisplayMode(dwWidth, dwHeight, dwBPP, 0, 0))) { return E_FAIL; } // Create primary surface (with backbuffer attached) DDSURFACEDESC2 ddsd; DDRAW_INIT_STRUCT(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT | DDSD_CKSRCBLT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE; ddsd.dwBackBufferCount = 1; if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsMain, NULL))) { return E_FAIL; } // Get a pointer to the back buffer DDSCAPS2 ddscaps; ZeroMemory(&ddscaps, sizeof(ddscaps)); ddscaps.dwCaps = DDSCAPS_BACKBUFFER; if (FAILED(lpddsMain->GetAttachedSurface(&ddscaps, &lpddsBack))) { return E_FAIL; } //lpddsBack->AddRef(); // Set surface color key DDCOLORKEY ddCK; ddCK.dwColorSpaceLowValue = 0; ddCK.dwColorSpaceHighValue = 0; if (lpddsBack->SetColorKey(DDCKEY_SRCBLT, &ddCK)) { return E_FAIL; } // Update window flag SetClassLong(hWnd, GCL_HICONSM, NULL); SendMessage(hWnd, WM_SETICON, ICON_SMALL, NULL); UpdateWindow(hWnd); return S_OK; }
int DD_Init(int width, int height, int bpp) { // this function initializes directdraw int index; // looping variable // create object and test for error if (DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)!=DD_OK) return(0); // set cooperation level to windowed mode normal if (lpdd->SetCooperativeLevel(main_window_handle, DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)!=DD_OK) return(0); // set the display mode if (lpdd->SetDisplayMode(width,height,bpp,0,0)!=DD_OK) return(0); // set globals screen_height = height; screen_width = width; screen_bpp = bpp; // Create the primary surface memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // we need to let dd know that we want a complex // flippable surface structure, set flags for that ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; // set the backbuffer count to 1 ddsd.dwBackBufferCount = 1; // create the primary surface lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL); // query for the backbuffer i.e the secondary surface ddscaps.dwCaps = DDSCAPS_BACKBUFFER; lpddsprimary->GetAttachedSurface(&ddscaps,&lpddsback); // create and attach palette // create palette data // clear all entries defensive programming memset(palette,0,256*sizeof(PALETTEENTRY)); // create a R,G,B,GR gradient palette for (index=0; index < 256; index++) { // set each entry if (index < 64) palette[index].peRed = index*4; else // shades of green if (index >= 64 && index < 128) palette[index].peGreen = (index-64)*4; else // shades of blue if (index >= 128 && index < 192) palette[index].peBlue = (index-128)*4; else // shades of grey if (index >= 192 && index < 256) palette[index].peRed = palette[index].peGreen = palette[index].peBlue = (index-192)*4; // set flags palette[index].peFlags = PC_NOCOLLAPSE; } // end for index // now create the palette object if (lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256, palette,&lpddpal,NULL)!=DD_OK) return(0); // attach the palette to the primary if (lpddsprimary->SetPalette(lpddpal)!=DD_OK) return(0); // clear out both primary and secondary surfaces DD_Fill_Surface(lpddsprimary,0); DD_Fill_Surface(lpddsback,0); // attach a clipper to the screen RECT screen_rect = {0,0,screen_width,screen_height}; lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect); // return success return(1); } // end DD_Init
LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; // Structure for the paint message POINT p = {0, 0}; // Translation point for the window's client region HRESULT hRet; switch (iMsg) { case WM_MOVE: // Make sure we're not moving to be minimized - because otherwise // our ratio varialbes (g_dwXRatio and g_dwYRatio) will end up // being 0, and once we hit CheckBoundries it divides by 0. if (!IsIconic(hwnd)) { g_rcSrc.left = 0; g_rcSrc.right = g_sizex; g_rcSrc.top = 0; g_rcSrc.bottom = g_sizey; GetClientRect(hwnd, &g_rcDst); g_dwXRatio = (g_rcDst.right - g_rcDst.left) * 1000 / (g_rcSrc.right - g_rcSrc.left); g_dwYRatio = (g_rcDst.bottom - g_rcDst.top) * 1000 / (g_rcSrc.bottom - g_rcSrc.top); ClientToScreen(hwnd, &p); g_rcDst.left = p.x; g_rcDst.top = p.y; g_rcDst.bottom += p.y; g_rcDst.right += p.x; CheckBoundries(); } else // Else, hide the overlay... just in case we can't do // destination color keying, this will pull the overlay // off of the screen for the user. if (g_pDDSOverlay && g_pDDSPrimary) g_pDDSOverlay->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, NULL); // Check to make sure our window exists before we tell it to // repaint. This will fail the first time (while the window is being created). if (hwnd) { InvalidateRect(hwnd, NULL, FALSE); UpdateWindow(hwnd); } return 0L; case WM_SIZE: // Another check for the minimization action. This check is // quicker though... if (wParam != SIZE_MINIMIZED) { GetClientRect(hwnd, &g_rcDst); ClientToScreen(hwnd, &p); g_rcDst.left = p.x; g_rcDst.top = p.y; g_rcDst.bottom += p.y; g_rcDst.right += p.x; g_rcSrc.left = 0; g_rcSrc.right = g_sizex; g_rcSrc.top = 0; g_rcSrc.bottom = g_sizey; // Here we multiply by 1000 to preserve 3 decimal places in the // division opperation (we picked 1000 to be on the same order // of magnitude as the stretch factor for easier comparisons) g_dwXRatio = (g_rcDst.right - g_rcDst.left) * 1000 / (g_rcSrc.right - g_rcSrc.left); g_dwYRatio = (g_rcDst.bottom - g_rcDst.top) * 1000 / (g_rcSrc.bottom - g_rcSrc.top); CheckBoundries(); } return 0L; case WM_PAINT: BeginPaint(hwnd, &ps); // Check the primary surface to see if it's lost - if so you can // pretty much bet that the other surfaces are also lost - thus // restore EVERYTHING! If we got our surfaces stolen by a full // screen app - then we'll destroy our primary - and won't be able // to initialize it again. When we get our next paint message (the // full screen app closed for example) we'll want to try to reinit // the surfaces again - that's why there is a check for // g_pDDSPrimary == NULL. The other option, is that our program // went through this process, could init the primary again, but it // couldn't init the overlay, that's why there's a third check for // g_pDDSOverlay == NULL. Make sure that the check for // !g_pDDSPrimary is BEFORE the IsLost call - that way if the // pointer is NULL (ie. !g_pDDSPrimary is TRUE) - the compiler // won't try to evaluate the IsLost function (which, since the // g_pDDSPrimary surface is NULL, would be bad...). if (!g_pDDSPrimary || (g_pDDSPrimary->IsLost() != DD_OK) || (g_pDDSOverlay == NULL)) { DestroyOverlay(); DestroyPrimary(); if (DDPrimaryInit()) if (DDOverlayInit()) if (!DrawOverlay()) DestroyOverlay(); } // UpdateOverlay is how we put the overlay on the screen. if (g_pDDSOverlay && g_pDDSPrimary && g_video->updating) { hRet = g_pDDSOverlay->UpdateOverlay(&g_rcSrc, g_pDDSPrimary, &g_rcDst, g_OverlayFlags, &g_OverlayFX); #ifdef _DEBUG if(hRet != DD_OK) DisplayError("Can't update overlay", hRet); #endif } EndPaint(hwnd, &ps); return 0L; // process mouse and keyboard events case WM_LBUTTONDOWN: mouse(1, lParam); break; case WM_LBUTTONUP: mouse(-1, lParam); break; case WM_RBUTTONDOWN: mouse(2, lParam); break; case WM_RBUTTONUP: mouse(-2, lParam); break; case WM_MBUTTONDOWN: mouse(3, lParam); break; case WM_MBUTTONUP: mouse(-3, lParam); break; case WM_CHAR: g_video->on_key(wParam); break; case WM_DISPLAYCHANGE: return 0L; case WM_DESTROY: // Now, shut down the window... PostQuitMessage(0); return 0L; } return g_pUserProc? g_pUserProc(hwnd, iMsg, wParam, lParam) : DefWindowProc(hwnd, iMsg, wParam, lParam); }
int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, // bitmap file to scan image data from LPDIRECTDRAWSURFACE7 lpdds, // surface to hold data int cx, int cy) // cell to scan image from { // this function extracts a bitmap out of a bitmap file UCHAR *source_ptr, // working pointers *dest_ptr; DDSURFACEDESC2 ddsd; // direct draw surface description // get the addr to destination surface memory // set size of the structure ddsd.dwSize = sizeof(ddsd); lpdds->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // compute position to start scanning bits from /* (0, 0) =》 cx=1, cy=1 (1, 0) => cx=dwWidth+2, cy=1 (2, 0) => cx=2dwWeight + 3, cy = 1 */ // 因为白线的缘故、一条线一个像素点、 // cx负责人物动画帧的起点x坐标、因为人物的左右总有两条白线 // cy负责人物动画帧的起点的y坐标、因为人物的顶头总有一条白色的线 // 所以总是从第二行开始、因为这里传入的cy恒为0、所以cy恒为1 cx = cx*(ddsd.dwWidth + 1) + 1; cy = cy*(ddsd.dwHeight+1) + 1; //gwidth = ddsd.dwWidth; //gheight = ddsd.dwHeight; // dwWidth和dwHeight分别是指人物表面的高宽 // 而biWidth和biHeight分别是指人物动画帧位图的高宽 // extract bitmap data // 为什么要加上biWidth呢、原因是要从第二行才开始录入动画帧表面、因为 // 图片的上方有一条一像素的白色、所以这就是总是要从第二行开始的原因了 // 为什么要加上1呢、因为最左边有一条白线、所以总是要加上1、过滤过它 // ptr => buffer + biWidth + 1 // ptr => buffer + biWidth + dwWidth + 2 // ptr => buffer + biWidth + 2dwWidth + 3 int ptr_offset = cy*bitmap->bitmapinfoheader.biWidth+cx; source_ptr = bitmap->buffer + ptr_offset; // assign a pointer to the memory surface for manipulation dest_ptr = (UCHAR *)ddsd.lpSurface; // iterate thru each scanline and copy bitmap // 一行一行的把位图相应的动画帧拷贝到帧表面上 for (int index_y=0; index_y < ddsd.dwHeight; index_y++) { // copy next line of data to destination // 这个狠好理解、前面确定好要拷贝哪帧的位置后、便从这个source_ptr这个位置点、 // 拷贝dwWidth个字节的位置 memcpy(dest_ptr, source_ptr, ddsd.dwWidth); // advance pointers // 在这里、由于动画帧表面是自己创建的、所以其实lPitch就是dwWidth人物表面的宽度而已 // 这里写lPitch主要也是为了安全而已 // 虽然内容是已经拷贝到相应位置了、但莪们还是要为下一行的拷贝做准备、因为指针还未移动呢! // // 动画帧表面、在拷贝下一行之前移动一整行、刚好就是动画帧的宽、这个比较好理解 // 虽然位图表面要拷贝的不是一整行、而是其中的dwWidth个像素而已、但也依然要移动位图宽度个字节 // 想想、把(x, y)移动到(x, y+1)刚好不就是当前行的下一行么、所以刚好也就是相差biWidth个位置 dest_ptr += (ddsd.lPitch); // (ddsd.dwWidth); source_ptr += bitmap->bitmapinfoheader.biWidth; } // end for index_y // unlock the surface lpdds->Unlock(NULL); // return success return(1); } // end Scan_Image_Bitmap
int Game_Main(void *parms = NULL, int num_parms = 0) { // this is the main loop of the game, do all your processing // here DDBLTFX ddbltfx; // the blitter fx structure static int feeling_counter = 0; // tracks how we feel :) static int happy = 1; // let's start off being happy // make sure this isn't executed again if (window_closed) return(0); // for now test if user is hitting ESC and send WM_CLOSE if (KEYDOWN(VK_ESCAPE)) { PostMessage(main_window_handle,WM_CLOSE,0,0); window_closed = 1; } // end if // use the blitter to erase the back buffer // first initialize the DDBLTFX structure DDRAW_INIT_STRUCT(ddbltfx); // now set the color word info to the color we desire ddbltfx.dwFillColor = 0; // make the blitter call if (FAILED(lpddsback->Blt(NULL, // pointer to dest RECT, NULL for whole thing NULL, // pointer to source surface NULL, // pointer to source RECT DDBLT_COLORFILL | DDBLT_WAIT, // do a color fill and wait if you have to &ddbltfx))) // pointer to DDBLTFX holding info return(0); // initialize ddsd DDRAW_INIT_STRUCT(ddsd); // lock the back buffer surface if (FAILED(lpddsback->Lock(NULL,&ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL))) return(0); // increment how we feel if (++feeling_counter > 200) { feeling_counter = 0; happy = -happy; } // end if // draw all the happy faces for (int face=0; face < 100; face++) { // are we happy or sad? if (happy==1) // we are happy :) Blit_Clipped(happy_faces[face].x, happy_faces[face].y, 8,8, happy_bitmap, (UCHAR *)ddsd.lpSurface, ddsd.lPitch); else // we must be sad :( Blit_Clipped(happy_faces[face].x, happy_faces[face].y, 8,8, sad_bitmap, (UCHAR *)ddsd.lpSurface, ddsd.lPitch); } // end face // move all happy faces for (face=0; face < 100; face++) { // move happy_faces[face].x+=happy_faces[face].xv; happy_faces[face].y+=happy_faces[face].yv; // check for off screen, if so wrap if (happy_faces[face].x > SCREEN_WIDTH) happy_faces[face].x = -8; else if (happy_faces[face].x < -8) happy_faces[face].x = SCREEN_WIDTH; if (happy_faces[face].y > SCREEN_HEIGHT) happy_faces[face].y = -8; else if (happy_faces[face].y < -8) happy_faces[face].y = SCREEN_HEIGHT; } // end face // unlock surface if (FAILED(lpddsback->Unlock(NULL))) return(0); // flip the pages while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); // wait a sec Sleep(30); // return success or failure or your own return code here return(1); } // end Game_Main
int Game_Main(void *parms = NULL, int num_parms = 0) { // this is the main loop of the game, do all your processing // here // lookup for proper walking sequence // 动画帧、先播放站立动作、然后是摆左手、然后再恢复站立动作、然后是摆右手 // 如此重复播放 // 声明为静态、所以不会随着Game_Main的调用而重复初始化 static int animation_seq[4] = {0,1,0,2}; int index; // general looping variable // make sure this isn't executed again if (window_closed) return(0); // for now test if user is hitting ESC and send WM_CLOSE if (KEYDOWN(VK_ESCAPE)) { PostMessage(main_window_handle,WM_CLOSE,0,0); window_closed = 1; } // end if DDRAW_INIT_STRUCT(ddbltfx); if(lpddsback->Blt(NULL, lpddsbackground, NULL, DDBLT_WAIT, &ddbltfx)) return 0; // move objects around // 这里是移动异形 for (index=0; index < 3; index++) { // move each object to the right at its given velocity // 移动异形向右走 aliens[index].x++; // =aliens[index].velocity; // 测试异形的位置是否已经到达了右边界已经完全看不着了 // 就把它又扔会左边从头走过来 // 因为x是左上角的坐标、所以x超过了屏幕宽度刚好完全看不见 // 而因为异形图片的人物宽度刚好为80、所以重置到左边时设置为-80 // test if off screen edge, and wrap around if (aliens[index].x > SCREEN_WIDTH) aliens[index].x = - 80; // animate bot if (++aliens[index].counter >= (8 - aliens[index].velocity)) { // reset counter aliens[index].counter = 0; // advance to next frame // 如果超过第三帧、则重置为第0帧、这里是由前面的结构所决定的、只有三个动作 // 由于采用了先自增再比较的办法、所以条件这里current_frame的范围恒为1~4 // 所谓的第零帧、也就是标准的站立动作、可以从位图图片得知、 if (++aliens[index].current_frame > 3) aliens[index].current_frame = 0; } // end if } // end for index // draw all the bots for (index=0; index < 3; index++) { /* 原型 int DDraw_Draw_Surface(LPDIRECTDRAWSURFACE7 source, // source surface to draw int x, int y, // position to draw at int width, int height, // size of source surface LPDIRECTDRAWSURFACE7 dest, // surface to draw the surface on int transparent = 1) // transparency flag */ // draw objects // 把相应的三个异形的每帧动作拷贝进缓冲表面中 // 其中animation_seq[aliens[index].current_frame]决定了产生哪些动作帧 // 在Game_Main函数就已经有定义了static int animation_seq[4] = {0,1,0,2}; // 这里current_frame的范围就是0~3 DDraw_Draw_Surface(aliens[index].frames[animation_seq[aliens[index].current_frame]], aliens[index].x, aliens[index].y, 72,80, lpddsback); } // end for index while(FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); // 每秒30帧 Sleep(33); // do nothing -- look at pretty picture // return success or failure or your own return code here return(1); } // end Game_Main
//----------------------------------------------------------------------------- // Name: Init() // Desc: Initializes Driect draw and anything that needs to be inited //----------------------------------------------------------------------------- int InitDD() {// this function is where i do all the initialization // for the game // create dd object and test for error ddReturnVal = DirectDrawCreateEx(NULL, (void **)&lpddObj, IID_IDirectDraw7, NULL); if (DDFailedCheck(ddReturnVal, "DirectDrawCreateEx() failed", cpErrorBuf )) { MessageBox(main_window_handle, cpErrorBuf, "Init()", MB_ICONEXCLAMATION); return(0); } // set cooperation level to windowed mode normal ddReturnVal = lpddObj->SetCooperativeLevel(main_window_handle, DDSCL_NORMAL); if (DDFailedCheck(ddReturnVal, "SetCooperativeLevel() failed", cpErrorBuf )) { MessageBox(main_window_handle, cpErrorBuf, "Init()", MB_ICONEXCLAMATION); return(0); } /* // set the display mode ddReturnVal = lpddObj->SetDisplayMode(nWindowWidth,nWindowHeight,BPP,0,0); if (DDFailedCheck(ddReturnVal, "SetDisplayMode() failed", cpErrorBuf )) { MessageBox(main_window_handle, cpErrorBuf, "Init()", MB_ICONEXCLAMATION); return(0); } */ // Create the primary surface first set the fields memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; //set the flags to validate both capabilites field adn the backbuffer count field ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; //tell dd that u have a complex flippable surface //ddsd.dwBackBufferCount = 1; //set the back buffer count //Createt the primary surface ddReturnVal = lpddObj->CreateSurface(&ddsd,&lpddsPrimary,NULL); if (DDFailedCheck(ddReturnVal, "CreateSurface() failed", cpErrorBuf )) { MessageBox(main_window_handle, cpErrorBuf, "Init()", MB_ICONEXCLAMATION); return(0); } //Create an off-screen surface as a backBuffer SCCOLOR col={255,0,255}; lpddsSecondary = CreateSurface(WINDOW_WIDTH, WINDOW_HEIGHT, col); //Attach a clipper RECT cliplist[1]; cliplist[0].top = iWindow_y; cliplist[0].left = iWindow_x; cliplist[0].bottom = iWindow_y+nWindowHeight;//GetSystemMetrics(SM_CYSCREEN); cliplist[0].right = iWindow_x+nWindowWidth;//GetSystemMetrics(SM_CXSCREEN); AttachClipper(lpddsPrimary,main_window_handle); //attack a color key // set color key to TransparentColor DDCOLORKEY color_key; // used to set color key color_key.dwColorSpaceLowValue = _RGB16BIT565(TransColor.r,TransColor.g,TransColor.b); color_key.dwColorSpaceHighValue = _RGB16BIT565(TransColor.r,TransColor.g,TransColor.b); // now set the color key for source blitting ddReturnVal = lpddsPrimary->SetColorKey(DDCKEY_SRCBLT, &color_key); if (DDFailedCheck(ddReturnVal, "SetColorKey() failed", cpErrorBuf )) { MessageBox(main_window_handle, cpErrorBuf, "Init()", MB_ICONEXCLAMATION); return(0); } //"""""""""""""""""""""Init Sprites""""""""""""""""""""" static int array[]={0,1}, array2[]= {0,1,2,3,4,5,6,7,8,9,10,11,12,13}; Sprites[0].InitSprite(64,64,1,1,1,120); Sprites[0].SetAnimations(array,0,SPRITE_ANIM_ONCE,0); Sprites[0].LoadSpriteImage("myface1.bmp"); Sprites[0].SetState(SPRITE_STATE_ALIVE); Sprites[0].SetXPos(100); Sprites[0].SetYPos(100); Sprites[1].InitSprite(43,37,14,6,3,120); Sprites[1].SetAnimations(array2,13,SPRITE_ANIM_CONT,0); Sprites[1].LoadSpriteImage("Expl16.bmp"); Sprites[1].SetState(SPRITE_STATE_ALIVE); Sprites[1].SetXPos(200); Sprites[1].SetYPos(100); //""""""""""""""""""End Init Sprites"""""""""""""""""""" return(1); }
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x24 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount = 1; // // request primary surface ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) return 0; // 把主屏和缓冲屏都填充为黑色初始化 DDraw_Fill_Surface(lpddsprimary, _RGB32BIT(0, 0,0,0)); DDraw_Fill_Surface(lpddsback, _RGB32BIT(0, 0,0,0)); // load the 24-bit image char* bmp_wc = "WarCraft24.bmp"; char* bmp_b8 = "bitmap8b.bmp"; char* bmp_b24 = "bitmap24.bmp"; char* bmp_b24e = "bitmap24_edit.bmp"; char* bmp_mo24 = "mosaic-600x.bmp"; char* bmp_ni24 = "nightelf-640x.bmp"; char* bmp_alley24 = "alley8_24bit.bmp"; // 载入背景图片 if (!Load_Bitmap_File(&bitmap, bmp_ni24)) return(0); // 创建背景表面、但实际上不是直接用背景表面来显示的、而是拷贝去缓冲表面和人物动作混合 // 后才一次性打到显示表面 // 这里头两个参数是指在屏幕的高和宽、第二个是指表面建立的地点、0指在显存建立、其它表示在 // 系统内存建立、当然速度自然是在显存建立快了、最后一个参数是是否设置为色彩键、这里设定为-1 // 也就是不设定任何色彩过滤、因为这个是背景表面、所以不需要任何透明的色彩键 lpddsbackground = DDraw_Create_Surface(640,480,0,-1); // 把bmp的内容拷贝至缓冲表面中 Bmp2Surface(lpddsbackground, SCREEN_WIDTH, SCREEN_HEIGHT); // 从现在开始创建人物动作了 if (!Load_Bitmap_File(&bitmap, "Dedsp0_24bit.bmp")) return(0); // seed random number generator // GetTickCount是一个系统启动至今的毫秒数、 // 配合srandg来产生一个随机数 srand(GetTickCount()); // initialize all the aliens // alien on level 1 of complex // //系统在调用rand()之前都会自动调用srand(),如果用户在rand()之前曾调用过srand()给参数seed指定了一个值, //那么rand()就会将seed的值作为产生伪随机数的初始值; //而如果用户在rand()前没有调用过srand(),那么rand()就会自动调用srand(1),即系统默认将1作为伪随机数的初始值。 //所以前面要调用一次srand来确保以下调用rand()的值会产生不同 // aliens[0].x = rand()%SCREEN_WIDTH; aliens[0].y = 116 - 72; aliens[0].velocity = 2+rand()%4; aliens[0].current_frame = 0; aliens[0].counter = 0; // alien on level 2 of complex aliens[1].x = rand()%SCREEN_WIDTH; aliens[1].y = 246 - 72; aliens[1].velocity = 2+rand()%4; aliens[1].current_frame = 0; aliens[1].counter = 0; // alien on level 3 of complex aliens[2].x = rand()%SCREEN_WIDTH; aliens[2].y = 382 - 72; aliens[2].velocity = 2+rand()%4; aliens[2].current_frame = 0; aliens[2].counter = 0; // now load the bitmap containing the alien imagery // then scan the images out into the surfaces of alien[0] // and copy then into the other two, be careful of reference counts! // 现在开始载入人物的动画帧图片了 if (!Load_Bitmap_File(&bitmap,"Dedsp0_24bit.bmp")) return(0); // create each surface and load bits // 初始化异形0号的三个动作帧表面、 // 其实、所有的异形动作帧表面都一样的、所以没有必要为每个异形都创建相应的动作帧、 // 所以其它异形的动作帧都指向这个异形0号的动作帧就可以了 for (int index = 0; index < 3; index++) { // create surface to hold image aliens[0].frames[index] = DDraw_Create_Surface(72,80,0); // now load bits... Scan_Image_Bitmap(&bitmap, // bitmap file to scan image data from aliens[0].frames[index], // surface to hold data index, 0); // cell to scan image from } // end for index // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // now for the tricky part. There is no need to create more surfaces with the same // data, so I'm going to copy the surface pointers member for member to each alien // however, be careful, since the reference counts do NOT go up, you still only need // to release() each surface once! for (index = 0; index < 3; index++) aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index]; // return success or failure or your own return code here return(1); } // end Game_Init
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x8 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS; // request primary surface ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); // build up the palette data array for (int color=1; color < 255; color++) { // fill with random RGB values palette[color].peRed = rand()%256; palette[color].peGreen = rand()%256; palette[color].peBlue = rand()%256; // set flags field to PC_NOCOLLAPSE palette[color].peFlags = PC_NOCOLLAPSE; } // end for color // now fill in entry 0 and 255 with black and white palette[0].peRed = 0; palette[0].peGreen = 0; palette[0].peBlue = 0; palette[0].peFlags = PC_NOCOLLAPSE; palette[255].peRed = 255; palette[255].peGreen = 255; palette[255].peBlue = 255; palette[255].peFlags = PC_NOCOLLAPSE; // create the palette object if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, palette,&lpddpal, NULL))) return(0); // finally attach the palette to the primary surface if (FAILED(lpddsprimary->SetPalette(lpddpal))) return(0); // return success or failure or your own return code here return(1); } // end Game_Init
//----------------------------------------------------------------------------- // 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; }