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

📄 r_part.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:

    // EDI = pdest = d_viewbuffer + d_scantable[v] + u;
    lea edi, [d_scantable+ecx*4]
    mov edi, [edi]
    add edi, d_viewbuffer
    add edi, ebx

    // complete
    // izi = (int)(zi * 0x8000);
    fistp tmp
    mov   eax, tmp
    mov   izi, ax

    {
    ** determine the screen area covered by the particle,
    ** which also means clamping to a min and max
    }
    //	pix = izi >> d_pix_shift;
    xor edx, edx
    mov dx, izi
    mov ecx, d_pix_shift
    shr dx, cl

    //	if (pix < d_pix_min)
    //		pix = d_pix_min;
    cmp edx, d_pix_min
    jge check_pix_max
    mov edx, d_pix_min
    jmp skip_pix_clamp

    //	else if (pix > d_pix_max)
    //		pix = d_pix_max;
check_pix_max:
    cmp edx, d_pix_max
    jle skip_pix_clamp
    mov edx, d_pix_max

skip_pix_clamp:

    {
    ** render the appropriate pixels
    **
    ** ECX = count (used for inner loop)
    ** EDX = count (used for outer loop)
    ** ESI = zbuffer
    ** EDI = framebuffer
    }
    mov ecx, edx

    cmp ecx, 1
    ja  over

over:

    {
    ** at this point:
    **
    ** ECX = count
    }
    push ecx
    push edi
    push esi

top_of_pix_vert_loop:

top_of_pix_horiz_loop:

    //	for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
    //	{
    //		for (i=0 ; i<pix ; i++)
    //		{
    //			if (pz[i] <= izi)
    //			{
    //				pdest[i] = blendparticle( color, pdest[i] );
    //			}
    //		}
    //	}
    xor   eax, eax

    mov   ax, word ptr [esi]

    cmp   ax, izi
    jg    end_of_horiz_loop

{$ifdef ENABLE_ZWRITES_FOR_PARTICLES}
    mov   bp, izi
    mov   word ptr [esi], bp
{$endif}

    mov   eax, partparms.color

    call  [blendfunc]

    add   edi, 1
    add   esi, 2

end_of_horiz_loop:

    dec ecx
    jnz top_of_pix_horiz_loop

    pop esi
    pop edi

    mov ebp, d_zwidth
    shl ebp, 1

    add esi, ebp
    add edi, [r_screenwidth]

    pop ecx
    push ecx

    push edi
    push esi

    dec edx
    jnz top_of_pix_vert_loop

    pop ecx
    pop ecx
    pop ecx

end_:
    pop edi
    pop esi
    mov ebp, ebpsave
    ret
end;

{$ENDIF} // __linux__
{$ELSE}

type
  TBlendParticle = function(pcolor, dstcolor: Integer): Byte;

function BlendParticle33(pcolor, dstcolor: Integer): Byte;
begin
  Result := PByte(Integer(vid.alphamap) + (pcolor + dstcolor * 256))^;
end;

function BlendParticle66(pcolor, dstcolor: Integer): Byte;
begin
  Result := PByte(Integer(vid.alphamap) + (pcolor * 256 + dstcolor))^;
end;

function BlendParticle100(pcolor, dstcolor: Integer): Byte;
begin
  Result := pcolor;
end;

(*
** R_DrawParticle
**
** Yes, this is amazingly slow, but it's the C reference
** implementation and should be both robust and vaguely
** understandable.  The only time this path should be
** executed is if we're debugging on x86 or if we're
** recompiling and deploying on a non-x86 platform.
**
** To minimize error and improve readability I went the
** function pointer route.  This exacts some overhead, but
** it pays off in clean and easy to understand code.
*)

procedure R_DrawParticle;
var
  pparticle: particle_p;
  level: Integer;
  local: vec3_t;
  transformed: vec3_t;
  zi: Single;
  pdest: PByte;
  pz: PSmallInt;
  color: Integer;
  i, izi, pix: Integer;
  count, u, v: Integer;
//	blendparticle : TBlendParticle;
begin
  pparticle := partparms.particle;
  level := partparms.level;
  color := pparticle^.color;
 (*
 ** transform the particle
 *)
  VectorSubtract(pparticle^.origin, r_origin, local);

  transformed[0] := DotProduct(local, r_pright);
  transformed[1] := DotProduct(local, r_pup);
  transformed[2] := DotProduct(local, r_ppn);

  if (transformed[2] < PARTICLE_Z_CLIP) then
    Exit;

 (*
 ** bind the blend function pointer to the appropriate blender
 *)
(*	if (level = PARTICLE_33) then
  blendparticle := BlendParticle33
 else
  begin
    if (level = PARTICLE_66) then
    blendparticle := BlendParticle66
   else
    blendparticle := BlendParticle100;
  end;*)
 (*
 ** project the point
 *)
 // FIXME: preadjust xcenter and ycenter
  zi := 1.0 / transformed[2];
  u := Trunc(xcenter + zi * transformed[0] + 0.5);
  v := Trunc(ycenter - zi * transformed[1] + 0.5);

  if ((v > d_vrectbottom_particle) or (u > d_vrectright_particle) or (v < d_vrecty) or (u < d_vrectx)) then
    Exit;

 (*
 ** compute addresses of zbuffer, framebuffer, and
 ** compute the Z-buffer reference value.
 *)
  pz := PSmallInt(Integer(d_pzbuffer) + (((Integer(d_zwidth) * v) + u) * SizeOf(SmallInt)));
  pdest := PByte(Integer(d_viewbuffer) + (d_scantable[v] + u));
  izi := Trunc(zi * $8000);

 (*
 ** determine the screen area covered by the particle,
 ** which also means clamping to a min and max
 *)
  pix := _SAR(izi, d_pix_shift);
  if (pix < d_pix_min) then
    pix := d_pix_min
  else
    if (pix > d_pix_max) then
      pix := d_pix_max;

 (*
 ** render the appropriate pixels
 *)
  count := pix;
  case (level) of
    PARTICLE_33:
      begin
        while (count > 0) do
        begin
          //FIXME--do it in blocks of 8?
          for I := 0 to pix - 1 do
          begin
            if (PSmallIntArray(pz)^[i] <= izi) then
            begin
              PSmallIntArray(pz)^[i] := izi;
              PByteArray(pdest)^[i] := PByteArray(vid.alphamap)^[color + (Integer(PByteArray(pdest)^[i]) shl 8)];
            end;
          end;
          Inc(Cardinal(pz), d_zwidth * SizeOf(SmallInt));
          Inc(Integer(pdest), r_screenwidth);
          Dec(count);
        end;
      end;
    PARTICLE_66:
      begin
        while (count > 0) do
        begin
          for I := 0 to pix - 1 do
          begin
            if (PSmallIntArray(pz)^[i] <= izi) then
            begin
              PSmallIntArray(pz)^[i] := izi;
              PByteArray(pdest)^[i] := PByteArray(vid.alphamap)^[(color shl 8) + Integer(PByteArray(pdest)^[i])];
            end;
          end;
          Inc(Cardinal(pz), d_zwidth * SizeOf(SmallInt));
          Inc(Integer(pdest), r_screenwidth);
          Dec(count);
        end;
      end;
  else //100
    begin
      while (count > 0) do
      begin
        for I := 0 to pix - 1 do
        begin
          if (PSmallIntArray(pz)^[i] <= izi) then
          begin
            PSmallIntArray(pz)^[i] := izi;
            PByteArray(pdest)^[i] := color;
          end;
        end;
        Inc(Cardinal(pz), d_zwidth * SizeOf(SmallInt));
        Inc(Integer(pdest), r_screenwidth);
        Dec(count);
      end;
    end;
  end;
end;

{$ENDIF} // id386

(*
** R_DrawParticles
**
** Responsible for drawing all of the particles in the particle list
** throughout the world.  Doesn't care if we're using the C path or
** if we're using the asm path, it simply assigns a function pointer
** and goes.
*)

procedure R_DrawParticles;
var
  p: particle_p;
  i: Integer;
//	extern unsigned long fpu_sp24_cw, fpu_chop_cw;
begin
  VectorScale(vright, xscaleshrink, r_pright);
  VectorScale(vup, yscaleshrink, r_pup);
  VectorCopy(vpn, r_ppn);

{$IFDEF id386}
{$IFNDEF __linux__}
  asm
    fldcw word ptr [fpu_sp24_cw]
  end;
{$ENDIF}
{$ENDIF}
  p := r_newrefdef.particles;
  for i := 0 to r_newrefdef.num_particles - 1 do
  begin
    if (p^.alpha > 0.66) then
      partparms.level := PARTICLE_OPAQUE
    else
    begin
      if (p^.alpha > 0.33) then
        partparms.level := PARTICLE_66
      else
        partparms.level := PARTICLE_33;
    end;
    partparms.particle := p;
    partparms.color := p^.color;
{$IFDEF id386}
    if (i < r_newrefdef.num_particles - 1) then
      s_prefetch_address := Integer(p) + 1
    else
      s_prefetch_address := Integer(r_newrefdef.particles);
{$ENDIF}
    R_DrawParticle;
    Inc(Integer(p), SizeOf(particle_t));
  end;
{$IFDEF id386}
  asm
    __asm fldcw word ptr [fpu_chop_cw]
  end;
{$ENDIF}

(*  r_newrefdef.particles
 for (p=r_newrefdef.particles, i=0 ; i<r_newrefdef.num_particles ; i++,p++)
 for (p=r_newrefdef.particles, i=0 ; i<r_newrefdef.num_particles ; i++,p++)
 {

  if ( p->alpha > 0.66 )
   partparms.level = PARTICLE_OPAQUE;
  else if ( p->alpha > 0.33 )
   partparms.level = PARTICLE_66;
  else
   partparms.level = PARTICLE_33;

  partparms.particle = p;
  partparms.color    = p->color;

#if id386 && !defined __linux__
  if ( i < r_newrefdef.num_particles-1 )
   s_prefetch_address = ( unsigned int ) ( p + 1 );
  else
   s_prefetch_address = ( unsigned int ) r_newrefdef.particles;
#endif

  R_DrawParticle;
 end;

#if id386 && !defined __linux__
 __asm fldcw word ptr [fpu_chop_cw]
#endif*)
end;

end.

⌨️ 快捷键说明

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