win_vid.c

来自「经典的老游戏digger的源代码.提起digger相信很多人会回忆起曾经为了它挑」· C语言 代码 · 共 1,254 行 · 第 1/3 页

C
1,254
字号
  {
    InvalidateRect(hWnd, NULL, FALSE);
    UpdateWindow(hWnd);
  }
  else
  {
//    if (g_pDDSPrimary && !suspend_game)
//      return IDirectDrawSurface_Blt(g_pDDSPrimary,  &g_rcScreen, g_pDDSBack, &rc_draw_area, DDBLT_WAIT, NULL);
    if (cur_dialog_box)
      GetWindowRect(cur_dialog_box,&nodraw);
    IDirectDrawSurface_Lock(g_pDDSPrimary,NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
    for (x=0;x<640;x++)
      for (y=0;y<400;y++)
      {
        if (cur_dialog_box)
        {
          pt.x = x;
          pt.y = y;
          if (PtInRect(&nodraw,pt))
            continue;
        }
        ((char*) ddsd.lpSurface)[y*ddsd.lPitch+x]=back_bitmap_bits[y*640+x];
      }
    IDirectDrawSurface_Unlock(g_pDDSPrimary, ddsd.lpSurface);
  }
  return DD_OK;
}

/* This is ONLY called when the window receives a WM_PAINT message. */
/* Repaint all or a portion of the window.                          */
/* (used in both Windowed and Fullscreen mode)                      */
void blit_to_window_dc(HWND wnd)
{
  HDC hDC;
  PAINTSTRUCT paintStruct;

  hDC = BeginPaint(hWnd, &paintStruct);
  if (palettized_desktop)
  {
    SelectPalette (hDC, desktop_palette, TRUE);
    RealizePalette (hDC);
  }

  if (g_bWindowed)
  {
    BitBlt(hDC,0,0,640,400,back_dc, 0,0,SRCCOPY);
  }
  else
    BitBlt(hDC,g_rcScreen.left,g_rcScreen.top,640,400,back_dc, 0,0,SRCCOPY);
  EndPaint(hWnd, &paintStruct);
}

HRESULT restore_surface()
{
  HRESULT hRet;
  hRet=IDirectDrawSurface_Restore(g_pDDSPrimary);
  if (hRet != DD_OK)
  {
    fatal_error(hRet, "DirectDraw: restore surfaces (primary) failed");
  }
  return TRUE;
}

/* Blits the given rectangle to the Window (or marks the given rectangle */
/* as dirty if Async option is on).                                      */
/* In DirectX/Fullscreen mode, there must NOT be a Clipper attached to   */
/* the surface (otherwise BltFast will not work).                        */
void blit_rect_to_window(int x, int y, int w, int h)
{
  RECT rect;
  DDSURFACEDESC ddsd;
  int xi,yi;

  ddsd.dwSize=sizeof(ddsd);

//  if (!g_bWindowed && !g_bActive)
//    return;

  if (g_bWindowed || preferred_video_mode.bpp > 8)
  {
    rect.left=x;
    rect.right=x+w;
    rect.top=y;
    rect.bottom=y+h;
    InvalidateRect(hWnd, &rect, FALSE);
    if (!use_async_screen_updates)
      UpdateWindow(hWnd);
  }
  else
  {
    if (g_pDDSPrimary)
    {
      rect.left=x;
      rect.right=x+w;
      rect.top=y;
      rect.bottom=y+h;
//      IDirectDrawSurface_BltFast(g_pDDSPrimary, g_rcScreen.left+x, g_rcScreen.top+y, g_pDDSBack, &rect, DDBLTFAST_NOCOLORKEY /* | DDBLTFAST_WAIT */);
      IDirectDrawSurface_Lock(g_pDDSPrimary,&rect, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
      for (xi=0;xi<w;xi++)
        for (yi=0;yi<h;yi++)
          ((char*) ddsd.lpSurface)[yi*ddsd.lPitch+xi]=back_bitmap_bits[(yi+y)*640+xi+x];
      IDirectDrawSurface_Unlock(g_pDDSPrimary, ddsd.lpSurface);
    }
  }
}

/* This function creates a back buffer for drawing on.             */
/*  - on Win32 this is a DIBSection                                */
bool create_back_buffer(HDC window_dc)
{
  HANDLE hloc;
  BITMAPINFO *pbmi;

  back_dc = CreateCompatibleDC(window_dc);
  back_bitmap=0;

  hloc = LocalAlloc(LMEM_ZEROINIT | LMEM_MOVEABLE, sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 16));
  pbmi = (BITMAPINFO*) LocalLock(hloc);
  pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  pbmi->bmiHeader.biWidth = 640;
  pbmi->bmiHeader.biHeight = -400;
  pbmi->bmiHeader.biPlanes = 1;
  pbmi->bmiHeader.biBitCount = 8;
  pbmi->bmiHeader.biClrUsed = 16;
  pbmi->bmiHeader.biClrImportant = 16;
  pbmi->bmiHeader.biCompression = BI_RGB;
  memset(pbmi->bmiColors,0,sizeof(RGBQUAD)*16);
  back_bitmap = CreateDIBSection(window_dc, (BITMAPINFO*) pbmi, DIB_RGB_COLORS, (VOID **) &back_bitmap_bits, (HANDLE) NULL, 0);
  LocalFree(hloc);
  if (!back_bitmap)
    return FALSE;
  old_bitmap = SelectObject(back_dc, back_bitmap);

  return TRUE;
}

void destroy_back_buffer()
{
  release_directdraw_objects();
  SelectObject(back_dc, old_bitmap);
  DeleteObject(back_bitmap);
  DeleteDC(back_dc);
  DeleteObject(desktop_palette);
}

HRESULT release_directdraw_objects()
{
  if (use_direct_draw)
  {
    if (g_pDD != NULL)
    {
      IDirectDraw_RestoreDisplayMode(g_pDD);
      IDirectDraw_SetCooperativeLevel(g_pDD, hWnd, DDSCL_NORMAL);
//      if (g_pDDSBack != NULL)
//      {
//          IDirectDraw_Release(g_pDDSBack);
//          g_pDDSBack = NULL;
//      }
      if (g_pDDSPrimary != NULL)
      {
          IDirectDraw_Release(g_pDDSPrimary);
          g_pDDSPrimary = NULL;
      }
    }
  }
  return DD_OK;
}

HRESULT fatal_error(HRESULT hRet, LPCTSTR szError)
{
  windows_finish();
  MessageBox(hWnd, szError, "Digger", MB_OK);
  DestroyWindow(hWnd);
  exit(1);
  return hRet;
}


HRESULT init_surfaces()
{
  HRESULT          hRet;
  DDSURFACEDESC   ddsd;
  DDBLTFX ddbltfx;
  int i, palnum;
  HDC hDC;
  LOGPALETTE*      logpalette;
  RGBQUAD *wp[] = { vga16_pal1_rgbq,vga16_pal1i_rgbq,vga16_pal2_rgbq,vga16_pal2i_rgbq };

  if (!use_direct_draw)
    g_bWindowed=TRUE;

  if (g_bWindowed)
  {
    /* Are we running in 256 colors (or less)?  */

    hDC=GetDC(hWnd);
    palettized_desktop=GetDeviceCaps(hDC, RASTERCAPS)&RC_PALETTE;
    if (palettized_desktop)
    {
      logpalette=(LOGPALETTE*) malloc(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*64);
      if (!logpalette)
        fatal_error(0,"init_surfaces: could not allocate memory for 'logpalette'");
      logpalette->palNumEntries=64;
      logpalette->palVersion=0x300;

      for (palnum=0;palnum<4;palnum++)
        for (i=0;i<16;i++)
        {
          logpalette->palPalEntry[palnum*16+i].peRed=wp[palnum][i].rgbRed;
          logpalette->palPalEntry[palnum*16+i].peBlue=wp[palnum][i].rgbBlue;
          logpalette->palPalEntry[palnum*16+i].peGreen=wp[palnum][i].rgbGreen;
          logpalette->palPalEntry[palnum*16+i].peFlags=(BYTE) NULL; //PC_NOCOLLAPSE;
        }

      desktop_palette=CreatePalette(logpalette);
      free (logpalette);
      SelectPalette(hDC,desktop_palette,TRUE);
      i=RealizePalette(hDC);
    }
    ReleaseDC(hWnd, hDC);
    if (use_direct_draw)
    {
      IDirectDraw_RestoreDisplayMode(g_pDD);
      hRet = IDirectDraw_SetCooperativeLevel(g_pDD, hWnd, DDSCL_NORMAL);
      if (hRet != DD_OK)
        return fatal_error(hRet, "DirectDraw: SetCooperativeLevel FAILED");
    }
    GetClientRect(hWnd, &g_rcViewport);
    GetClientRect(hWnd, &g_rcScreen);
    ClientToScreen(hWnd, (POINT*)&g_rcScreen.left);
    ClientToScreen(hWnd, (POINT*)&g_rcScreen.right);
  }
  else
  {
    SetWindowLong(hWnd, GWL_STYLE, DIGGER_WS_FULLSCREEN);
    if (preferred_video_mode.height<=400)
      SetMenu(hWnd,NULL);
    hRet = IDirectDraw_SetCooperativeLevel(g_pDD, hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
    if (hRet != DD_OK)
      return fatal_error(hRet, "DirectDraw: SetCooperativeLevel (fullscreen) FAILED");

    SetRect(&g_rcViewport, 0, 0, 640, 400 );
    memcpy(&g_rcScreen, &g_rcViewport, sizeof(RECT) );

    if (!use_640x480_fullscreen)
      hRet = IDirectDraw_SetDisplayMode(g_pDD, preferred_video_mode.width, preferred_video_mode.height, preferred_video_mode.bpp);
    if (hRet != DD_OK || use_640x480_fullscreen)
    {
      hRet = IDirectDraw_SetDisplayMode(g_pDD, 640, 480, 8);
      if (hRet != DD_OK)
      {
        return fatal_error(hRet, "DirectDraw: SetDisplayMode FAILED");
      }
      SetRect(&g_rcViewport, 0, 40, 640, 440 );
      memcpy(&g_rcScreen, &g_rcViewport, sizeof(RECT) );
    }

    /* Create the primary surface */
    ZeroMemory(&ddsd,sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    hRet = IDirectDraw_CreateSurface(g_pDD, &ddsd, &g_pDDSPrimary, NULL);
    if (hRet != DD_OK)
      return fatal_error(hRet, "DirectDraw: CreateSurface (primary, fullscreen) FAILED");

    vgainten(cur_intensity);

    /* clear the screen */
    ZeroMemory(&ddbltfx,sizeof(DDBLTFX));
    ddbltfx.dwFillColor=0;
    ddbltfx.dwSize=sizeof(DDBLTFX);
    IDirectDrawSurface_Blt(g_pDDSPrimary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT , &ddbltfx );

  }
  rc_640x400.left=0;
  rc_640x400.top=0;
  rc_640x400.right=640;
  rc_640x400.bottom=400;
  rc_draw_area.left=0;
  rc_draw_area.top=0;
  rc_draw_area.right=640;
  rc_draw_area.bottom=400;
  return DD_OK;
}

void destroy_palettes()
{
  fullscreen_palette[0]=NULL;
}

void init_palettes()
{
  HRESULT          hRet;
  PALETTEENTRY     palentry[256];
  int i, palnum;
  HDC hDC;
  LOGPALETTE*      logpalette;

  if (!use_direct_draw)
    g_bWindowed=TRUE;

  if (g_bWindowed)
  {
    /* Are we running in 256 colors (or less)?  */

    hDC=GetDC(hWnd);
    palettized_desktop=GetDeviceCaps(hDC, RASTERCAPS)&RC_PALETTE;
    if (palettized_desktop)
    {
      logpalette=(LOGPALETTE*) malloc(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*64);
      if (!logpalette)
        fatal_error(0,"init_surfaces: could not allocate memory for 'logpalette'");
      logpalette->palNumEntries=64;
      logpalette->palVersion=0x300;

      for (palnum=0;palnum<4;palnum++)
        for (i=0;i<16;i++)
        {
          logpalette->palPalEntry[palnum*16+i].peRed=windowed_palette[palnum][i].rgbRed;
          logpalette->palPalEntry[palnum*16+i].peBlue=windowed_palette[palnum][i].rgbBlue;
          logpalette->palPalEntry[palnum*16+i].peGreen=windowed_palette[palnum][i].rgbGreen;
          logpalette->palPalEntry[palnum*16+i].peFlags=(BYTE) NULL; //PC_NOCOLLAPSE;
        }

      desktop_palette=CreatePalette(logpalette);
      free (logpalette);
      SelectPalette(hDC,desktop_palette,TRUE);
      i=RealizePalette(hDC);
    }
    ReleaseDC(hWnd, hDC);

/*
    if (use_direct_draw)
    {
      hRet = IDirectDraw_SetCooperativeLevel(g_pDD, hWnd, DDSCL_NORMAL);
      if (hRet != DD_OK)
        fatal_error(hRet, "DirectDraw: SetCooperativeLevel FAILED");
    }
*/
    GetClientRect(hWnd, &g_rcViewport);
    GetClientRect(hWnd, &g_rcScreen);
    ClientToScreen(hWnd, (POINT*)&g_rcScreen.left);
    ClientToScreen(hWnd, (POINT*)&g_rcScreen.right);
  }
  else
  {
    if (fullscreen_palette[0]==NULL)
    {
      for (palnum=0;palnum<4;palnum++)
      {
        for (i=0;i<256;i++)
        {
          if (i<16)
          {
            palentry[i].peRed=windowed_palette[palnum][i].rgbRed;
            palentry[i].peBlue=windowed_palette[palnum][i].rgbBlue;
            palentry[i].peGreen=windowed_palette[palnum][i].rgbGreen;
            palentry[i].peFlags=(BYTE) NULL;
          }
          else
          {
            palentry[i].peRed=0;
            palentry[i].peBlue=0;
            palentry[i].peGreen=0;
            palentry[i].peFlags=(BYTE) NULL;
          }
        }
        IDirectDraw_CreatePalette(g_pDD, DDPCAPS_8BIT, palentry, &fullscreen_palette[palnum], NULL);
      }
    }

    vgainten(cur_intensity);
  }
}

/* toggle between windowed and fullscreen mode */

HRESULT ChangeCoopLevel()
{
    HRESULT hRet;

    if (FAILED(hRet = release_directdraw_objects()))
      return fatal_error(hRet, "DirectDraw: release_directdraw_objects FAILED");

    if (g_bWindowed)
    {
      SetWindowLong(hWnd, GWL_STYLE, DIGGER_WS_WINDOWED);
      SetWindowPos(hWnd, HWND_NOTOPMOST, g_rcWindow.left, g_rcWindow.top,
                  (g_rcWindow.right - g_rcWindow.left),
                  (g_rcWindow.bottom - g_rcWindow.top), SWP_SHOWWINDOW );
      InvalidateRect(NULL, NULL, TRUE);   // all windows should be repainted
    }
    hRet = init_surfaces();
    init_palettes();
    return hRet;
}

void init_directdraw()
{
  HRESULT hRet;
  DDSURFACEDESC ddsd;

  GetWindowRect(hWnd, &g_rcWindow); // what is this doing here???

  if (!lpDirectDrawCreate)
  {
    use_direct_draw=0;
    return;
  }

  hRet = DirectDrawCreate( NULL, &g_pDD, NULL);
  if (hRet==DD_OK)
  {
    use_direct_draw=1;
  }
  memset(&ddsd,0,sizeof(ddsd));
  ddsd.dwSize=sizeof(ddsd);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?