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

📄 rw_imp.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): rw_Imp.h                                                          }
{                                                                            }
{ Initial conversion by : Avatar.dx(Avatar.dx@libertysurf.fr)                }
{ Initial conversion on : 23-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:                               }
{ ?                                                                          }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{ ?                                                                          }
{----------------------------------------------------------------------------}

(*
**
** RW_IMP.C
**
** This file contains ALL Win32 specific stuff having to do with the
** software refresh.  When a port is being made the following functions
** must be implemented by the port:
**
** SWimp_EndFrame
** SWimp_Init
** SWimp_SetPalette
** SWimp_Shutdown
*)

unit rw_Imp;

interface

uses
  rw_Win,
  r_Local;

procedure VID_CreateWindow(Width, Height, StyleBits : Integer);
function SWimp_Init( hInstance : Pointer; wndProc : Pointer ) : QBoolean;
function SWimp_InitGraphics(FullScreen : Boolean) : QBoolean;
procedure SWimp_EndFrame;
function SWimp_SetMode(pWidth,pHeight : PInteger; Mode : Integer; FullScreen : Boolean): rserr_t;
procedure SWimp_SetPalette(Palette : PChar);
procedure SWimp_ShutDown;
procedure SWimp_AppActivate(Active : qBoolean);
procedure Sys_MakeCodeWriteable(StartAddr, Length : Double);

// Console variables that we need to access from this module
var
  sww_state  : swwstate_t;

const
  WINDOW_CLASS_NAME = 'Quake2';
implementation

(*
** VID_CreateWindow
*)

procedure VID_CreateWindow(Width, Height, StyleBits : Integer);
var
  wc : WNDCLASS;
  r  : TRect;
  x,y,w,h : Integer;
  exStyle : Integer;
  vid_xPos, vid_yPos , vid_FullScreen : cvar_p;

Begin

  vid_xPos       := Cvar_Get('Vid_xPos', '0', 0);
  vid_yPos       := Cvar_Get('Vid_yPos', '0', 0);
  vid_FullScreen := Cvar_Get('Vid_Fullscreen','0', CVAR_ARCHIVE);

  if Assigned(vid_FullScreen.Value) then exstyle := WS_EX_TOPMOST
  else exstyle := 0;

  (* Register the frame class *)

  wc.Style         := 0;
  wc.lpfnWndProc   := sww_state.wndProc;
  wc.cbClsExtra    := 0;
  wc.cbWndExtra    := 0;
  wc.HInstance     := sww_state.Hinstance;
  wc.hIcon         := 0;
  wc.hCursor       := LoadCursor (nil,IDC_ARROW);
  wc.hbrBackground := COLOR_GRAYTEXT;
  wc.lpszMenuName  := 0;
  wc.lpszClassName := WINDOW_CLASS_NAME;

  if not RegisterClass(@wc) then ri.Sys_Error (ERR_FATAL, 'Couldn''t register window class');

  r.Left   :=0;
  r.Top    := 0;
  r.Right  := Width;
  r.Bottom := Height;

  AdjustWindowRect (@r, stylebits, FALSE);

  w := r.right - r.left;
  h := r.bottom - r.top;
  x := vid_xpos.value;
  y := vid_ypos.value;

  sww_state.hWnd := CreateWindowEx(
                                   exStyle,
                                   WINDOW_CLASS_NAME,
                                   'Quake2',
                                   stylebits,
                                   x,y,w,h,
                                   nil,
                                   nil,
                                   sww_state.hInstance,
                                   nil);

  if not Assigned(sww_state.hWnd) then ri.SysError (ERR_FATAL, 'Couldn''t create device window');

  ShowWindow( sww_state.hWnd, SW_SHOWNORMAL );
  UpdateWindow( sww_state.hWnd );
  SetForegroundWindow( sww_state.hWnd );
  SetFocus( sww_state.hWnd );

  // let the sound and input subsystems know about the new window
  ri.Vid_NewWindow (width, height);

end;

(*
** SWimp_Init
**
** This routine is responsible for initializing the implementation
** specific stuff in a software rendering subsystem.
*)

function SWimp_Init( hInstance : Pointer; wndProc : Pointer ) : QBoolean;
Begin

  sww_state.hInstance := hInstance;
  sww_state.wndProc   := wndProc;

  Result := True;

end;

(*
** SWimp_InitGraphics
**
** This initializes the software refresh's implementation specific
** graphics subsystem.  In the case of Windows it creates DIB or
** DDRAW surfaces.
**
** The necessary width and height parameters are grabbed from
** vid.width and vid.height.
*)

function SWimp_InitGraphics(FullScreen : Boolean) : QBoolean;
Begin
  // free resources in use
  SWimp_ShutDown;

  // create a new window
  VID_CreateWindow(vid.width, vid.height, WINDOW_STYLE);

  // initialize the appropriate subsystem
  if not Fullscreen then
  Begin
    if not Dib_Init(vid.Buffer, vid.rowBytes) then
    Begin

      vid.Buffer   := 0;
      vid.RowBytes := 0;

      Result := False;
      Exit;

    end;
  end
  else
  Begin
    if not DDraw_Init(vid.Buffer, vid.RowBytes) then
    Begin

      vid.Buffer   := 0;
      vid.RowBytes := 0;

      Result := False;
      Exit;

    end;
  end;

  Result := true;

end;

(*
** SWimp_EndFrame
**
** This does an implementation specific copy from the backbuffer to the
** front buffer.  In the Win32 case it uses BitBlt or BltFast depending
** on whether we're using DIB sections/GDI or DDRAW.
*)

procedure SWimp_EndFrame;
var
  r    : TRect;
  rVal : HResult;
  ddsd : DDsurfaceDesc;

Begin
  if not swState.FullScreen then
  Begin
    if ssw_state.palettized then
    Begin
//    holdpal = SelectPalette(hdcScreen, hpalDIB, FALSE);
//    RealizePalette(hdcScreen);
    end;

    BitBlt(sww_state.hDC, 0, 0,
           vid.Width, vid.Height,
           sww_state.hdcDIBSection,
           0, 0,
           SRCCOPY);

    if  sww_state.palettized then
    Begin
//    SelectPalette(hdcScreen, holdpal, FALSE);
    end;
  end
  else
  Begin

    r.Left   := 0;
    r.Top    := 0;
    r.Right  := vid.Width;
    r.Bottom := vid.Height;

    sww_state.lpddsOffScreenBuffer.lpVtbl.Unlock( sww_state.lpddsOffScreenBuffer, vid.buffer);

    if sww_State.Modex then
    Begin
      Rval := sww_state.lpddsBackBuffer.lpVtbl.BltFast(sww_state.lpddsBackBuffer, 0, 0,
						       sww_state.lpddsOffScreenBuffer,
						       @r,DDBLTFAST_WAIT);
      if RVal := DDERR_SURFACELOST then
      Begin
        sww_state.lpddsBackBuffer.lpvtbl.Restore(sww_state.lpddsBackBuffer);
        sww_state.lpddsBackBuffer.lpvtbl.BltFast(sww_state.lpddsBackBuffer,
					       0, 0, sww_state.lpddsOffScreenBuffer,
					       @r, DDBLTFAST_WAIT );
      end;
      Rval := sww_state.lpddsFrontBuffer.lpVtbl.Flip( sww_state.lpddsFrontBuffer, Nil, DDFLIP_WAIT );
      if Rval := DDERR_SURFACELOST then
      Begin
        sww_state.lpddsFrontBuffer.lpVtbl.Restore( sww_state.lpddsFrontBuffer );
        sww_state.lpddsFrontBuffer.lpVtbl.Flip( sww_state.lpddsFrontBuffer, Nil, DDFLIP_WAIT );
      end;
    end
    Else
    Begin
      rval := lpddsBackBuffer.lpVtbl.BltFast(sww_state.lpddsFrontBuffer, 0, 0,
                                             sww_state.lpddsOffScreenBuffer,
                                             @r,
                                             DDBLTFAST_WAIT);
      if rval := DDERR_SURFACELOST then
      Begin
        sww_state.lpddsBackBuffer.lpVtbl.Restore(sww_state.lpddsFrontBuffer);
        sww_state.lpddsBackBuffer.lpVtbl.BltFast(sww_state.lpddsFrontBuffer, 0, 0,
                                                 sww_state.lpddsOffScreenBuffer,
                                                 @r,
                                                 DDBLTFAST_WAIT);
      end;
    end;

    FillChar(@ddsd,SizeOf(ddsd),0);
    ddsd.dwSize := sizeOf(ddsd);

    sww_state.lpddsOffScreenBuffer.lpVtbl.Lock(sww_state.lpddsOffScreenBuffer, nil, @ddsd, DDLOCK_WAIT, nil);

    vid.Buffer   := ddsd.lpSurface;
    vid.RowBytes := ddsd.lPitch;
  end;
end;

(*
** SWimp_SetMode
*)

function SWimp_SetMode(pWidth,pHeight : PInteger; Mode : Integer; FullScreen : QBoolean): rserr_t;
const
  win_fs : array[0..1] of Pchar = ('W','FS');
var
  retVal : rserr_t;
Begin
  retval := rserr_ok

  ri.Con_Printf (PRINT_ALL, 'setting mode %d:', mode );
  if not Ri.Vid_GetModeInfo( pwidth, pheight, mode ) then
  Begin
    ri.Con_Printf( PRINT_ALL, ' invalid mode\n' );
    Result := rserr_invalid_mode;
    Exit;
  end;

  ri.Con_Printf( PRINT_ALL, ' %d %d %s\n', pwidth, pheight, win_fs[fullscreen] );

  sww_state.Initializing := true;

  if FullScreen  then
  Begin
    if not SWimp_InitGraphics = 1 then
    Begin
      if SWimp_InitGraphics = 0 then
      Begin
        // mode is legal but not as fullscreen
        fullscreen = 0;
        retval = rserr_invalid_fullscreen;
      end
      else
      Begin
        // failed to set a valid mode in windowed mode
       	retval = rserr_unknown;
      end;
    end;
  end
  else
  Begin
    // failure to set a valid mode in windowed mode
    if not SWimp_InitGraphics( fullscreen ) then
    Begin
      sww_state.initializing := true;
      result := rserr_unknown;
      exit;
    end;
  end;
  sw_state.fullscreen := fullscreen;

  R_GammaCorrectAndSetPalette(PCHAR( d_8to24table ));
  sww_state.initializing := true;

  Result := RetVal;

end;

(*
** SWimp_SetPalette
**
** System specific palette setting routine.  A NULL palette means
** to use the existing palette.  The palette is expected to be in
** a padded 4-byte xRGB format.
*)

procedure SWimp_SetPalette(Palette : PChar);
Begin
// MGL - what the fuck was kendall doing here?!
// clear screen to black and change palette
//	for (i=0 ; i<vid.height ; i++)
//		memset (vid.buffer + i*vid.rowbytes, 0, vid.width);

  if not Assigned(Palette) then Palette := PCHAR(sw_state.currentpalette);
  if not sw_state.FullScreen then DIB_SetPalette(PChar(Palette))
  Else DDraw_SetPalette(PCHAR(Palette));
end;

(*
** SWimp_Shutdown
**
** System specific graphics subsystem shutdown routine.  Destroys
** DIBs or DDRAW surfaces as appropriate.
*)

procedure SWimp_ShutDown;
Begin
  ri.Con_Printf( PRINT_ALL, "Shutting down SW imp\n" );
  DIB_Shutdown();
  DDRAW_Shutdown();

  if assigned(sww_state.hwnd) then
  Begin
    ri.Con_Printf(PRINT_ALL, '...destroying window\n' );
    ShowWindow( sww_state.hWnd, SW_SHOWNORMAL );	// prevents leaving empty slots in the taskbar
    DestroyWindow (sww_state.hWnd);
    sww_state.hWnd = nil;
    UnregisterClass (WINDOW_CLASS_NAME, sww_state.hInstance);
  end;
end;

(*
** SWimp_AppActivate
*)

procedure SWimp_AppActivate(Active : qBoolean);
Begin
  if Active then
  Begin
    if Assigned(sww_state.hwnd) then
    Begin
      SetForegroundWindow( sww_state.hWnd );
      ShowWindow( sww_state.hWnd, SW_RESTORE );
    end;
  end
  else
  Begin
    if Assigned(sww_state.hwnd) then
    Begin
      if sww_state.Initializing then Exit;
      if Assigned(vid_fullscreen.Value) then ShowWindow(sww_state.hwnd, SW_MINIMIZE);
    end;
  end;
end;

//===============================================================================


(*
================
Sys_MakeCodeWriteable
================
*)

procedure Sys_MakeCodeWriteable(StartAddr, Length : Double);
var
  flOldProtect : DWORD;
Begin
  if not(VirtualProtect(startaddr, length, PAGE_READWRITE, @flOldProtect)) then
  ri.sys_Error(ERR_FATAL, 'Protection change failed\n');

end;

(*
** Sys_SetFPCW
**
** For reference:
**
** 1
** 5               0
** xxxxRRPP.xxxxxxxx
**
** PP = 00 = 24-bit single precision
** PP = 01 = reserved
** PP = 10 = 53-bit double precision
** PP = 11 = 64-bit extended precision
**
** RR = 00 = round to nearest
** RR = 01 = round down (towards -inf, floor)
** RR = 10 = round up (towards +inf, ceil)
** RR = 11 = round to zero (truncate/towards 0)
**
*)
{$IFNDEF id386}
procedure Sys_SetFPCW;
Begin
end;
{$ELSE}
var
  fpu_ceil_cwfpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw : Word;
  fpu_sp24_cw, fpu_sp24_ceil_cw : Word;

procedure Sys_SetFPCW;
Begin
  asm
  xor eax, eax
  fnstcw  word ptr fpu_cw
  mov ax, word ptr fpu_cw

  and ah, 0f0h
  or  ah, 003h          ; round to nearest mode, extended precision
  mov fpu_full_cw, eax

  and ah, 0f0h
  or  ah, 00fh          ; RTZ/truncate/chop mode, extended precision
  mov fpu_chop_cw, eax

  and ah, 0f0h
  or  ah, 00bh          ; ceil mode, extended precision
  mov fpu_ceil_cw, eax

  and ah, 0f0h          ; round to nearest, 24-bit single precision
  mov fpu_sp24_cw, eax

  and ah, 0f0h          ; ceil mode, 24-bit single precision
  or  ah, 008h          ;
  mov fpu_sp24_ceil_cw, eax
end;
{$ENDIF}

end;



end.

⌨️ 快捷键说明

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