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

📄 dxrender.pas

📁 传奇源代码的delphi版本
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    function CreateTree_LoadColor(Color: DWORD): PDXRMachine_Tree;
    function CreateTree_LoadConstColor(R, G, B, A: Byte): PDXRMachine_Tree;
    function CreateTree_LoadTexture(Texture: DWORD): PDXRMachine_Tree;
    function CreateTree_LoadBumpTexture(Texture, BumpTexture: DWORD): PDXRMachine_Tree;
    function CreateTree_Blend(Blend: TDXR_Blend; BlendTree1, BlendTree2: PDXRMachine_Tree): PDXRMachine_Tree;
    procedure Initialize;
    procedure Compile(Tree: PDXRMachine_Tree);
    procedure Run(Count: Integer);
    property Compiled: Boolean read FCompiled write FCompiled;
  end;

const
  CPUIDF_FPU  = 1 shl 0;  {  Floating-point unit on-chip  }
  CPUIDF_VME  = 1 shl 1;  {  Virtual Mode Extension  }
  CPUIDF_DE   = 1 shl 2;  {  Debugging Extension  }
  CPUIDF_PSE  = 1 shl 3;  {  Page Size Extension  }
  CPUIDF_TSC  = 1 shl 4;  {  Time Stamp Counter  }
  CPUIDF_MSR  = 1 shl 5;  {  Mode Spacific Registers  }
  CPUIDF_PAE  = 1 shl 6;  {  Physical Address Extension  }
  CPUIDF_MCE  = 1 shl 7;  {  Machine Check Exception  }
  CPUIDF_CX8  = 1 shl 8;  {  CMPXCHG8 Instruction Supported  }
  CPUIDF_APIC = 1 shl 9;  {  On-chip APIC Hardware Supported }
  CPUIDF_MTRR = 1 shl 12; {  Memory Type Range Registers  }
  CPUIDF_PGE  = 1 shl 13; {  Page Global Enable  }
  CPUIDF_MCA  = 1 shl 14; {  Machine Check Architecture  }
  CPUIDF_CMOV = 1 shl 15; {  Conditional Move Instruction Supported  }
  CPUIDF_MMX  = 1 shl 23; {  Intel Architecture MMX Technology supported  }

var
  CPUIDVendor: array[0..11] of Char;
  CPUIDSignature: Integer;
  CPUIDFeatures: Integer;
  UseMMX: Boolean;

  RenderPrimitiveCount: Integer;

procedure ReadCPUID; 
begin
  asm
    push ebx

    pushfd
    pop eax
    mov ecx,eax
    xor eax,$200000
    push eax
    popfd
    pushfd
    pop eax
    xor eax,ecx
    jz @@exit

    mov eax,0
    db $0F,$A2                  ///cpuid
    cmp eax,1
    jl @@exit

    {  Vendor ID  }
    mov eax,0
    db $0F,$A2                  ///cpuid
    mov dword ptr [CPUIDVendor], ebx
    mov dword ptr [CPUIDVendor+4], edx
    mov dword ptr [CPUIDVendor+8], ecx

    {  Features, Signature  }
    mov eax,1
    db $0F,$A2                  ///cpuid
    mov CPUIDSignature,eax
    mov CPUIDFeatures,edx
  @@exit:
    pop ebx
  end;
  UseMMX := CPUIDFeatures and CPUIDF_MMX<>0;
end;

function dxrGetOption(Option: TDXR_Option): DWORD;
begin
  Result := 0;
  case Option of
    DXR_OPTION_VERSION:
        begin
          Result := 1*100 + 0;
        end;
    DXR_OPTION_MMXENABLE:
        begin
          Result := DWORD(LongBool(UseMMX));
        end;
    DXR_OPTION_RENDERPRIMITIVES:
        begin
          Result := RenderPrimitiveCount;
        end;
  end;
end;

procedure dxrSetOption(Option: TDXR_Option; Value: DWORD);
begin
  case Option of
    DXR_OPTION_MMXENABLE:
        begin
          UseMMX := LongBool(Value) and (CPUIDFeatures and CPUIDF_MMX<>0);
        end;
    DXR_OPTION_RENDERPRIMITIVES:
        begin
          RenderPrimitiveCount := Value;
        end;
  end;
end;

function GetBitCount(B: Integer): DWORD;
begin
  Result := 31;
  while (Result>0) and (((1 shl Result) and B)=0) do Dec(Result);
end;

function GetFirstZeroBitCount(B: Integer): DWORD;
begin
  Result := 0;
  while (Result<31) and (((1 shl Result) and B)=0) do Inc(Result);
end;

function GetOneBitCount(B: Integer): DWORD;
var
  i: Integer;
begin
  Result := 0;
  for i:=0 to 31 do
    Inc(Result, Ord(b and (1 shl i)<>0));
end;

function dxrMakeColorChannel(Mask: DWORD; indexed: Boolean): TDXR_ColorChannel;
var
  i: Integer;
begin
  Result.BitCount := GetOneBitCount(Mask shr (GetFirstZeroBitCount(Mask)));
  Result.Mask := Mask;

  if indexed then
  begin
    Result.rshift := GetFirstZeroBitCount(Mask);
    Result.lshift := 0;
  end else
  begin
    i :=  GetFirstZeroBitCount(Mask)-(8-Result.BitCount);

    if i<0 then
    begin
      Result.lshift := -i;
      Result.rshift := 0;
    end else
    begin
      Result.lshift := 0;
      Result.rshift := DWORD(i);
    end;
  end;
end;

procedure dxrMakeIndexedSurface(var Surface: TDXR_Surface; Width, Height, BitCount: DWORD;
  Bits: Pointer; pitch: Integer; idx_index, idx_alpha: DWORD);
begin
  FillChar(Surface, SizeOf(Surface), 0);

  Surface.ColorType := DXR_COLORTYPE_INDEXED;
  Surface.Width := Width;
  Surface.Height := Height;
  Surface.WidthBit := GetBitCount(Width);
  Surface.HeightBit := GetBitCount(Height);
  Surface.Width2 := 1 shl Surface.WidthBit;
  Surface.Height2 := 1 shl Surface.HeightBit;
  Surface.WidthMask := Surface.Width-1;
  Surface.HeightMask := Surface.Height2-1;

  Surface.BitCount := BitCount;
  Surface.Bits := Bits;
  Surface.Pitch := Pitch;
  Surface.PitchBit := GetBitCount(Abs(Pitch));

  Surface.idx_index := dxrMakeColorChannel(idx_index, True);
  Surface.idx_alpha := dxrMakeColorChannel(idx_alpha, False);
end;

procedure dxrMakeRGBSurface(var Surface: TDXR_Surface; Width, Height, BitCount: DWORD;
  Bits: Pointer; pitch: Integer; rgb_red, rgb_green, rgb_blue, rgb_alpha: DWORD);
begin
  FillChar(Surface, SizeOf(Surface), 0);

  Surface.ColorType := DXR_COLORTYPE_RGB;
  Surface.Width := Width;
  Surface.Height := Height;
  Surface.WidthBit := GetBitCount(Width);
  Surface.HeightBit := GetBitCount(Height);
  Surface.Width2 := 1 shl Surface.WidthBit;
  Surface.Height2 := 1 shl Surface.HeightBit;
  Surface.WidthMask := Surface.Width-1;
  Surface.HeightMask := Surface.Height2-1;

  Surface.BitCount := BitCount;
  Surface.Bits := Bits;
  Surface.Pitch := Pitch;
  Surface.PitchBit := GetBitCount(Abs(Pitch));

  Surface.rgb_red := dxrMakeColorChannel(rgb_red, False);
  Surface.rgb_green := dxrMakeColorChannel(rgb_green, False);
  Surface.rgb_blue := dxrMakeColorChannel(rgb_blue, False);
  Surface.rgb_alpha := dxrMakeColorChannel(rgb_alpha, False);
end;

function dxrCompareSurface(const Surface1, Surface2: TDXR_Surface): Boolean;
begin
  if Surface1.ColorType=DXR_COLORTYPE_INDEXED then
  begin
    Result := (Surface2.ColorType=DXR_COLORTYPE_INDEXED) and
      (Surface1.idx_index.Mask=Surface2.idx_index.Mask) and
      (Surface1.idx_alpha.Mask=Surface2.idx_alpha.Mask);
  end else if Surface1.ColorType=DXR_COLORTYPE_RGB then
  begin
    Result := (Surface2.ColorType=DXR_COLORTYPE_RGB) and
      (Surface1.rgb_red.Mask=Surface2.rgb_red.Mask) and
      (Surface1.rgb_green.Mask=Surface2.rgb_green.Mask) and
      (Surface1.rgb_blue.Mask=Surface2.rgb_blue.Mask) and
      (Surface1.rgb_alpha.Mask=Surface2.rgb_alpha.Mask);
  end else
    Result := False;
end;

function dxrDDSurfaceLock(DDSurface: IDirectDrawSurface; var Surface: TDXR_Surface): Boolean;
var
  ddsd: TDDSurfaceDesc;
begin
  Result := dxrDDSurfaceLock2(DDSurface, ddsd, Surface);
end;

function dxrDDSurfaceLock2(DDSurface: IDirectDrawSurface; var ddsd: TDDSurfaceDesc;
  var Surface: TDXR_Surface): Boolean;
const
  DDPF_PALETTEINDEXED = DDPF_PALETTEINDEXED1 or DDPF_PALETTEINDEXED2 or
    DDPF_PALETTEINDEXED4 or DDPF_PALETTEINDEXED8;
begin
  ddsd.dwSize := SizeOf(ddsd);
  Result := DDSurface.Lock(nil, ddsd, DDLOCK_WAIT, 0)=DD_OK;
  if Result then
  begin
    FillChar(Surface, SizeOf(Surface), 0);
    if ddsd.ddpfPixelFormat.dwFlags and DDPF_PALETTEINDEXED<>0 then
    begin
      dxrMakeIndexedSurface(Surface, ddsd.dwWidth, ddsd.dwHeight, ddsd.ddpfPixelFormat.dwRGBBitCount,
        ddsd.lpSurface, ddsd.lPitch, (1 shl ddsd.ddpfPixelFormat.dwRGBBitCount)-1, 0);
    end else
    begin
      if ddsd.ddpfPixelFormat.dwFlags and DDPF_ALPHAPIXELS<>0 then
      begin
        dxrMakeRGBSurface(Surface, ddsd.dwWidth, ddsd.dwHeight, ddsd.ddpfPixelFormat.dwRGBBitCount,
          ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRBitMask, ddsd.ddpfPixelFormat.dwGBitMask,
          ddsd.ddpfPixelFormat.dwBBitMask, ddsd.ddpfPixelFormat.dwRGBAlphaBitMask);
      end else
      begin
        dxrMakeRGBSurface(Surface, ddsd.dwWidth, ddsd.dwHeight, ddsd.ddpfPixelFormat.dwRGBBitCount,
          ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRBitMask, ddsd.ddpfPixelFormat.dwGBitMask,
          ddsd.ddpfPixelFormat.dwBBitMask, 0);
      end;                          
    end;
  end;
end;

procedure dxrDDSurfaceUnLock(DDSurface: IDirectDrawSurface; const Surface: TDXR_Surface);
begin
  DDSurface.Unlock(Surface.Bits);
end;

function dxrScanLine(const Surface: TDXR_Surface; y: DWORD): Pointer;
begin
  Result := Pointer(Integer(Surface.Bits)+Surface.Pitch*Integer(y));
end;

procedure dxrZBufferClear(const Surface: TDXR_Surface);
var
  i: Integer;
begin
  for i:=0 to Surface.Height-1 do
    FillChar(dxrScanLine(Surface, i)^, Abs(Surface.Pitch), $FF);
end;

{  TDXRMachine  }

constructor TDXRMachine.Create;
begin
  inherited Create;
  FBuf := VirtualAlloc(nil, 2048, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
end;

destructor TDXRMachine.Destroy;
begin
  VirtualFree(FBuf, 0, MEM_RELEASE);
  inherited Destroy;
end;

procedure TDXRMachine.Initialize;
begin
  FCall := nil;
  ColorIndexCount := 0;
  TextureIndexCount := 0;

  FTreeCount := 0;

  Dest := nil;
  FCompiled := False;
  FMMXUsed := False;

  FillChar(ColorList, SizeOf(ColorList), 0);
  FillChar(TextureList, SizeOf(TextureList), 0);
  FillChar(Dither, SizeOf(Dither), 0);
  FillChar(ZBuffer, SizeOf(ZBuffer), 0);
  FillChar(Axis, SizeOf(Axis), 0);
  FillChar(RHW, SizeOf(RHW), 0);
end;

function TDXRMachine.CreateTree: PDXRMachine_Tree;
begin
  Result := @FTreeList[FTreeCount];
  FillChar(Result^, SizeOf(Result^), 0);
  Inc(FTreeCount);
end;

function TDXRMachine.CreateTree2(Typ: TDXRMachine_TreeType): PDXRMachine_Tree;
begin
  Result := CreateTree;
  Result.Typ := Typ;
end;

function TDXRMachine.CreateTree_LoadColor(Color: DWORD): PDXRMachine_Tree;
begin
  Result := CreateTree;
  Result.Typ := DXR_TREETYPE_LOADCOLOR;
  Result.Color := Color;
end;

function TDXRMachine.CreateTree_LoadConstColor(R, G, B, A: Byte): PDXRMachine_Tree;
begin
  Result := CreateTree;
  Result.Typ := DXR_TREETYPE_LOADCONSTCOLOR;
  Result.ConstColor.R := R shl 8;
  Result.ConstColor.G := G shl 8;
  Result.ConstColor.B := B shl 8;
  Result.ConstColor.A := A shl 8;
end;

function TDXRMachine.CreateTree_LoadTexture(Texture: DWORD): PDXRMachine_Tree;
begin
  Result := CreateTree;
  Result.Typ := DXR_TREETYPE_LOADTEXTURE;
  Result.Texture := Texture;
end;

function TDXRMachine.CreateTree_LoadBumpTexture(Texture, BumpTexture: DWORD): PDXRMachine_Tree;
begin
  Result := CreateTree;
  Result.Typ := DXR_TREETYPE_LOADBUMPTEXTURE;
  Result.Texture := Texture;
  Result.BumpTexture := BumpTexture;
end;

function TDXRMachine.CreateTree_Blend(Blend: TDXR_Blend; BlendTree1, BlendTree2: PDXRMachine_Tree): PDXRMachine_Tree;
begin
  Result := CreateTree;
  Result.Typ := DXR_TREETYPE_BLEND;
  Result.Blend := Blend;
  Result.BlendTree1 := BlendTree1;
  Result.BlendTree2 := BlendTree2;
end;

procedure TDXRMachine.Compile;

  function GetSurfaceChannels(const Surface: TDXR_Surface): TDXRColorChannels;
  begin
    Result := [];

    if Surface.ColorType=DXR_COLORTYPE_INDEXED then
    begin
      if Surface.idx_index.Mask<>0 then Result := Result + [chRed, chGreen, chBlue];
      if Surface.idx_alpha.Mask<>0 then Result := Result + [chAlpha];
    end else
    begin
      if Surface.rgb_red.Mask<>0 then Result := Result + [chRed];
      if Surface.rgb_green.Mask<>0 then Result := Result + [chGreen];
      if Surface.rgb_blue.Mask<>0 then Result := Result + [chBlue];
      if Surface.rgb_alpha.Mask<>0 then Result := Result + [chAlpha];
    end;
  end;

  procedure OptimizeTree(var Tree: PDXRMachine_Tree);

    procedure GetBlendChannels(Blend: TDXR_Blend; var Col1_1, Col1_2, Col2_1, Col2_2: TDXRColorChannels);
    begin
      case Blend of
        DXR_BLEND_ZERO:
          begin
            Col1_1 := [];
            Col1_2 := [];
            Col2_1 := [];
            Col2_2 := [];
          end;
        DXR_BLEND_ONE1:
          begin
            Col1_1 := [chRed, chGreen, chBlue, chAlpha];
            Col1_2 := [];
            Col2_1 := [];
            Col2_2 := [];
          end;
        DXR_BLEND_ONE2:
          begin
            Col1_1 := [];
            Col1_2 := [];
            Col2_1 := [chRed, chGreen, chBlue, chAlpha];
            Col2_2 := [];
          end;
        DXR_BLEND_ONE1_ADD_ONE2, DXR_BLEND_ONE1_SUB_ONE2:
          begin
            Col1_1 := [chRed, chGreen, chBlue, chAlpha];
            Col1_2 := [];
            Col2_1 := [chRed, chGreen, chBlue, chAlpha];
            Col2_2 := [];
          end;
        DXR_BLEND_ONE2_SUB_ONE1, DXR_BLEND_ONE1_MUL_ONE2:
          begin
            Col1_1 := [chRed, chGreen, chBlue, chAlpha];
            Col1_2 := [];
            Col2_1 := [chRed, chGreen, chBlue, chAlpha];
            Col2_2 := [];

⌨️ 快捷键说明

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