📄 r_part.pas
字号:
//100%
{$ALIGN 8}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{ }
{ File(s): r_part.c }
{ }
{ Initial conversion by : Gargoylle[LtK](gargoylle_ltk@hotmail.com }
{ Initial conversion on : 09-Jul-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. }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ r_main }
{----------------------------------------------------------------------------}
{ * TODO: }
{ * VERRY IMPORTANT: some of the routines in r_part.c are declared as }
{ __declspec(naked). As far as I know this means that no frame stack }
{ is created for them. I however have no knoledge of how to do this }
{ in Delphi so currently __declspec(naked) is IGNORED and the routines }
{ are just declared as any other normal routines. A suitable solution }
{ must however be found. }
{ * conversion started on 09-Jul-2002 }
{----------------------------------------------------------------------------}
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//
// PLEASE NOTE:
// 1) all original comments will be retained. My own comments will begin with
// "GARGO".
// 2) this file does not have a .H file to go with it
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
unit r_part;
interface
uses
q_shared,
ref,
r_local,
rw_imp; // see the note at R_DrawParticles
{$IFDEF id386}
{$IFNDEF __linux__}
// GARGO: GARGO_ByteFunc required to declare variables needed by R_DrawParticle
type
GARGO_ByteFunc = function: byte;
var
s_prefetch_address: Cardinal;
// GARGO: the following are the routines declared in r_part.c
// As I have mentioned before, some are originally declared
// as __declspec(naked). Currently I have ignored it so the
// routines are declared as any normal routine would be.
// procedure BlendParticle33;
// procedure BlendParticle66;
// procedure BlendParticle100;
{$ENDIF} // __linux__
{$ELSE}
// procedure BlendParticle33;
// procedure BlendParticle66;
// procedure BlendParticle100;
{$ENDIF}
procedure R_DrawParticles;
implementation
uses
r_misc,
r_main,
DelphiTypes,
SysUtils;
const
PARTICLE_33 = 0;
PARTICLE_66 = 1;
PARTICLE_OPAQUE = 2;
type
partparms_p = ^partparms_t;
ppartparms_t = partparms_p;
partparms_t = record
particle: particle_p;
level: integer;
color: integer;
end;
TPartParms = partparms_t;
PPartParms = ppartparms_t;
var
r_pright: vec3_t;
r_pup: vec3_t;
r_ppn: vec3_t;
partparms: partparms_t;
{$IFDEF id386}
{$IFNDEF __linux__}
(*
** BlendParticleXX
**
** Inputs:
** EAX = color
** EDI = pdest
**
** Scratch:
** EBX = scratch (dstcolor)
** EBP = scratch
**
** Outputs:
** none
*)
procedure BlendParticle33;
asm
// return vid.alphamap[color + dstcolor*256];
mov ebp, vid.alphamap
xor ebx, ebx
mov bl, byte ptr [edi]
shl ebx, 8
add ebp, ebx
add ebp, eax
mov al, byte ptr [ebp]
mov byte ptr [edi], al
end;
procedure BlendParticle66;
asm
// return vid.alphamap[pcolor*256 + dstcolor];
mov ebp, vid.alphamap
xor ebx, ebx
shl eax, 8
mov bl, byte ptr [edi]
add ebp, ebx
add ebp, eax
mov al, byte ptr [ebp]
mov byte ptr [edi], al
end;
procedure BlendParticle100;
asm
mov byte ptr [edi], al
end;
{
** R_DrawParticle (asm version)
**
** Since we use __declspec( naked ) we don't have a stack frame
** that we can use. Since I want to reserve EBP anyway, I tossed
** all the important variables into statics. This routine isn't
** meant to be re-entrant, so this shouldn't cause any problems
** other than a slightly higher global memory footprint.
**
}
procedure R_DrawParticle;
// GARGO: labels must be defined before they are used, even in
// assmebler code
label
blendfunc_33;
label
blendfunc_66;
label
done_selecting_blend_func;
label
check_pix_max;
label
skip_pix_clamp;
label
over;
label
top_of_pix_vert_loop;
label
top_of_pix_horiz_loop;
label
end_of_horiz_loop;
label
end_;
asm
// GARGO: statics declared here moved to the interface area
{
** save trashed variables
}
mov ebpsave, ebp
push esi
push edi
{
** transform the particle
}
// VectorSubtract (pparticle->origin, r_origin, local);
mov esi, partparms.particle
fld dword ptr [esi+0] // p_o.x
fsub dword ptr [r_origin+0] // p_o.x-r_o.x
fld dword ptr [esi+4] // p_o.y | p_o.x-r_o.x
fsub dword ptr [r_origin+4] // p_o.y-r_o.y | p_o.x-r_o.x
fld dword ptr [esi+8] // p_o.z | p_o.y-r_o.y | p_o.x-r_o.x
fsub dword ptr [r_origin+8] // p_o.z-r_o.z | p_o.y-r_o.y | p_o.x-r_o.x
fxch st(2) // p_o.x-r_o.x | p_o.y-r_o.y | p_o.z-r_o.z
fstp dword ptr [local+0] // p_o.y-r_o.y | p_o.z-r_o.z
fstp dword ptr [local+4] // p_o.z-r_o.z
fstp dword ptr [local+8] // (empty)
// transformed[0] = DotProduct(local, r_pright);
// transformed[1] = DotProduct(local, r_pup);
// transformed[2] = DotProduct(local, r_ppn);
fld dword ptr [local+0] // l.x
fmul dword ptr [r_pright+0] // l.x*pr.x
fld dword ptr [local+4] // l.y | l.x*pr.x
fmul dword ptr [r_pright+4] // l.y*pr.y | l.x*pr.x
fld dword ptr [local+8] // l.z | l.y*pr.y | l.x*pr.x
fmul dword ptr [r_pright+8] // l.z*pr.z | l.y*pr.y | l.x*pr.x
fxch st(2) // l.x*pr.x | l.y*pr.y | l.z*pr.z
faddp st(1), st // l.x*pr.x + l.y*pr.y | l.z*pr.z
faddp st(1), st // l.x*pr.x + l.y*pr.y + l.z*pr.z
fstp dword ptr [transformed+0] // (empty)
fld dword ptr [local+0] // l.x
fmul dword ptr [r_pup+0] // l.x*pr.x
fld dword ptr [local+4] // l.y | l.x*pr.x
fmul dword ptr [r_pup+4] // l.y*pr.y | l.x*pr.x
fld dword ptr [local+8] // l.z | l.y*pr.y | l.x*pr.x
fmul dword ptr [r_pup+8] // l.z*pr.z | l.y*pr.y | l.x*pr.x
fxch st(2) // l.x*pr.x | l.y*pr.y | l.z*pr.z
faddp st(1), st // l.x*pr.x + l.y*pr.y | l.z*pr.z
faddp st(1), st // l.x*pr.x + l.y*pr.y + l.z*pr.z
fstp dword ptr [transformed+4] // (empty)
fld dword ptr [local+0] // l.x
fmul dword ptr [r_ppn+0] // l.x*pr.x
fld dword ptr [local+4] // l.y | l.x*pr.x
fmul dword ptr [r_ppn+4] // l.y*pr.y | l.x*pr.x
fld dword ptr [local+8] // l.z | l.y*pr.y | l.x*pr.x
fmul dword ptr [r_ppn+8] // l.z*pr.z | l.y*pr.y | l.x*pr.x
fxch st(2) // l.x*pr.x | l.y*pr.y | l.z*pr.z
faddp st(1), st // l.x*pr.x + l.y*pr.y | l.z*pr.z
faddp st(1), st // l.x*pr.x + l.y*pr.y + l.z*pr.z
fstp dword ptr [transformed+8] // (empty)
{
** make sure that the transformed particle is not in front of
** the particle Z clip plane. We can do the comparison in
** integer space since we know the sign of one of the inputs
** and can figure out the sign of the other easily enough.
}
// if (transformed[2] < PARTICLE_Z_CLIP)
// return;
mov eax, dword ptr [transformed+8]
and eax, eax
js end_
cmp eax, particle_z_clip
jl end_
{
** project the point by initiating the 1/z calc
}
// zi = 1.0 / transformed[2];
fld one
fdiv dword ptr [transformed+8]
{
** bind the blend function pointer to the appropriate blender
** while we're dividing
}
//if ( level == PARTICLE_33 )
// blendparticle = BlendParticle33;
//else if ( level == PARTICLE_66 )
// blendparticle = BlendParticle66;
//else
// blendparticle = BlendParticle100;
cmp partparms.level, PARTICLE_66
je blendfunc_66
jl blendfunc_33
lea ebx, BlendParticle100
jmp done_selecting_blend_func
blendfunc_33:
lea ebx, BlendParticle33
jmp done_selecting_blend_func
blendfunc_66:
lea ebx, BlendParticle66
done_selecting_blend_func:
mov blendfunc, ebx
// prefetch the next particle
mov ebp, s_prefetch_address
mov ebp, [ebp]
// finish the above divide
fstp zi
// u = (int)(xcenter + zi * transformed[0] + 0.5);
// v = (int)(ycenter - zi * transformed[1] + 0.5);
fld zi // zi
fmul dword ptr [transformed+0] // zi * transformed[0]
fld zi // zi | zi * transformed[0]
fmul dword ptr [transformed+4] // zi * transformed[1] | zi * transformed[0]
fxch st(1) // zi * transformed[0] | zi * transformed[1]
fadd xcenter // xcenter + zi * transformed[0] | zi * transformed[1]
fxch st(1) // zi * transformed[1] | xcenter + zi * transformed[0]
fld ycenter // ycenter | zi * transformed[1] | xcenter + zi * transformed[0]
fsubrp st(1), st(0) // ycenter - zi * transformed[1] | xcenter + zi * transformed[0]
fxch st(1) // xcenter + zi * transformed[0] | ycenter + zi * transformed[1]
fadd point_five // xcenter + zi * transformed[0] + 0.5 | ycenter - zi * transformed[1]
fxch st(1) // ycenter - zi * transformed[1] | xcenter + zi * transformed[0] + 0.5
fadd point_five // ycenter - zi * transformed[1] + 0.5 | xcenter + zi * transformed[0] + 0.5
fxch st(1) // u | v
fistp dword ptr [u] // v
fistp dword ptr [v] // (empty)
{
** clip out the particle
}
// if ((v > d_vrectbottom_particle) ||
// (u > d_vrectright_particle) ||
// (v < d_vrecty) ||
// (u < d_vrectx))
// {
// return;
// }
mov ebx, u
mov ecx, v
cmp ecx, d_vrectbottom_particle
jg end_
cmp ecx, d_vrecty
jl end_
cmp ebx, d_vrectright_particle
jg end_
cmp ebx, d_vrectx
jl end_
{
** compute addresses of zbuffer, framebuffer, and
** compute the Z-buffer reference value.
**
** EBX = U
** ECX = V
**
** Outputs:
** ESI = Z-buffer address
** EDI = framebuffer address
}
// ESI = d_pzbuffer + (d_zwidth * v) + u;
mov esi, d_pzbuffer // esi = d_pzbuffer
mov eax, d_zwidth // eax = d_zwidth
mul ecx // eax = d_zwidth*v
add eax, ebx // eax = d_zwidth*v+u
shl eax, 1 // eax = 2*(d_zwidth*v+u)
add esi, eax // ; esi = ( short * ) ( d_pzbuffer + ( d_zwidth * v ) + u )
// initiate
// izi = (int)(zi * 0x8000);
fld zi
fmul eight_thousand_hex
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -