int Game_Main(void *parms = NULL, int num_parms = 0) { // this is the main loop of the game, do all your processing // here // 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 the bitmap image to the primary buffer line by line // notice the 24 to 16 bit conversion pixel by pixel // lock the primary surface lpddsprimary->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer to primary surfce USHORT *primary_buffer = (USHORT *)ddsd.lpSurface; // process each line and copy it into the primary buffer for (int index_y = 0; index_y < SCREEN_HEIGHT; index_y++) { for (int index_x = 0; index_x < SCREEN_WIDTH; index_x++) { // get BGR values, note the scaling down of the channels, so that they // fit into the 5.6.5 format UCHAR blue = (bitmap.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 0]) >> 3, green = (bitmap.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 1]) >> 3, red = (bitmap.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 2]) >> 3; // this builds a 16 bit color value in 5.6.5 format (green dominant mode) USHORT pixel = _RGB16BIT565(red,green,blue); // write the pixel primary_buffer[index_x + (index_y*ddsd.lPitch >> 1)] = pixel; } // end for index_x } // end for index_y // now unlock the primary surface if (FAILED(lpddsprimary->Unlock(NULL))) return(0); // do nothing -- look at pretty picture // 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 // 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 // clear out the back buffer DDraw_Fill_Surface(lpddsback, 0); // lock primary buffer DDRAW_INIT_STRUCT(ddsd); if (FAILED(lpddsback->Lock(NULL,&ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL))) return(0); // do the graphics Draw_Polygon2D(&asteroid, (UCHAR *)ddsd.lpSurface, ddsd.lPitch); // test for scale if (KEYDOWN('A')) // scale up Scale_Polygon2D(&asteroid, 1.1, 1.1); else if (KEYDOWN('S')) // scale down Scale_Polygon2D(&asteroid, 0.9, 0.9); // rotate the polygon by 5 degrees Rotate_Polygon2D(&asteroid, 5); // unlock primary buffer if (FAILED(lpddsback->Unlock(NULL))) return(0); // perform the flip while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); // wait a sec Sleep(33); // return success or failure or your own return code here return(1); } // end Game_Main
//----------------------------------------------------------------------------- // Name: Lock() // Desc: Fucntion to lock the entire surface //----------------------------------------------------------------------------- int Lock(LPDIRECTDRAWSURFACE7 lpddsSurface) { memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddReturnVal = lpddsSurface->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); if (DDFailedCheck(ddReturnVal, "Lock(), failed", cpErrorBuf )) { MessageBox(main_window_handle, cpErrorBuf, "SurfaceFuncs, Lock()", MB_ICONEXCLAMATION); return(0); } return (1); }
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); // lock the display surface lpdds->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL); // compute position to start scanning bits from cx = cx*(ddsd.dwWidth+1) + 1; cy = cy*(ddsd.dwHeight+1) + 1; gwidth = ddsd.dwWidth; gheight = ddsd.dwHeight; // extract bitmap data source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx; // 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 memcpy(dest_ptr, source_ptr, ddsd.dwWidth); // advance pointers dest_ptr += (ddsd.lPitch); source_ptr += bitmap->bitmapinfoheader.biWidth; } // end for index_y // unlock the surface lpdds->Unlock(NULL); // return success return(1); } // end Scan_Image_Bitmap
int Bmp2Surface(LPDIRECTDRAWSURFACE7 lpdds, int SurfaceWidth, int SurfaceHeight) { // copy the bitmap image to the lpddsback buffer line by line // notice the 24 to 32 bit conversion pixel by pixel // 一个像素一个像素的逐粒拷贝至表面 // lock the lpddsback surface lpdds->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer to primary surfce DWORD *back_buffer = (DWORD *)ddsd.lpSurface; // process each line and copy it into the lpddsback buffer if (ddsd.lPitch == SurfaceWidth) { // copy memory from double buffer to lpddsback buffer memcpy((void *)back_buffer, (void *)bitmap.buffer, SurfaceWidth*SurfaceHeight); } else { for (int index_y = 0; index_y < SurfaceHeight; index_y++) { for (int index_x = 0; index_x < SurfaceWidth; index_x++) { // get BGR values UCHAR blue = (bitmap.buffer[index_y*SurfaceWidth*3 + index_x*3 + 0]), green = (bitmap.buffer[index_y*SurfaceWidth*3 + index_x*3 + 1]), red = (bitmap.buffer[index_y*SurfaceWidth*3 + index_x*3 + 2]); // this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode) DWORD pixel = _RGB32BIT(0,red,green,blue); // write the pixel back_buffer[index_x + (index_y*ddsd.lPitch >> 2)] = pixel; } // end for index_x } // end for index_y } // now unlock the lpddsback surface if (FAILED(lpdds->Unlock(NULL))) return(0); } // end Bmp2Surface
HRESULT GameDisplayLoop(HWND hWnd, PFPImage pImage, LONG destX, LONG destY) { HRESULT hResult; DDBLTFX ddBltFx; memset(&ddBltFx, 0, sizeof(ddBltFx)); ddBltFx.dwSize = sizeof(ddBltFx); ddBltFx.dwROP = SRCCOPY; RECT rcMain = { 0 }; GetClientRect(hWnd, &rcMain); ClientToScreen(hWnd, ((LPPOINT)&rcMain) + 0); ClientToScreen(hWnd, ((LPPOINT)&rcMain) + 1); //FP_DEBUG_MSG(_T("CLINET RECT: (%d, %d) - (%d, %d)\n"), rcMain.top, rcMain.bottom, rcMain.left, rcMain.right); RECT rcBack = { 0 }; DDSURFACEDESC2 ddsd; DDRAW_INIT_STRUCT(ddsd); if (FAILED(hResult = lpddsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))) { FP_DEBUG_MSG(_T("Lock Error: 0x%08x\n"), hResult); return E_FAIL; } LPPALETTEENTRY lpPalet = NULL; if (FAILED(gameGraphics->ChangePalette(FP_PALETTE_DAY, &lpPalet))) { return E_FAIL; } LPBYTE lpPixel = (LPBYTE)ddsd.lpSurface; LPBYTE lpData = (LPBYTE)pImage->data; LONG n = 0; for (LONG i = 0; i < pImage->height; i++) { n = (i + destY) * ddsd.lPitch + destX * sizeof(PALETTEENTRY); for (LONG j = 0; j < pImage->width; j++, n += 4) { LPBYTE lpPtr = &lpPixel[n]; *(lpPtr + 0) = lpPalet[lpData[(pImage->height - i - 1) * pImage->width + j]].peRed; *(lpPtr + 1) = lpPalet[lpData[(pImage->height - i - 1) * pImage->width + j]].peGreen; *(lpPtr + 2) = lpPalet[lpData[(pImage->height - i - 1) * pImage->width + j]].peBlue; *(lpPtr + 3) = 0; } } lpddsBack->Unlock(NULL); lpddsMain->Blt(&rcMain, lpddsBack, NULL, DDBLT_WAIT, &ddBltFx); 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 // 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 // lock primary buffer DDRAW_INIT_STRUCT(ddsd); if (FAILED(lpddsprimary->Lock(NULL,&ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL))) return(0); // draw 1000 random lines for (int index=0; index < 1000; index++) { Draw_Line(rand()%SCREEN_WIDTH, rand()%SCREEN_HEIGHT, rand()%SCREEN_WIDTH, rand()%SCREEN_HEIGHT, rand()%256, (UCHAR *)ddsd.lpSurface, ddsd.lPitch); } // end for index // unlock primary buffer if (FAILED(lpddsprimary->Unlock(NULL))) return(0); // wait a sec Sleep(33); // return success or failure or your own return code here return(1); } // end Game_Main
//----------------------------------------------------------------------------- // Name: dx_AccessMemoire(...) // Desc: Vérouille/déverouille l'accès à la mémoire vidéo //----------------------------------------------------------------------------- bool dx_AccessMemoire (bool pVerrou) { if (pVerrou) { SurfaceBack->Lock (NULL, &SurfaceDesc, DDLOCK_WAIT, NULL); Pitch = (int)SurfaceDesc.lPitch; Ecran = (BVRA*)SurfaceDesc.lpSurface; } else { SurfaceBack->Unlock (NULL); Pitch = 0; Ecran = NULL; } return dx_Test (); }
//! 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; }
void DDAccurateUpdateDisplay(bool singlestep) { static int framecounter=0; HRESULT hRet; RECT rDest; if (++framecounter > zx81.frameskip || singlestep) framecounter=0; else return; DDFrame->Unlock(NULL); POINT p = {0, 0}; if(!Form1->FullScreen) p=Form1->ClientToScreen(p); rDest=rcdest; rDest.left += p.x; rDest.top += p.y; rDest.right += p.x; rDest.bottom += p.y; //if (Form1->FullScreen) DDDrawBorder(); while(1) { hRet = m_pddsFrontBuffer->Blt(&rDest, DDFrame, &rcsource, DDBLT_WAIT, NULL); if (hRet == DD_OK) break; else if(hRet == DDERR_SURFACELOST) { m_pddsFrontBuffer->Restore(); m_pddsFrame->Restore(); } else if(hRet != DDERR_WASSTILLDRAWING) return; } DDFrame->Lock(NULL, &DDFrameSurface, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); dest=buffer= (BYTE*)DDFrameSurface.lpSurface; }
void DDAccurateInit(int resize) { DDPIXELFORMAT DDpf; DDSURFACEDESC2 ddsd; float OrigW, OrigH, ScaleW, ScaleH; OrigW=Form1->ClientWidth; OrigH=Form1->ClientHeight; if (Form1->StatusBar1->Visible) OrigH -= Form1->StatusBar1->Height; if (Form1->BaseWidth==0) Form1->BaseWidth= NoWinR-NoWinL; if (Form1->BaseHeight==0) Form1->BaseHeight= NoWinT-NoWinB; ScaleW = OrigW / Form1->BaseWidth; ScaleH = OrigH / Form1->BaseHeight; RasterX=0; RasterY=random(256); //fill the DDpf structure and get the BytesPerPixel ZeroMemory (&DDpf, sizeof(DDpf)); DDpf.dwSize = sizeof(DDpf); m_pddsFrontBuffer->GetPixelFormat(&DDpf); BPP = DDpf.dwRGBBitCount/8; Paletteised = (BPP==1) ? true:false; Scale= tv.AdvancedEffects?2:1; //ScanLen=460*BPP; ScanLen=(2+machine.tperscanline*2)*BPP; switch(zx81.bordersize) { case BORDERNONE: WinL=BlWinL; WinR=BlWinR; WinT=BlWinT; WinB=BlWinB; if (zx81.NTSC) { WinT-=24; WinB-=24; } break; case BORDERSMALL: WinL=SmWinL; WinR=SmWinR; WinT=SmWinT; WinB=SmWinB; if (zx81.NTSC) { WinT-=24; WinB-=24; } break; case BORDERNORMAL: WinL=NoWinL; WinR=NoWinR; WinT=NoWinT; WinB=NoWinB; if (zx81.NTSC) { WinT-=24; WinB-=24; } break; case BORDERLARGE: WinL=LaWinL; WinR=LaWinR; WinT=LaWinT; WinB=LaWinB; if (zx81.NTSC) { WinB-=24; } break; case BORDERFULL: WinL=FuWinL; WinR=FuWinR; WinT=FuWinT; WinB=FuWinB; if (zx81.NTSC) WinB-=51; break; } ZeroMemory( &ddsd, sizeof( ddsd ) ); ddsd.dwSize = sizeof( ddsd ); // Create the backbuffer surface ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; if (tv.AdvancedEffects) { WinL*=2; WinR*=2; WinT*=2; WinB*=2; ScanLen*=2; TVW=ddsd.dwWidth = 1024; TVH=ddsd.dwHeight = 768; HSYNC_TOLLERANCE=HTOL*2; HSYNC_MINLEN=10; VSYNC_TOLLERANCE=VTOL*2; VSYNC_MINLEN=350; } else { TVW=ddsd.dwWidth = 520; TVH=ddsd.dwHeight = 380; HSYNC_TOLLERANCE=HTOL; HSYNC_MINLEN=10; VSYNC_TOLLERANCE=VTOL; VSYNC_MINLEN=350; } m_pddsFrame->Release(); m_pddsFrame = NULL; m_pDD->CreateSurface(&ddsd, &m_pddsFrame, NULL); if (zx81.NTSC) VSYNC_TOLLERANCE-=60; if ((resize) && (!Form1->FullScreen)) { Form1->BaseWidth=WinR-WinL; Form1->BaseHeight=WinB-WinT; OrigW = Form1->BaseWidth * ScaleW; OrigH = Form1->BaseHeight * ScaleH; if (Form1->StatusBar1->Visible) OrigH += Form1->StatusBar1->Height; Form1->ClientWidth = OrigW; Form1->ClientHeight = OrigH; } DDFrame=m_pddsFrame; ZeroMemory(&DDFrameSurface, sizeof(DDFrameSurface)); DDFrameSurface.dwSize = sizeof(DDFrameSurface); DDFrame->Lock(NULL, &DDFrameSurface, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); dest=buffer= (BYTE*)DDFrameSurface.lpSurface; TVP=DDFrameSurface.lPitch; RecalcPalette(); RecalcWinSize(); }
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); }
BOOL JCDD_Wrapper::loadBitmapDataFromFile(INT surfaceID, LPWCH filePath) { if(lpjcdd->containsTheOffscreenSurface(surfaceID)) { return FALSE; } JCDD_File file; if(!file.loadData(filePath)) { return FALSE; } JCDD_BitmapData bmpd; if(!bmpd.create(file.getData())) { return FALSE; } BOOL reverseRow = bmpd.bmpInfoHeader.biHeight < 0; INT biWidth = bmpd.bmpInfoHeader.biWidth; INT biHeight = reverseRow ? -bmpd.bmpInfoHeader.biHeight : bmpd.bmpInfoHeader.biHeight; if(bmpd.bmpInfoHeader.biBitCount != BitmapDataBitCount_8 && bmpd.bmpInfoHeader.biBitCount != BitmapDataBitCount_24 && bmpd.bmpInfoHeader.biBitCount != BitmapDataBitCount_32) { return FALSE; } if(!lpjcdd->createOffscreenSurface(surfaceID, bmpd.bmpInfoHeader.biWidth, biHeight)) { return FALSE; } LPJCDD_Surface surface = lpjcdd->getOffscreenSurface(surfaceID); LPDIRECTDRAWSURFACE7 lpdds = surface->getSurface(); DDSURFACEDESC2 ddsd; jcdd_initStruct(&ddsd); if(FAILED(lpdds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))) { lpjcdd->deleteOffscreenSurface(surfaceID); return FALSE; } UINT* buffer = (UINT*)ddsd.lpSurface; INT pixelWidth = bmpd.bmpInfoHeader.biWidth; INT pixelHeight = biHeight; INT pixelWidthCount = 0; INT pixelHeightCount = biHeight - 1; INT pitch = ddsd.lPitch >> 2; if(bmpd.bmpInfoHeader.biBitCount == BitmapDataBitCount_8) { JCDD_BitmapDataColorIterator8Bit it(&bmpd); while(it.hasNext()) { PALETTEENTRY color = bmpd.palette[it.next()]; buffer[pixelWidthCount + pixelHeightCount * pitch] = jcdd_rgb32Bit(0x00, color.peRed, color.peGreen, color.peBlue); if(++pixelWidthCount == pixelWidth) { pixelWidthCount = 0; --pixelHeightCount; } } } else if(bmpd.bmpInfoHeader.biBitCount == BitmapDataBitCount_24) { JCDD_BitmapDataColorIterator24Bit it(&bmpd); while(it.hasNext()) { JCDD_BitmapDataRGB* color = it.next(); buffer[pixelWidthCount + pixelHeightCount * pitch] = jcdd_rgb32Bit(0x00, color->r, color->g, color->b); if(++pixelWidthCount == pixelWidth) { pixelWidthCount = 0; --pixelHeightCount; } } } else if(bmpd.bmpInfoHeader.biBitCount == BitmapDataBitCount_32) { JCDD_BitmapDataColorIterator32Bit it(&bmpd); while(it.hasNext()) { JCDD_BitmapDataXRGB* color = it.next(); buffer[pixelWidthCount + pixelHeightCount * pitch] = jcdd_rgb32Bit(0x00, color->r, color->g, color->b); if(++pixelWidthCount == pixelWidth) { pixelWidthCount = 0; --pixelHeightCount; } } } if(FAILED(lpdds->Unlock(NULL))) { lpjcdd->deleteOffscreenSurface(surfaceID); return FALSE; } return TRUE; }
int Game_Main(void *parms = NULL, int num_parms = 0) { // this is the main loop of the game, do all your processing // here // 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 // clear out the back buffer DDraw_Fill_Surface(lpddsback, 0); // lock primary buffer DDRAW_INIT_STRUCT(ddsd); if (FAILED(lpddsback->Lock(NULL,&ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL))) return(0); // draw all the asteroids for (int curr_index = 0; curr_index < NUM_ASTEROIDS; curr_index++) { // do the graphics Draw_Polygon2D(&asteroids[curr_index], (UCHAR *)ddsd.lpSurface, ddsd.lPitch); // move the asteroid Translate_Polygon2D(&asteroids[curr_index], asteroids[curr_index].xv, asteroids[curr_index].yv); // rotate the polygon by 5 degrees Rotate_Polygon2D(&asteroids[curr_index], 5); // test for out of bounds if (asteroids[curr_index].x0 > SCREEN_WIDTH+100) asteroids[curr_index].x0 = - 100; if (asteroids[curr_index].y0 > SCREEN_HEIGHT+100) asteroids[curr_index].y0 = - 100; if (asteroids[curr_index].x0 < -100) asteroids[curr_index].x0 = SCREEN_WIDTH+100; if (asteroids[curr_index].y0 < -100) asteroids[curr_index].y0 = SCREEN_HEIGHT+100; } // end for curr_asteroid // unlock primary buffer if (FAILED(lpddsback->Unlock(NULL))) return(0); // perform the flip while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); // wait a sec Sleep(33); // 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 // not doing this will cause occasional errors // 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 // lock the back buffer DDRAW_INIT_STRUCT(ddsd); lpddsback->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // alias pointer to back buffer surface UCHAR *back_buffer = (UCHAR *)ddsd.lpSurface; // now clear the back buffer out // linear memory? if (ddsd.lPitch == SCREEN_WIDTH) { memset(back_buffer,0,SCREEN_WIDTH*SCREEN_HEIGHT); } else { // non-linear memory // make copy of video pointer UCHAR *dest_ptr = back_buffer; // clear out memory one line at a time for (int y=0; y<SCREEN_HEIGHT; y++) { // clear next line memset(dest_ptr,0,SCREEN_WIDTH); // advance pointer to next line dest_ptr+=ddsd.lPitch; } // end for y } // end else // you would perform game logic... // draw the next frame into the back buffer, notice that we // must use the lpitch since it's a surface and may not be linear // plot 5000 random pixels for (int index=0; index < 5000; index++) { int x = rand()%SCREEN_WIDTH; int y = rand()%SCREEN_HEIGHT; UCHAR col = rand()%256; back_buffer[x+y*ddsd.lPitch] = col; } // end for index // unlock the back buffer if (FAILED(lpddsback->Unlock(NULL))) return(0); // perform the flip while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); // return success or failure or your own return code here return(1); } // end Game_Main
/** * 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; }
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 (in real life do this in a loop or function) // 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; aliens[0].width = 72; // set real size aliens[0].height = 80; aliens[0].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[0].y+=(72 - aliens[0].scale*72); // 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; aliens[1].width = 72; // set real size aliens[1].height = 80; aliens[1].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[1].y+=(72 - aliens[1].scale*72); // 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; aliens[2].width = 72; // set real size aliens[2].height = 80; aliens[2].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[2].y+=(72 - aliens[2].scale*72); // 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
int Game_Main(void *parms = NULL, int num_parms = 0) { DDBLTFX ddbltfx; RECT dest_rect; static short curr_color = 0; static short top = 0; static short left = 0; if (window_closed) { return (0); } // for now test if user is hitting ESC and send WM_CLOSE if (KEYDOWN(VK_ESCAPE)) { window_closed = true; SendMessage(main_window_handle,WM_CLOSE,0,0); } // just blast pixels here.. #if 0 // this is the main loop of the game, do all your processing // here memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if (FAILED(lpddsprimary->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL) ) ) { // BAD SHIT HAPPENED HERE... g_ddStepFailure = DDSF_LOCKFAILED; SendMessage(main_window_handle,WM_CLOSE,0,0); } int mempitch = (ddsd.lPitch >> 1); // adjust for words.. WORD *video_buffer = (WORD *) ddsd.lpSurface; #endif // prefigure mPitchlookup for even greater speed. // x1,y1 dest_rect.left = left; dest_rect.top = top; // x2,y2 dest_rect.right = dest_rect.left+20; dest_rect.bottom = dest_rect.top+20; // setup structure!!!! memset(&ddbltfx,0,sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); // color to fill. ddbltfx.dwFillColor = colors16[curr_color]; // blit it baby! if (FAILED(lpddsprimary->Blt(&dest_rect, NULL, // no source surface.. its just a fill NULL, // no source RECT, since no source surface.. DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx ))) { return(0); } #if 0 lpddsprimary->Unlock(NULL); #endif top = top + 10; left = left + 10; if (top > SCREEN_HEIGHT - 20) { top = 0; } if (left > SCREEN_WIDTH - 20) { left = 0; } curr_color++; if (curr_color > 5000) { curr_color = 0; } // 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 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 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