⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rw_ddraw.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): rw_draw.h - This handles DirecTDraw management under Windows.     }
{                                                                            }
{ Initial conversion (90%) by : Savage (Dominique@SavageSoftware.com.au)     }
{ Final conversion by : Massimo (max-67@libero.it)                           }
{ Initial conversion on : 09-Jan-2002                                        }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ Copyright (C) 1997-2001 Id Software, Inc.                                  }
{                                                                            }
{ This program is free software; you can redistribute it and/or              }
{ modify it under the terms of the GNU General Public License                }
{ as published by the Free Software Foundation; either version 2             }
{ of the License, or (at your option) any later version.                     }
{                                                                            }
{ This program is distributed in the hope that it will be useful,            }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of             }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       }
{                                                                            }
{ See the GNU General Public License for more details.                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ Updated on :                                                               }
{ Updated by :                                                               }
{                                                                            }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{ 1) ?                                                                       }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{ 1) ?                                                                       }
{----------------------------------------------------------------------------}

unit rw_ddraw;

interface

uses
  Windows,
  SysUtils,
  r_local;

var
  d_8to24table: array[0..255] of Word;

function DDrawError(code: integer): string;
function DDRAW_Init(ppbuffer: PByte; ppitch: Pinteger): Boolean; //qboolean;
procedure DDRAW_Shutdown;
procedure DDRAW_SetPalette( palette: PByteArray);

implementation

uses Directdraw,
  rw_win;

(*
** DDRAW_Init
**
** Builds our DDRAW stuff
*)

function DDRAW_Init(ppbuffer: PByte; ppitch: Pinteger): Boolean; //qboolean;
var
  ddrval: HRESULT;
  ddsd: TDDSURFACEDESC;
  ddscaps: TDDSCAPS;
  palentries: array[0..255] of TPALETTEENTRY;
  i: integer;
  sw_allow_modex: PChar;
  QDirectDrawCreate: function(lpGUID: PGUID; lplpDDRAW: IDIRECTDRAW; pUnkOuter:
    IUnknown): Hresult;
begin
  ri.Con_Printf(PRINT_ALL, 'Initializing DirectDraw ');

  for i := 0 to 255 do
  begin
    palentries[i].peRed := (d_8to24table[i] shr 0) and $FF;
    palentries[i].peGreen := (d_8to24table[i] shr 8) and $FF;
    palentries[i].peBlue := (d_8to24table[i] shr 16) and $FF;
  end;

  (*
  ** load DLL and fetch pointer to entry point
  *)
  if not (sww_state.hinstDDRAW = 0) then
  begin
    ri.Con_Printf(PRINT_ALL, '...loading DDRAW.DLL: ');
    sww_state.hinstDDRAW := LoadLibrary('ddraw.dll');
    if (sww_state.hinstDDRAW = 0) then
    begin
      ri.Con_Printf(PRINT_ALL, 'failed ');
      DDRAW_Shutdown;
      result := False;
      Exit;
    end;
    ri.Con_Printf(PRINT_ALL, 'ok ');
  end;

  QDirectDrawCreate := GetProcAddress(sww_state.hinstDDRAW, 'DirectDrawCreate');
  if (QDirectDrawCreate = nil) then
  begin
    ri.Con_Printf(PRINT_ALL, '*** DirectDrawCreate = nil *** ');
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;

  (*
  ** create the direct draw object
  *)
  ri.Con_Printf(PRINT_ALL, '...creating DirectDraw object: ');
  ddrval := QDirectDrawCreate(nil, sww_state.lpDirectDraw, nil);
  if (ddrval <> DD_OK) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed - %s ', DDrawError(ddrval));
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;
  ri.Con_Printf(PRINT_ALL, 'ok ');

  (*
  ** see if linear modes exist first
  *)
  sww_state.modex := false;

  ri.Con_Printf(PRINT_ALL, '...setting exclusive mode: ');
  ddrval :=
    sww_state.lpDIRECTDraw.SetCooperativeLevel( sww_state.h_Wnd,
    DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN);
  if (ddrval <> DD_OK) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed - %s ', DDrawError(ddrval));
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;
  ri.Con_Printf(PRINT_ALL, 'ok ');

  (*
  ** try changing the display mode normally
  *)
  ri.Con_Printf(PRINT_ALL, '...finding display mode ');
  ri.Con_Printf(PRINT_ALL, '...setting linear mode: ');
  ddrval := sww_state.lpDIRECTDraw.SetDisplayMode( vid.width, vid.height, 8);
  if (ddrval = DD_OK) then
    ri.Con_Printf(PRINT_ALL, 'ok ')
    (*
    ** if no linear mode found, go for modex if we're trying 32$240
    *)
  else if ((sw_mode.value = 0) and sw_allow_modex.value) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed ');
    ri.Con_Printf(PRINT_ALL, '...attempting ModeX 320x240: ');

    (*
    ** reset to normal cooperative level
    *)
    sww_state.lpDIRECTDraw.SetCooperativeLevel( sww_state.h_Wnd, DDSCL_NORMAL);

    (*
    ** set exclusive mode
    *)
    ddrval :=
      sww_state.lpDIRECTDraw.SetCooperativeLevel( sww_state.h_Wnd,
                                                  DDSCL_EXCLUSIVE or
                                                  DDSCL_FULLSCREEN or
                                                  DDSCL_NOWINDOWCHANGES or
                                                  DDSCL_ALLOWMODEX);
    if (ddrval <> DD_OK) then
    begin
      ri.Con_Printf(PRINT_ALL, 'failed SCL - %s ', DDrawError(ddrval));
      DDRAW_Shutdown;
      result := False;
      Exit;
    end;

    (*
    ** change our display mode
    *)
    ddrval := sww_state.lpDIRECTDraw.SetDisplayMode( vid.Width, vid.height, 8);
    if (ddrval <> DD_OK) then
    begin
      ri.Con_Printf(PRINT_ALL, 'failed SDM - %s ', DDrawError(ddrval));
      DDRAW_Shutdown;
      result := False;
      Exit;
    end;
    ri.Con_Printf(PRINT_ALL, 'ok ');

    sww_state.modex := true;
  end
  else
  begin
    ri.Con_Printf(PRINT_ALL, 'failed ');
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;

  (*
  ** create our front buffer
  *)
  FillChar(ddsd, sizeof(ddsd), 0);
  ddsd.dwSize := sizeof(ddsd);
  ddsd.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
  ddsd.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE or DDSCAPS_FLIP or
    DDSCAPS_COMPLEX;
  ddsd.dwBackBufferCount := 1;

  ri.Con_Printf(PRINT_ALL, '...creating front buffer: ');
  ddrval := sww_state.lpDIRECTDraw.CreateSurface( ddsd, sww_state.lpddsFrontBuffer, nil);
  if (ddrval <> DD_OK) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed - %s ', DDrawError(ddrval));
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;
  ri.Con_Printf(PRINT_ALL, 'ok ');

  (*
  ** see if we're a ModeX mode
  *)
  sww_state.lpddsFrontBuffer.GetCaps( ddscaps);
  if (ddscaps.dwCaps and DDSCAPS_MODEX) = 0 then
    ri.Con_Printf(PRINT_ALL, '...using ModeX ');

  (*
  ** create our back buffer
  *)
    ddsd.ddsCaps.dwCaps := DDSCAPS_BACKBUFFER;

  ri.Con_Printf(PRINT_ALL, '...creating back buffer: ');
  ddrval := sww_state.lpddsFrontBuffer.GetAttachedSurface(ddsd.ddsCaps,
                                                          sww_state.lpddsBackBuffer);
  if (ddrval <> DD_OK) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed - %s ', DDrawError(ddrval));
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;
  ri.Con_Printf(PRINT_ALL, 'ok ');

  (*
  ** create our rendering buffer
  *)
  FillChar(ddsd, sizeof(ddsd), 0);
  ddsd.dwSize := sizeof(ddsd);
  ddsd.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS;
  ddsd.dwHeight := vid.height;
  ddsd.dwWidth := vid.width;
  ddsd.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN or DDSCAPS_SYSTEMMEMORY;

  ri.Con_Printf(PRINT_ALL, '...creating offscreen buffer: ');
  ddrval := sww_state.lpDIRECTDraw.CreateSurface( ddsd,sww_state.lpddsOffScreenBuffer, nil);
  if (ddrval <> DD_OK) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed - %s ', DDrawError(ddrval));
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;
  ri.Con_Printf(PRINT_ALL, 'ok ');

  (*
  ** create our DIRECTDRAWPALETTE
  *)
  ri.Con_Printf(PRINT_ALL, '...creating palette: ');
  ddrval := sww_state.lpDIRECTDraw.CreatePalette( DDPCAPS_8BIT or DDPCAPS_ALLOW256, @palentries,
    sww_state.lpddpPalette,
    nil);
  if (ddrval <> DD_OK) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed - %s ', DDrawError(ddrval));
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;
  ri.Con_Printf(PRINT_ALL, 'ok ');

  ri.Con_Printf(PRINT_ALL, '...setting palette: ');
  ddrval :=
    sww_state.lpddsFrontBuffer.SetPalette( sww_state.lpddpPalette);
  if (ddrval <> DD_OK) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed - %s ', DDrawError(ddrval));
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;
  ri.Con_Printf(PRINT_ALL, 'ok ');

  DDRAW_SetPalette(@sw_state.currentpalette);

  (*
  ** lock the back buffer
  *)
  FillChar(ddsd, sizeof(ddsd), 0);
  ddsd.dwSize := sizeof(ddsd);

  ri.Con_Printf(PRINT_ALL, '...locking backbuffer: ');
  ddrval :=
    sww_state.lpddsOffScreenBuffer.Lock( nil, ddsd, DDLOCK_WAIT, 0);
  if (ddrval <> DD_OK) then
  begin
    ri.Con_Printf(PRINT_ALL, 'failed - %s ', DDrawError(ddrval));
    DDRAW_Shutdown;
    result := False;
    Exit;
  end;
  ri.Con_Printf(PRINT_ALL, 'ok ');

  ppbuffer := @(ddsd.lpSurface);
  ppitch^ := ddsd.lPitch;

  for i := 0 to vid.height - 1 do
  begin
    Inc( ppbuffer, (i * ppitch^) );
    FillChar(ppbuffer , sizeof(ppitch), 0);

⌨️ 快捷键说明

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