www.pudn.com > MirGame.zip > cliUtil.pas


unit cliUtil; 
 
//工具库:主要提供一些图形操作函数 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  DXDraws, DXClass, WIL, {Grobal2,} StdCtrls, DirectX, DIB, HUtil32, 
  wmutil; //, bmputil; 
 
 
const 
   MAXGRADE = 64; 
   DIVUNIT = 4; 
 
 
type 
  TColorEffect = (ceNone, ceGrayScale, ceBright, ceBlack, ceWhite, ceRed, ceGreen, ceBlue, ceYellow, ceFuchsia); 
 
  TNearestIndexHeader = record 
    Title: string[30]; 
    IndexCount: integer; 
    desc: array[0..10] of byte; 
  end; 
 
function  HasMMX: Boolean; 
procedure BuildColorLevels (ctable: TRGBQuads); 
procedure BuildNearestIndex (ctable: TRGBQuads); 
procedure SaveNearestIndex (flname: string); 
function  LoadNearestIndex (flname: string): Boolean; 
procedure DrawFog (ssuf: TDirectDrawSurface; fogmask: PByte; fogwidth: integer); 
procedure DrawFog2 (ssuf: TDirectDrawSurface; fogmask: PByte; fogwidth: integer); 
procedure MakeDark (ssuf: TDirectDrawSurface; darklevel: integer); 
procedure FogCopy (PSource: Pbyte; ssx, ssy, swidth, sheight: integer; 
                   PDest: Pbyte; ddx, ddy, dwidth, dheight, maxfog: integer); 
procedure DrawBlend (dsuf: TDirectDrawSurface; x, y: integer; ssuf: TDirectDrawSurface; blendmode: integer); 
procedure DrawBlendEx (dsuf: TDirectDrawSurface; x, y: integer; ssuf: TDirectDrawSurface; ssufleft, ssuftop, ssufwidth, ssufheight, blendmode: integer); 
procedure SpriteCopy(DestX, DestY : integer; 
                       SourX, SourY : integer; 
                       Size         : TPoint; 
                       Sour, Dest   : TDirectDrawSurface); 
procedure MMXBlt (ssuf, dsuf: TDirectDrawSurface); 
procedure DrawEffect (x, y, width, height: integer; ssuf: TDirectDrawSurface; eff: TColorEffect); 
 
var 
   DarkLevel : integer; 
 
 
implementation 
 
var 
  RgbIndexTable: array[0..MAXGRADE-1, 0..MAXGRADE-1, 0..MAXGRADE-1] of byte; 
  Color256Mix: array[0..255, 0..255] of byte; 
  Color256Anti: array[0..255, 0..255] of byte; 
  HeavyDarkColorLevel: array[0..255, 0..255] of byte; 
  LightDarkColorLevel: array[0..255, 0..255] of byte; 
  DengunColorLevel: array[0..255, 0..255] of byte; 
  BrightColorLevel: array[0..255] of byte; 
  GrayScaleLevel: array[0..255] of byte; 
  RedishColorLevel: array[0..255] of byte; 
  BlackColorLevel: array[0..255] of byte; 
  WhiteColorLevel: array[0..255] of byte; 
  GreenColorLevel: array[0..255] of byte; 
  YellowColorLevel: array[0..255] of byte; 
  BlueColorLevel: array[0..255] of byte; 
  FuchsiaColorLevel: array[0..255] of byte; 
 
//判断机器是否有MMX功能 
function  HasMMX: Boolean; 
var 
   n: byte; 
begin 
   asm 
      mov   eax, 1 
      db $0F,$A2               /// CPUID 
      test  edx, 00800000H 
      mov   n, 1 
      jnz   @@Found 
      mov   n, 0 
   @@Found: 
   end; 
   if n = 1 then Result := TRUE 
   else Result := FALSE; 
end; 
 
procedure BuildNearestIndex (ctable: TRGBQuads); 
var 
   r, g, b, rr, gg, bb, color, MinDif, ColDif: Integer; 
   MatchColor: Byte; 
   pal0, pal1, pal2: TRGBQuad; 
 
   //调色板混合256X256 
   procedure BuildMix; 
   var 
      i, j, n: integer; 
   begin 
      for i:=0 to 255 do begin 
         pal0 := ctable[i]; 
         for j:=0 to 255 do begin 
            pal1 := ctable[j]; 
            pal1.rgbRed := pal0.rgbRed div 2 + pal1.rgbRed div 2; 
            pal1.rgbGreen := pal0.rgbGreen div 2 + pal1.rgbGreen div 2; 
            pal1.rgbBlue := pal0.rgbBlue div 2 + pal1.rgbBlue div 2; 
            MinDif := 768; 
            MatchColor := 0; 
            for n:=0 to 255 do begin 
               pal2 := ctable[n]; 
               ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                         Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                         Abs(pal2.rgbBlue - pal1.rgbBlue); 
               if ColDif < MinDif then begin 
                  MinDif := ColDif; 
                  MatchColor := n; 
               end; 
            end; 
            Color256Mix[i, j] := MatchColor; 
         end; 
      end; 
   end; 
   //调色板动画颜色表256X256 
   procedure BuildAnti; 
   var 
      i, j, n, ever: integer; 
   begin 
      for i:=0 to 255 do begin 
         pal0 := ctable[i]; 
         for j:=0 to 255 do begin 
            pal1 := ctable[j]; 
            ever := _MAX(pal0.rgbRed, pal0.rgbGreen); 
            ever := _MAX(ever, pal0.rgbBlue); 
            pal1.rgbRed := _MIN(255, Round (pal0.rgbRed  + (255-pal0.rgbRed)/255 * pal1.rgbRed)); 
            pal1.rgbGreen := _MIN(255, Round (pal0.rgbGreen  + (255-pal0.rgbGreen)/255 * pal1.rgbGreen)); 
            pal1.rgbBlue := _MIN(255, Round (pal0.rgbBlue  + (255-pal0.rgbBlue)/255 * pal1.rgbBlue)); 
            MinDif := 768; 
            MatchColor := 0; 
            for n:=0 to 255 do begin 
               pal2 := ctable[n]; 
               ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                         Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                         Abs(pal2.rgbBlue - pal1.rgbBlue); 
               if ColDif < MinDif then begin 
                  MinDif := ColDif; 
                  MatchColor := n; 
               end; 
            end; 
            Color256Anti[i, j] := MatchColor; 
         end; 
      end; 
   end; 
   //灰阶颜色表256X256 
   procedure BuildColorLevels; 
   var 
      n, i, j, rr, gg, bb: integer; 
   begin 
      for n:=0 to 30 do begin 
         for i:=0 to 255 do begin 
            pal1 := ctable[i]; 
            rr := _MIN(Round(pal1.rgbRed * (n+1) / 31) - 5, 255);      //(n + (n-1)*3) / 121); 
            gg := _MIN(Round(pal1.rgbGreen * (n+1) / 31) - 5, 255);  //(n + (n-1)*3) / 121); 
            bb := _MIN(Round(pal1.rgbBlue * (n+1) / 31) - 5, 255);    //(n + (n-1)*3) / 121); 
            pal1.rgbRed := _MAX(0, rr); 
            pal1.rgbGreen := _MAX(0, gg); 
            pal1.rgbBlue := _MAX(0, bb); 
            MinDif := 768; 
            MatchColor := 0; 
            for j:=0 to 255 do begin 
               pal2 := ctable[j]; 
               ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                         Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                         Abs(pal2.rgbBlue - pal1.rgbBlue); 
               if ColDif < MinDif then begin 
                  MinDif := ColDif; 
                  MatchColor := j; 
               end; 
            end; 
            HeavyDarkColorLevel[n, i] := MatchColor; 
         end; 
      end; 
      for n:=0 to 30 do begin 
         for i:=0 to 255 do begin 
            pal1 := ctable[i]; 
            pal1.rgbRed := _MIN(Round(pal1.rgbRed * (n*3+47) / 140), 255); 
            pal1.rgbGreen := _MIN(Round(pal1.rgbGreen * (n*3+47) / 140), 255); 
            pal1.rgbBlue := _MIN(Round(pal1.rgbBlue * (n*3+47) / 140), 255); 
            MinDif := 768; 
            MatchColor := 0; 
            for j:=0 to 255 do begin 
               pal2 := ctable[j]; 
               ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                         Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                         Abs(pal2.rgbBlue - pal1.rgbBlue); 
               if ColDif < MinDif then begin 
                  MinDif := ColDif; 
                  MatchColor := j; 
               end; 
            end; 
            LightDarkColorLevel[n, i] := MatchColor; 
         end; 
      end; 
      for n:=0 to 30 do begin 
         for i:=0 to 255 do begin 
            pal1 := ctable[i]; 
            pal1.rgbRed := _MIN(Round(pal1.rgbRed * (n*3+120) / 214), 255); 
            pal1.rgbGreen := _MIN(Round(pal1.rgbGreen * (n*3+120) / 214), 255); 
            pal1.rgbBlue := _MIN(Round(pal1.rgbBlue * (n*3+120) / 214), 255); 
            MinDif := 768; 
            MatchColor := 0; 
            for j:=0 to 255 do begin 
               pal2 := ctable[j]; 
               ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                         Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                         Abs(pal2.rgbBlue - pal1.rgbBlue); 
               if ColDif < MinDif then begin 
                  MinDif := ColDif; 
                  MatchColor := j; 
               end; 
            end; 
            DengunColorLevel[n, i] := MatchColor; 
         end; 
      end; 
 
      for n:=31 to 255 do 
         for i:=0 to 255 do begin 
            HeavyDarkColorLevel[n, i] := HeavyDarkColorLevel[30, i]; 
            LightDarkColorLevel[n, i] := LightDarkColorLevel[30, i]; 
            DengunColorLevel[n, i] := DengunColorLevel[30, i]; 
         end; 
   end; 
begin 
   BuildMix; 
   BuildAnti; 
   BuildColorLevels; 
end; 
 
procedure BuildColorLevels (ctable: TRGBQuads); 
var 
   n, i, j, MinDif, ColDif: integer; 
   pal1, pal2: TRGBQuad; 
   MatchColor: byte; 
begin 
   BrightColorLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      pal1.rgbRed := _MIN(Round(pal1.rgbRed * 1.3), 255); 
      pal1.rgbGreen := _MIN(Round(pal1.rgbGreen * 1.3), 255); 
      pal1.rgbBlue := _MIN(Round(pal1.rgbBlue * 1.3), 255); 
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      BrightColorLevel[i] := MatchColor; 
   end; 
   GrayScaleLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      n := (pal1.rgbRed + pal1.rgbGreen + pal1.rgbBlue) div 3; 
      pal1.rgbRed := n; //Round(pal1.rgbRed * (n*3+25) / 118); 
      pal1.rgbGreen := n; //Round(pal1.rgbGreen * (n*3+25) / 118); 
      pal1.rgbBlue := n; //Round(pal1.rgbBlue * (n*3+25) / 118); 
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      GrayScaleLevel[i] := MatchColor; 
   end; 
   BlackColorLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      n := Round ((pal1.rgbRed + pal1.rgbGreen + pal1.rgbBlue) / 3 * 0.6); 
      pal1.rgbRed := n; //_MAX(8, Round(pal1.rgbRed * 0.7)); 
      pal1.rgbGreen := n; //_MAX(8, Round(pal1.rgbGreen * 0.7)); 
      pal1.rgbBlue := n; //_MAX(8, Round(pal1.rgbBlue * 0.7)); 
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      BlackColorLevel[i] := MatchColor; 
   end; 
   WhiteColorLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      n := _MIN (Round ((pal1.rgbRed + pal1.rgbGreen + pal1.rgbBlue) / 3 * 1.6), 255); 
      pal1.rgbRed := n; //_MAX(8, Round(pal1.rgbRed * 0.7)); 
      pal1.rgbGreen := n; //_MAX(8, Round(pal1.rgbGreen * 0.7)); 
      pal1.rgbBlue := n; //_MAX(8, Round(pal1.rgbBlue * 0.7)); 
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      WhiteColorLevel[i] := MatchColor; 
   end; 
   RedishColorLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      n := (pal1.rgbRed + pal1.rgbGreen + pal1.rgbBlue) div 3; 
      pal1.rgbRed := n; 
      pal1.rgbGreen := 0; 
      pal1.rgbBlue := 0; 
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      RedishColorLevel[i] := MatchColor; 
   end; 
   GreenColorLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      n := (pal1.rgbRed + pal1.rgbGreen + pal1.rgbBlue) div 3; 
      pal1.rgbRed := 0; 
      pal1.rgbGreen := n; 
      pal1.rgbBlue := 0; 
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      GreenColorLevel[i] := MatchColor; 
   end; 
   YellowColorLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      n := (pal1.rgbRed + pal1.rgbGreen + pal1.rgbBlue) div 3; 
      pal1.rgbRed := n; 
      pal1.rgbGreen := n; 
      pal1.rgbBlue := 0; 
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      YellowColorLevel[i] := MatchColor; 
   end; 
   BlueColorLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      n := (pal1.rgbRed + pal1.rgbGreen + pal1.rgbBlue) div 3; 
      pal1.rgbRed := 0; 
      pal1.rgbGreen := 0; 
      pal1.rgbBlue := n;  
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      BlueColorLevel[i] := MatchColor; 
   end; 
   FuchsiaColorLevel[0] := 0; 
   for i:=1 to 255 do begin 
      pal1 := ctable[i]; 
      n := (pal1.rgbRed + pal1.rgbGreen + pal1.rgbBlue) div 3; 
      pal1.rgbRed := n; 
      pal1.rgbGreen := 0; 
      pal1.rgbBlue := n; 
      MinDif := 768; 
      MatchColor := 0; 
      for j:=1 to 255 do begin 
         pal2 := ctable[j]; 
         ColDif := Abs(pal2.rgbRed - pal1.rgbRed) + 
                   Abs(pal2.rgbGreen - pal1.rgbGreen) + 
                   Abs(pal2.rgbBlue - pal1.rgbBlue); 
         if ColDif < MinDif then begin 
            MinDif := ColDif; 
            MatchColor := j; 
         end; 
      end; 
      FuchsiaColorLevel[i] := MatchColor; 
   end; 
end; 
 
//保存几个颜色表到文件 
procedure SaveNearestIndex (flname: string); 
var 
   nih: TNearestIndexHeader; 
   fhandle: integer; 
begin 
   nih.Title := 'WEMADE Entertainment Inc.'; 
   nih.IndexCount := Sizeof(Color256Mix);   //65536 
   if FileExists (flname) then begin 
      fhandle := FileOpen (flname, fmOpenWrite or fmShareDenyNone); 
   end else 
      fhandle := FileCreate (flname); 
   if fhandle > 0 then begin 
      FileWrite (fhandle, nih, sizeof(TNearestIndexHeader)); 
      FileWrite (fhandle, Color256Mix, sizeof(Color256Mix)); 
      FileWrite (fhandle, Color256Anti, sizeof(Color256Anti)); 
      FileWrite (fhandle, HeavyDarkColorLevel, sizeof(HeavyDarkColorLevel)); 
      FileWrite (fhandle, LightDarkColorLevel, sizeof(LightDarkColorLevel)); 
      FileWrite (fhandle, DengunColorLevel, sizeof(DengunColorLevel)); 
      FileClose (fhandle); 
   end; 
end; 
 
//从文件中读取几个颜色表 
function LoadNearestIndex (flname: string): Boolean; 
var 
   nih: TNearestIndexHeader; 
   fhandle, rsize: integer; 
begin 
   Result := FALSE; 
   if FileExists (flname) then begin 
      fhandle := FileOpen (flname, fmOpenRead or fmShareDenyNone); 
      if fhandle > 0 then begin 
         FileRead (fhandle, nih, sizeof(TNearestIndexHeader)); 
         if nih.IndexCount = Sizeof(Color256Mix) then begin 
            Result := TRUE; 
            rsize := 256*256; 
            if rsize <> FileRead (fhandle, Color256Mix, sizeof(Color256Mix)) then Result := FALSE; 
            if rsize <> FileRead (fhandle, Color256Anti, sizeof(Color256Anti)) then Result := FALSE; 
            if rsize <> FileRead (fhandle, HeavyDarkColorLevel, sizeof(HeavyDarkColorLevel)) then Result := FALSE; 
            if rsize <> FileRead (fhandle, LightDarkColorLevel, sizeof(LightDarkColorLevel)) then Result := FALSE; 
            if rsize <> FileRead (fhandle, DengunColorLevel, sizeof(DengunColorLevel)) then Result := FALSE; 
         end; 
         FileClose (fhandle); 
      end; 
   end; 
end; 
 
//生成雾的效果 
procedure FogCopy (PSource: Pbyte; ssx, ssy, swidth, sheight: integer; 
                   PDest: Pbyte; ddx, ddy, dwidth, dheight, maxfog: integer); 
var 
   i, j, n, k, row, srclen, scount, si, di, srcheight, spitch, dpitch: integer; 
   sptr, dptr: PByte; 
begin 
   if (PSource = nil) or (pDest = nil) then exit;  
   spitch := swidth; 
   dpitch := dwidth; 
   if ddx < 0 then begin 
      ssx := ssx - ddx; 
      swidth := swidth + ddx; 
      //dwidth := dwidth + ddx; 
      ddx := 0; 
   end; 
   if ddy < 0 then begin 
      ssy := ssy - ddy; 
      sheight := sheight + ddy; 
      //dheight := dheight + ddy; 
      ddy := 0; 
   end; 
   //if ssx+swidth > dwidth then swidth := dwidth - ssx; 
   //if ssy+sheight > dheight then sheight := dheight - ssy; 
   srclen := _MIN(swidth, dwidth-ddx); 
   srcheight := _MIN(sheight, dheight-ddy); 
   if (srclen <= 0) or (srcheight <= 0) then exit; 
 
   asm 
         mov   row, 0 
      @@NextRow: 
         mov   eax, row 
         cmp   eax, srcheight 
         jae   @@Finish 
 
         mov   esi, psource 
         mov   eax, ssy 
         add   eax, row 
         mov   ebx, spitch 
         imul  eax, ebx 
         add   eax, ssx 
         add   esi, eax          //sptr 
 
         mov   edi, pdest 
         mov   eax, ddy 
         add   eax, row 
         mov   ebx, dpitch 
         imul  eax, ebx 
         add   eax, ddx 
         add   edi, eax          //dptr 
 
         mov   ebx, srclen 
      @@FogNext: 
         cmp   ebx, 0 
         jbe   @@FinOne 
         cmp   ebx, 8 
         jb    @@FinOne   //@@EageNext 
 
         db $0F,$6F,$06           /// movq  mm0, [esi] 
         db $0F,$6F,$0F           /// movq  mm1, [edi] 
         db $0F,$FE,$C8           /// paddd mm1, mm0 
         db $0F,$7F,$0F           /// movq [edi], mm1 
 
         sub   ebx, 8 
         add   esi, 8 
         add   edi, 8 
         jmp   @@FogNext 
      {@@EageNext: 
         movzx eax, [esi].byte 
         movzx ecx, [edi].byte 
         add   eax, ecx 
         mov   [edi].byte, al 
 
         dec   ebx 
         inc   esi 
         inc   edi 
         jmp   @@FogNext } 
      @@FinOne: 
         inc   row 
         jmp   @@NextRow 
 
      @@Finish: 
         db $0F,$77               /// emms 
   end; 
end; 
 
//显示雾效果 
procedure DrawFog (ssuf: TDirectDrawSurface; fogmask: PByte; fogwidth: integer); 
var 
   i, j, idx, row, n, count: integer; 
   ddsd: DDSURFACEDESC; 
   sptr, mptr, pmix: PByte; 
   //source: array[0..910] of byte; 
   bitindex, scount, dcount, srclen, destlen, srcheight: integer; 
   lpitch: integer; 
   src, msk: array[0..7] of byte; 
   pSrc, psource, pColorLevel: Pbyte; 
begin 
   if ssuf.Width > 900 then exit; 
   case DarkLevel of 
      1: pColorLevel := @HeavyDarkColorLevel;  //深夜 
      2: pColorLevel := @LightDarkColorLevel;  //中等亮度 
      3: pColorLevel := @DengunColorLevel;     //中午 
      else exit; 
   end; 
   try 
      ddsd.dwSize := SizeOf(ddsd); 
      ssuf.Lock (TRect(nil^), ddsd); 
      srclen := _MIN(ssuf.Width, fogwidth); 
      pSrc := @src; 
      srcheight := ssuf.Height; 
      lpitch := ddsd.lPitch; 
      psource := ddsd.lpSurface; 
 
      asm 
            mov   row, 0 
         @@NextRow: 
            mov   ebx, row 
            mov   eax, srcheight 
            cmp   ebx, eax 
            jae   @@DrawFogFin 
 
            mov   esi, psource      //esi = ddsd.lpSurface; 
            mov   eax, lpitch 
            mov   ebx, row 
            imul  eax, ebx 
            add   esi, eax 
 
            mov   edi, fogmask      //edi = fogmask 
            mov   eax, fogwidth 
            mov   ebx, row 
            imul  eax, ebx 
            add   edi, eax 
 
            mov   ecx, srclen 
            mov   edx, pColorLevel 
 
         @@NextByte: 
            cmp   ecx, 0 
            jbe   @@Finish 
 
            movzx eax, [edi].byte   //fogmask 
            ///cmp   eax, 30 
            ///ja    @@SkipByte 
            imul  eax, 256 
            movzx ebx, [esi].byte   //家胶 ddsd.lpSurface; 
            add   eax, ebx 
            mov   al, [edx+eax].byte //pColorLevel 
            mov   [esi].byte, al 
         ///@@SkipByte: 
            dec   ecx 
            inc   esi 
            inc   edi 
            jmp   @@NextByte 
 
         @@Finish: 
            inc   row 
            jmp   @@NextRow 
 
         @@DrawFogFin: 
            db $0F,$77               /// emms 
      end; 
   finally 
      ssuf.UnLock (); 
   end; 
end; 
 
procedure DrawFog2 (ssuf: TDirectDrawSurface; fogmask: PByte; fogwidth: integer); 
var 
   i, j, n, scount, srclen, offsvalue: integer; 
   sddsd: DDSURFACEDESC; 
   sptr, fptr, pColorLevel: Pbyte; 
   source: array[0..810] of byte; 
begin 
   if ssuf.Width > 800 then exit; 
   try 
      sddsd.dwSize := SizeOf(sddsd); 
      ssuf.Lock (TRect(nil^), sddsd); 
      srclen := _MIN(ssuf.Width, fogwidth); 
      case DarkLevel of 
         0: pColorLevel := @HeavyDarkColorLevel; 
         1: pColorLevel := @LightDarkColorLevel; 
         2: pColorLevel := @DengunColorLevel; 
      end; 
      for i:=0 to ssuf.height-1 do begin 
         sptr := PBYTE(integer(sddsd.lpSurface) + i*sddsd.lPitch); 
         fptr := PBYTE(integer(fogmask) + i*fogwidth); 
         asm 
               mov   scount, 0 
               mov   esi, sptr 
               lea   edi, source 
            @@CopySource: 
               mov   ebx, scount        //ebx = scount 
               cmp   ebx, srclen 
               jae   @@EndSourceCopy 
               db $0F,$6F,$04,$1E       /// movq  mm0, [esi+ebx] 
               db $0F,$7F,$07           /// movq  [edi], mm0 
 
               xor   ebx, ebx 
            @@Loop8: 
               cmp   ebx, 8 
               jz    @@EndLoop8 
               mov   ecx, fptr 
               add   ecx, scount 
               add   ecx, ebx 
               movzx eax, [ecx].byte 
               cmp   eax, 30 
               jae   @@Skip 
               imul  eax, 256 
               mov   ecx, eax 
 
 
               movzx eax, [edi+ebx].byte 
               mov   edx, pColorLevel 
               add   edx, ecx 
               movzx eax, [edx+eax].byte     // 
               mov   [edi+ebx], al 
            @@Skip: 
               inc   ebx 
               jmp   @@Loop8 
            @@EndLoop8: 
 
               mov   ebx, scount 
               db $0F,$6F,$07           /// movq  mm0, [edi] 
               db $0F,$7F,$04,$1E       /// movq  [esi+ebx], mm0 
 
               add   edi, 8 
               add   scount, 8 
               jmp   @@CopySource 
            @@EndSourceCopy: 
               db $0F,$77               /// emms 
 
         end; 
      end; 
   finally 
      ssuf.UnLock (); 
   end; 
end; 
 
 
procedure MakeDark (ssuf: TDirectDrawSurface; darklevel: integer); 
var 
   i, j, idx, row, n, count: integer; 
   ddsd: DDSURFACEDESC; 
   sptr, mptr, pmix: PByte; 
   //source: array[0..910] of byte; 
   bitindex, scount, dcount, srclen, destlen, srcheight: integer; 
   lpitch: integer; 
   src, msk: array[0..7] of byte; 
   pSrc, psource, pColorLevel: Pbyte; 
begin 
   if not darklevel in [1..30] then exit; 
   if ssuf.Width > 900 then exit; 
   try 
      ddsd.dwSize := SizeOf(ddsd); 
      ssuf.Lock (TRect(nil^), ddsd); 
      srclen := ssuf.Width; 
      srcheight := ssuf.Height; 
      pSrc := @src; 
      //if HeavyDark then pColorLevel := @HeavyDarkColorLevel 
      //else pColorLevel := @LightDarkColorLevel; 
      pColorLevel := @HeavyDarkColorLevel; 
      lpitch := ddsd.lPitch; 
      psource := ddsd.lpSurface; 
 
      asm 
            mov   row, 0 
         @@NextRow: 
            mov   ebx, row 
            mov   eax, srcheight 
            cmp   ebx, eax 
            jae   @@DrawFogFin 
 
            mov   esi, psource      //sptr 
            mov   eax, lpitch 
            mov   ebx, row 
            imul  eax, ebx 
            add   esi, eax 
 
            mov   eax, srclen 
            mov   scount, eax 
         @@FogNext: 
            mov   edx, pSrc     //pSrc = array[0..7] 
            mov   ebx, scount 
            cmp   ebx, 0 
            jbe   @@Finish 
            cmp   ebx, 8 
            jb    @@FogSmall 
 
            db $0F,$6F,$06           /// movq  mm0, [esi]       //8官捞飘 佬澜 sptr 
            db $0F,$7F,$02           /// movq  [edx], mm0 
            mov   count, 8 
 
          @@LevelChange: 
            mov   eax, darklevel 
            imul  eax, 256 
            movzx ebx, [edx].byte   //8官捞飘 弓澜栏肺 佬篮 单捞磐 
            add   eax, ebx 
            mov   ebx, pColorLevel 
            mov   al, [ebx+eax].byte 
            mov   [edx].byte, al 
 
         @@Skip1: 
            dec   count 
            inc   edx 
            inc   edi 
            cmp   count, 0 
            ja    @@LevelChange 
            sub   edx, 8 
 
            db $0F,$6F,$02           /// movq  mm0, [edx] 
            db $0F,$7F,$06           /// movq  [esi], mm0 
         @@Skip_8Byte: 
            sub   scount, 8 
            add   esi, 8 
            jmp   @@FogNext 
 
         @@FogSmall: 
            mov   eax, darklevel 
            imul  eax, 256 
            movzx ebx, [edx].byte 
            add   eax, ebx 
            mov   ebx, pColorLevel 
            mov   al, [ebx+eax].byte 
            mov   [esi].byte, al 
 
         @@Skip2: 
            inc   edi 
            inc   esi 
            dec   scount 
            jmp   @@FogNext 
 
         @@Finish: 
            inc   row 
            jmp   @@NextRow 
 
         @@DrawFogFin: 
            db $0F,$77               /// emms 
      end; 
   finally 
      ssuf.UnLock (); 
   end; 
end; 
 
//ssuf(system memory) -> dsuf(video memory)  : 捞锭父 荤侩且 巴 
//MMX指令实现BitBlt 
procedure MMXBlt (ssuf, dsuf: TDirectDrawSurface); 
var 
   n, m, aheight, awidth, spitch, dpitch: integer; 
   sddsd, dddsd: DDSURFACEDESC; 
   sptr, dptr: PByte; 
begin 
   try 
      sddsd.dwSize := SizeOf(sddsd); 
      ssuf.Lock (TRect(nil^), sddsd); 
      dddsd.dwSize := Sizeof(dddsd); 
      dsuf.Lock (TRect(nil^), dddsd); 
      aheight := ssuf.Height-1; 
      awidth := ssuf.Width-1; 
      spitch := sddsd.lPitch; 
      dpitch := dddsd.lPitch; 
      sptr := sddsd.lpSurface; //esi 
      dptr := dddsd.lpSurface; //edi 
      m := -1; //height 
      asm 
       @@NextLine: 
         inc   m 
         mov   eax, m 
         cmp   eax, aheight 
         jae   @@End 
         //sptr 
         mov   esi, sptr 
         mov   ebx, spitch 
         imul  eax, ebx 
         add   esi, eax 
         //dptr 
         mov   eax, m 
         mov   edi, dptr 
         mov   ebx, dpitch 
         imul  eax, ebx 
         add   edi, eax 
 
         xor   eax, eax 
       @@CopyNext: 
         cmp   eax, awidth 
         jae   @@NextLine 
 
         db $0F,$6F,$04,$06       /// movq  mm0, [esi+eax] 
         db $0F,$7F,$04,$07       /// movq  [edi+eax], mm0 
 
         add   eax, 8 
         jmp   @@CopyNext 
 
       @@End: 
         db $0F,$77               /// emms 
      end; 
   finally 
      ssuf.UnLock (); 
      dsuf.UnLock (); 
   end; 
end; 
 
//混合显示:ssurface + dsurface => dsurface 
procedure DrawBlend (dsuf: TDirectDrawSurface; x, y: integer; ssuf: TDirectDrawSurface; blendmode: integer); 
begin 
   DrawBlendEx (dsuf, x, y, ssuf, 0, 0, ssuf.Width, ssuf.Height, blendmode); 
end; 
 
//混合显示:DayBright:ssurface + dsurface => dsurface 
procedure DrawBlendEx (dsuf: TDirectDrawSurface; x, y: integer; ssuf: TDirectDrawSurface; ssufleft, ssuftop, ssufwidth, ssufheight, blendmode: integer); 
var 
   i, j, srcleft, srctop, srcwidth, srcbottom, sidx, didx: integer; 
   sddsd, dddsd: DDSURFACEDESC; 
   sptr, dptr, pmix: PByte; 
   source, dest: array[0..910] of byte; 
   bitindex, scount, dcount, srclen, destlen, wcount, awidth, bwidth: integer; 
begin 
   if (dsuf.canvas = nil) or (ssuf.canvas = nil) then exit; 
   if x >= dsuf.Width then exit; 
   if y >= dsuf.Height then exit; 
   if x < 0 then begin 
      srcleft := -x; 
      srcwidth := ssufwidth + x; 
      x := 0; 
   end else begin 
      srcleft := ssufleft; 
      srcwidth := ssufwidth; 
   end; 
   if y < 0 then begin 
      srctop := -y; 
      srcbottom := ssufheight; 
      y := 0; 
   end else begin 
      srctop := ssuftop; 
      srcbottom := srctop + ssufheight; 
   end; 
   if srcleft + srcwidth > ssuf.Width then srcwidth := ssuf.Width-srcleft; 
   if srcbottom > ssuf.Height then 
      srcbottom := ssuf.Height;//-srcheight; 
   if x + srcwidth > dsuf.Width then srcwidth := (dsuf.Width-x) div 4 * 4; 
   if y + srcbottom - srctop > dsuf.Height then 
      srcbottom := dsuf.Height-y+srctop; 
   if (x+srcwidth) * (y+srcbottom-srctop) > dsuf.Width * dsuf.Height then //烙矫.. 
      srcbottom := srctop + (srcbottom-srctop) div 2; 
 
   if (srcwidth <= 0) or (srcbottom <= 0) or (srcleft >= ssuf.Width) or (srctop >= ssuf.Height) then exit; 
   if srcWidth > 900 then exit; 
   try 
      sddsd.dwSize := SizeOf(sddsd); 
      dddsd.dwSize := SizeOf(dddsd); 
      ssuf.Lock (TRect(nil^), sddsd); 
      dsuf.Lock (TRect(nil^), dddsd); 
      awidth := srcwidth div 4; //ssuf.Width div 4; 
      bwidth := srcwidth; //ssuf.Width; 
      srclen := srcwidth; //ssuf.Width; 
      destlen := srcwidth; //ssuf.Width; 
      case blendmode of 
         0: pmix := @Color256Mix[0,0]; 
         else pmix := @Color256Anti[0,0]; 
      end; 
      for i:=srctop to srcbottom-1 do begin 
         sptr := PBYTE(integer(sddsd.lpSurface) + sddsd.lPitch * i + srcleft); 
         dptr := PBYTE(integer(dddsd.lpSurface) + (y+i-srctop) * dddsd.lPitch + x); 
         asm 
               mov   scount, 0 
               mov   esi, sptr 
               lea   edi, source 
               mov   ebx, scount        //ebx = scount 
            @@CopySource: 
               cmp   ebx, srclen 
               jae    @@EndSourceCopy 
               db $0F,$6F,$04,$1E       /// movq  mm0, [esi+ebx] 
               db $0F,$7F,$04,$1F       /// movq  [edi+ebx], mm0 
               add   ebx, 8 
               jmp   @@CopySource 
            @@EndSourceCopy: 
 
               mov   dcount, 0 
               mov   esi, dptr 
               lea   edi, dest 
               mov   ebx, dcount 
            @@CopyDest: 
               cmp   ebx, destlen 
               jae    @@EndDestCopy 
               db $0F,$6F,$04,$1E       /// movq  mm0, [esi+ebx] 
               db $0F,$7F,$04,$1F       /// movq  [edi+ebx], mm0 
               add   ebx, 8 
               jmp   @@CopyDest 
            @@EndDestCopy: 
 
               lea   esi, source 
               lea   edi, dest 
               mov   wcount, 0 
 
            @@BlendNext: 
               mov   ebx, wcount 
               cmp   [esi+ebx].byte, 0     //if _src[bitindex] > 0 
               jz    @@EndBlend 
 
               movzx eax, [esi+ebx].byte     //sidx := _src[bitindex] 
               shl   eax, 8                  //sidx * 256 
               mov   sidx, eax 
 
               movzx eax, [edi+ebx].byte     //didx := _dest[bitindex] 
               add   sidx, eax 
 
               mov   edx, pmix 
               mov   ecx, sidx 
               movzx eax, [edx+ecx].byte     // 
               mov   [edi+ebx], al 
 
            @@EndBlend: 
               inc   wcount 
               mov   eax, bwidth 
               cmp   wcount, eax 
               jb    @@BlendNext 
 
               lea   esi, dest               //Move (_src, dptr^, 4) 
               mov   edi, dptr 
               mov   ecx, awidth 
               cld 
               rep movsd 
 
         end; 
      end; 
      asm 
         db $0F,$77               /// emms 
      end; 
 
   finally 
      ssuf.UnLock (); 
      dsuf.UnLock (); 
   end; 
end; 
 
procedure   SpriteCopy(DestX, DestY : integer; 
                       SourX, SourY : integer; 
                       Size         : TPoint; 
                       Sour, Dest   : TDirectDrawSurface); 
const 
   TRANSPARENCY_VALUE  = 0; // 透明色,这里总是用黑色. 
var 
   SourDesc, DestDesc  : DDSURFACEDESC; 
   pSour, pDest, pMask : PByte; 
   Transparency        : array[1..8] of byte; 
begin 
   FillChar(Transparency,8,TRANSPARENCY_VALUE); 
 
   SourDesc.dwSize := SizeOf(DDSURFACEDESC); 
   Sour.Lock (TRect(nil^), SourDesc); 
   DestDesc.dwSize := SizeOf(DDSURFACEDESC); 
   Dest.Lock (TRect(nil^), DestDesc); 
 
   pSour := PByte(DWORD(SourDesc.lpSurface)+SourY*SourDesc.lPitch+SourX); 
   pDest := PByte(DWORD(DestDesc.lpSurface)+DestY*DestDesc.lPitch+DestX); 
   pMask := Pointer(@Transparency); 
 
   asm 
         push  esi 
         push  edi 
 
         mov   esi, pMask 
         db $0F,$6F,$26       /// movq  mm4, [esi] 
                              //  mm4 俊 捧疙祸 锅龋甫 持绰促 
         mov   esi, pSour 
         mov   edi, pDest 
 
         mov   ecx, Size.Y 
 
   @@LOOP_Y: 
 
         push  ecx 
 
         mov   ecx, Size.X 
         shr   ecx, 3         // 悼矫俊 8俺狼 痢阑 楷魂窍骨肺 
 
 
   @@LOOP_X: 
 
         db $0F,$6F,$07       /// movq  mm0, [edi] 
                              //  mm0 篮 Destination 
         db $0F,$6F,$0E       /// movq  mm1, [esi] 
                              //  mm1 篮 Source 
         db $0F,$6F,$D1       /// movq  mm2, mm1 
                              //  mm2 俊 Source 单捞磐甫 汗荤 
         db $0F,$74,$D4       /// pcmpeqb mm2, mm4 
                              //  mm2 俊 捧疙祸俊 蝶弗 付胶农甫 积己 
         db $0F,$6F,$DA       /// movq  mm3, mm2 
                              //  mm3 俊 付胶农甫 窍唱 歹 汗荤 
         db $0F,$DF,$D1       /// pandn mm2, mm1 
                              //  Source 胶橇扼捞飘 何盒父阑 巢辫 
         db $0F,$DB,$D8       /// pand  mm3, mm0 
                              //  Destination 狼 盎脚瞪 何盒父 力芭 
         db $0F,$EB,$D3       /// por   mm2, mm3 
                              //  Source 客 Destination 阑 搬钦 
         db $0F,$7F,$17       /// movq  [edi], mm2 
                              //  Destination 俊 搬苞甫 靖 
 
         add   esi, 8 
                              //  茄锅俊 8 bytes 甫 悼矫俊 贸府沁栏骨肺 
         add   edi, 8 
 
         loop  @@LOOP_X 
 
         add   esi, SourDesc.lPitch 
         sub   esi, Size.X 
         add   edi, DestDesc.lPitch 
         sub   edi, Size.X 
 
         pop   ecx 
         loop  @@LOOP_Y 
 
         db $0F,$77              /// emms 
 
         pop   edi 
         pop   esi 
 
   end; 
 
   Sour.UnLock(); 
   Dest.UnLock(); 
 
end; 
 
//画效果 
procedure DrawEffect (x, y, width, height: integer; ssuf: TDirectDrawSurface; eff: TColorEffect); 
var 
   i, j, n, scount, srclen: integer; 
   sddsd: DDSURFACEDESC; 
   sptr, peff: PByte; 
   source: array[0..810] of byte; 
begin 
   if Width > 800 then exit; 
   if eff = ceNone then exit; 
   peff := nil; 
   case eff of 
      ceGrayScale: peff := @GrayScaleLevel; 
      ceBright: peff := @BrightColorLevel; 
      ceBlack: peff := @BlackColorLevel; 
      ceWhite: peff := @WhiteColorLevel; 
      ceRed: peff := @RedishColorLevel; 
      ceGreen: peff := @GreenColorLevel; 
      ceBlue:  peff := @BlueColorLevel; 
      ceYellow:  peff := @YellowColorLevel; 
      ceFuchsia: peff := @FuchsiaColorLevel; 
      //else exit; 
   end; 
   if peff = nil then begin 
      peff := nil; 
      exit; 
   end; 
   try 
      sddsd.dwSize := SizeOf(sddsd); 
      ssuf.Lock (TRect(nil^), sddsd); 
      srclen := width; 
      for i:=0 to height-1 do begin 
         sptr := PBYTE(integer(sddsd.lpSurface) + (y+i) * sddsd.lPitch + x); 
         asm 
               mov   scount, 0 
               mov   esi, sptr 
               lea   edi, source 
            @@CopySource: 
               mov   ebx, scount        //ebx = scount 
               cmp   ebx, srclen 
               jae   @@EndSourceCopy 
               db $0F,$6F,$04,$1E       /// movq  mm0, [esi+ebx] 
               db $0F,$7F,$07           /// movq  [edi], mm0 
 
               mov   ebx, 0 
            @@Loop8: 
               cmp   ebx, 8 
               jz    @@EndLoop8 
               movzx eax, [edi+ebx].byte 
               mov   edx, peff 
               movzx eax, [edx+eax].byte     // 
               mov   [edi+ebx], al 
               inc   ebx 
               jmp   @@Loop8 
            @@EndLoop8: 
 
               mov   ebx, scount 
               db $0F,$6F,$07           /// movq  mm0, [edi] 
               db $0F,$7F,$04,$1E       /// movq  [esi+ebx], mm0 
 
               add   edi, 8 
               add   scount, 8 
               jmp   @@CopySource 
            @@EndSourceCopy: 
               db $0F,$77               /// emms 
 
         end; 
      end; 
   finally 
      ssuf.UnLock (); 
   end; 
end; 
 
 
end.