?? r_part.c
字號:
/*
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "r_local.h"
vec3_t r_pright, r_pup, r_ppn;
#define PARTICLE_33 0
#define PARTICLE_66 1
#define PARTICLE_OPAQUE 2
typedef struct
{
particle_t *particle;
int level;
int color;
} partparms_t;
static partparms_t partparms;
#if id386 && !defined __linux__
static unsigned s_prefetch_address;
/*
** BlendParticleXX
**
** Inputs:
** EAX = color
** EDI = pdest
**
** Scratch:
** EBX = scratch (dstcolor)
** EBP = scratch
**
** Outputs:
** none
*/
__declspec(naked) void BlendParticle33( void )
{
// return vid.alphamap[color + dstcolor*256];
__asm mov ebp, vid.alphamap
__asm xor ebx, ebx
__asm mov bl, byte ptr [edi]
__asm shl ebx, 8
__asm add ebp, ebx
__asm add ebp, eax
__asm mov al, byte ptr [ebp]
__asm mov byte ptr [edi], al
__asm ret
}
__declspec(naked) void BlendParticle66( void )
{
// return vid.alphamap[pcolor*256 + dstcolor];
__asm mov ebp, vid.alphamap
__asm xor ebx, ebx
__asm shl eax, 8
__asm mov bl, byte ptr [edi]
__asm add ebp, ebx
__asm add ebp, eax
__asm mov al, byte ptr [ebp]
__asm mov byte ptr [edi], al
__asm ret
}
__declspec(naked) void BlendParticle100( void )
{
__asm mov byte ptr [edi], al
__asm ret
}
/*
** 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.
**
*/
__declspec(naked) void R_DrawParticle( void )
{
static vec3_t local, transformed;
static float zi;
static int u, v, tmp;
static short izi;
static int ebpsave;
static byte (*blendfunc)(void);
/*
** must be memvars since x86 can't load constants
** directly. I guess I could use fld1, but that
** actually costs one more clock than fld [one]!
*/
static float particle_z_clip = PARTICLE_Z_CLIP;
static float one = 1.0F;
static float point_five = 0.5F;
static float eight_thousand_hex = 0x8000;
/*
** save trashed variables
*/
__asm mov ebpsave, ebp
__asm push esi
__asm push edi
/*
** transform the particle
*/
// VectorSubtract (pparticle->origin, r_origin, local);
__asm mov esi, partparms.particle
__asm fld dword ptr [esi+0] ; p_o.x
__asm fsub dword ptr [r_origin+0] ; p_o.x-r_o.x
__asm fld dword ptr [esi+4] ; p_o.y | p_o.x-r_o.x
__asm fsub dword ptr [r_origin+4] ; p_o.y-r_o.y | p_o.x-r_o.x
__asm fld dword ptr [esi+8] ; p_o.z | p_o.y-r_o.y | p_o.x-r_o.x
__asm fsub dword ptr [r_origin+8] ; p_o.z-r_o.z | p_o.y-r_o.y | p_o.x-r_o.x
__asm fxch st(2) ; p_o.x-r_o.x | p_o.y-r_o.y | p_o.z-r_o.z
__asm fstp dword ptr [local+0] ; p_o.y-r_o.y | p_o.z-r_o.z
__asm fstp dword ptr [local+4] ; p_o.z-r_o.z
__asm fstp dword ptr [local+8] ; (empty)
// transformed[0] = DotProduct(local, r_pright);
// transformed[1] = DotProduct(local, r_pup);
// transformed[2] = DotProduct(local, r_ppn);
__asm fld dword ptr [local+0] ; l.x
__asm fmul dword ptr [r_pright+0] ; l.x*pr.x
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
__asm fmul dword ptr [r_pright+4] ; l.y*pr.y | l.x*pr.x
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
__asm fmul dword ptr [r_pright+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
__asm fstp dword ptr [transformed+0] ; (empty)
__asm fld dword ptr [local+0] ; l.x
__asm fmul dword ptr [r_pup+0] ; l.x*pr.x
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
__asm fmul dword ptr [r_pup+4] ; l.y*pr.y | l.x*pr.x
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
__asm fmul dword ptr [r_pup+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
__asm fstp dword ptr [transformed+4] ; (empty)
__asm fld dword ptr [local+0] ; l.x
__asm fmul dword ptr [r_ppn+0] ; l.x*pr.x
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
__asm fmul dword ptr [r_ppn+4] ; l.y*pr.y | l.x*pr.x
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
__asm fmul dword ptr [r_ppn+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
__asm 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;
__asm mov eax, dword ptr [transformed+8]
__asm and eax, eax
__asm js end
__asm cmp eax, particle_z_clip
__asm jl end
/*
** project the point by initiating the 1/z calc
*/
// zi = 1.0 / transformed[2];
__asm fld one
__asm 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;
__asm cmp partparms.level, PARTICLE_66
__asm je blendfunc_66
__asm jl blendfunc_33
__asm lea ebx, BlendParticle100
__asm jmp done_selecting_blend_func
blendfunc_33:
__asm lea ebx, BlendParticle33
__asm jmp done_selecting_blend_func
blendfunc_66:
__asm lea ebx, BlendParticle66
done_selecting_blend_func:
__asm mov blendfunc, ebx
// prefetch the next particle
__asm mov ebp, s_prefetch_address
__asm mov ebp, [ebp]
// finish the above divide
__asm fstp zi
// u = (int)(xcenter + zi * transformed[0] + 0.5);
// v = (int)(ycenter - zi * transformed[1] + 0.5);
__asm fld zi ; zi
__asm fmul dword ptr [transformed+0] ; zi * transformed[0]
__asm fld zi ; zi | zi * transformed[0]
__asm fmul dword ptr [transformed+4] ; zi * transformed[1] | zi * transformed[0]
__asm fxch st(1) ; zi * transformed[0] | zi * transformed[1]
__asm fadd xcenter ; xcenter + zi * transformed[0] | zi * transformed[1]
__asm fxch st(1) ; zi * transformed[1] | xcenter + zi * transformed[0]
__asm fld ycenter ; ycenter | zi * transformed[1] | xcenter + zi * transformed[0]
__asm fsubrp st(1), st(0) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0]
__asm fxch st(1) ; xcenter + zi * transformed[0] | ycenter + zi * transformed[1]
__asm fadd point_five ; xcenter + zi * transformed[0] + 0.5 | ycenter - zi * transformed[1]
__asm fxch st(1) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0] + 0.5
__asm fadd point_five ; ycenter - zi * transformed[1] + 0.5 | xcenter + zi * transformed[0] + 0.5
__asm fxch st(1) ; u | v
__asm fistp dword ptr [u] ; v
__asm 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;
// }
__asm mov ebx, u
__asm mov ecx, v
__asm cmp ecx, d_vrectbottom_particle
__asm jg end
__asm cmp ecx, d_vrecty
__asm jl end
__asm cmp ebx, d_vrectright_particle
__asm jg end
__asm cmp ebx, d_vrectx
__asm 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;
__asm mov esi, d_pzbuffer ; esi = d_pzbuffer
__asm mov eax, d_zwidth ; eax = d_zwidth
__asm mul ecx ; eax = d_zwidth*v
__asm add eax, ebx ; eax = d_zwidth*v+u
__asm shl eax, 1 ; eax = 2*(d_zwidth*v+u)
__asm add esi, eax ; esi = ( short * ) ( d_pzbuffer + ( d_zwidth * v ) + u )
// initiate
// izi = (int)(zi * 0x8000);
__asm fld zi
__asm fmul eight_thousand_hex
// EDI = pdest = d_viewbuffer + d_scantable[v] + u;
__asm lea edi, [d_scantable+ecx*4]
__asm mov edi, [edi]
__asm add edi, d_viewbuffer
__asm add edi, ebx
// complete
// izi = (int)(zi * 0x8000);
__asm fistp tmp
__asm mov eax, tmp
__asm mov izi, ax
/*
** determine the screen area covered by the particle,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -