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

📄 r_drawa.asm

📁 Quake 2 Source code for students by Theerthan You can also download from idsoftwares.com
💻 ASM
📖 第 1 页 / 共 2 页
字号:
 .386P
 .model FLAT
;
; r_drawa.s
; x86 assembly-language edge clipping and emission code
;

include qasm.inc
include d_if.inc

if	id386

; !!! if these are changed, they must be changed in r_draw.c too !!!
FULLY_CLIPPED_CACHED	equ		080000000h
FRAMECOUNT_MASK			equ		07FFFFFFFh

_DATA SEGMENT	

Ld0 dd 0.0	
Ld1 dd 0.0	
Lstack dd 0	
Lfp_near_clip dd NEAR_CLIP	
Lceilv0 dd 0	
Lv dd 0	
Lu0 dd 0	
Lv0 dd 0	
Lzi0 dd 0	

_DATA ENDS
_TEXT SEGMENT	

;----------------------------------------------------------------------
; edge clipping code
;----------------------------------------------------------------------

pv0		equ		4+12
pv1		equ		8+12
clip	equ		12+12

 align 4	
 public _R_ClipEdge	
_R_ClipEdge:	
 push esi	; preserve register variables
 push edi	
 push ebx	
 mov ds:dword ptr[Lstack],esp	; for clearing the stack later

;	float		d0, d1, f;
;	mvertex_t	clipvert;

 mov ebx,ds:dword ptr[clip+esp]	
 mov esi,ds:dword ptr[pv0+esp]	
 mov edx,ds:dword ptr[pv1+esp]	

;	if (clip)
;	{
 test ebx,ebx	
 jz Lemit	

;		do
;		{

Lcliploop:	

;			d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
;			d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
 fld ds:dword ptr[mv_position+0+esi]	
 fmul ds:dword ptr[cp_normal+0+ebx]	
 fld ds:dword ptr[mv_position+4+esi]	
 fmul ds:dword ptr[cp_normal+4+ebx]	
 fld ds:dword ptr[mv_position+8+esi]	
 fmul ds:dword ptr[cp_normal+8+ebx]	
 fxch st(1)	
 faddp st(2),st(0)	; d0mul2 | d0add0

 fld ds:dword ptr[mv_position+0+edx]	
 fmul ds:dword ptr[cp_normal+0+ebx]	
 fld ds:dword ptr[mv_position+4+edx]	
 fmul ds:dword ptr[cp_normal+4+ebx]	
 fld ds:dword ptr[mv_position+8+edx]	
 fmul ds:dword ptr[cp_normal+8+ebx]	
 fxch st(1)	
 faddp st(2),st(0)	; d1mul2 | d1add0 | d0mul2 | d0add0
 fxch st(3)	; d0add0 | d1add0 | d0mul2 | d1mul2

 faddp st(2),st(0)	; d1add0 | dot0 | d1mul2 
 faddp st(2),st(0)	; dot0 | dot1

 fsub ds:dword ptr[cp_dist+ebx]	; d0 | dot1
 fxch st(1)	; dot1 | d0
 fsub ds:dword ptr[cp_dist+ebx]	; d1 | d0
 fxch st(1)	
 fstp ds:dword ptr[Ld0]	
 fstp ds:dword ptr[Ld1]	

;			if (d0 >= 0)
;			{
 mov eax,ds:dword ptr[Ld0]	
 mov ecx,ds:dword ptr[Ld1]	
 or ecx,eax	
 js Lp2	

; both points are unclipped

Lcontinue:	

;
;				R_ClipEdge (&clipvert, pv1, clip->next);
;				return;
;			}
;		} while ((clip = clip->next) != NULL);
 mov ebx,ds:dword ptr[cp_next+ebx]	
 test ebx,ebx	
 jnz Lcliploop	

;	}

;// add the edge
;	R_EmitEdge (pv0, pv1);
Lemit:	

;
; set integer rounding to ceil mode, set to single precision
;
; FIXME: do away with by manually extracting integers from floats?
; FIXME: set less often
 fldcw ds:word ptr[_fpu_ceil_cw]	

;	edge_t	*edge, *pcheck;
;	int		u_check;
;	float	u, u_step;
;	vec3_t	local, transformed;
;	float	*world;
;	int		v, v2, ceilv0;
;	float	scale, lzi0, u0, v0;
;	int		side;

;	if (r_lastvertvalid)
;	{
 cmp ds:dword ptr[_r_lastvertvalid],0	
 jz LCalcFirst	

;		u0 = r_u1;
;		v0 = r_v1;
;		lzi0 = r_lzi1;
;		ceilv0 = r_ceilv1;
 mov eax,ds:dword ptr[_r_lzi1]	
 mov ecx,ds:dword ptr[_r_u1]	
 mov ds:dword ptr[Lzi0],eax	
 mov ds:dword ptr[Lu0],ecx	
 mov ecx,ds:dword ptr[_r_v1]	
 mov eax,ds:dword ptr[_r_ceilv1]	
 mov ds:dword ptr[Lv0],ecx	
 mov ds:dword ptr[Lceilv0],eax	
 jmp LCalcSecond	

;	}

LCalcFirst:	

;	else
;	{
;		world = &pv0->position[0];

 call near ptr LTransformAndProject	; v0 | lzi0 | u0

 fst ds:dword ptr[Lv0]	
 fxch st(2)	; u0 | lzi0 | v0
 fstp ds:dword ptr[Lu0]	; lzi0 | v0
 fstp ds:dword ptr[Lzi0]	; v0

;		ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
 fistp ds:dword ptr[Lceilv0]	

;	}

LCalcSecond:	

;	world = &pv1->position[0];
 mov esi,edx	

 call near ptr LTransformAndProject	; v1 | lzi1 | u1

 fld ds:dword ptr[Lu0]	; u0 | v1 | lzi1 | u1
 fxch st(3)	; u1 | v1 | lzi1 | u0
 fld ds:dword ptr[Lzi0]	; lzi0 | u1 | v1 | lzi1 | u0
 fxch st(3)	; lzi1 | u1 | v1 | lzi0 | u0
 fld ds:dword ptr[Lv0]	; v0 | lzi1 | u1 | v1 | lzi0 | u0
 fxch st(3)	; v1 | lzi1 | u1 | v0 | lzi0 | u0

;	r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
 fist ds:dword ptr[_r_ceilv1]	

 fldcw ds:word ptr[_fpu_chop_cw]	; put back normal floating-point state

 fst ds:dword ptr[_r_v1]	
 fxch st(4)	; lzi0 | lzi1 | u1 | v0 | v1 | u0

;	if (r_lzi1 > lzi0)
;		lzi0 = r_lzi1;
 fcom st(1)	
 fnstsw ax	
 test ah,1	
 jz LP0	
 fstp st(0)	
 fld st(0)	
LP0:	

 fxch st(1)	; lzi1 | lzi0 | u1 | v0 | v1 | u0
 fstp ds:dword ptr[_r_lzi1]	; lzi0 | u1 | v0 | v1 | u0
 fxch st(1)	
 fst ds:dword ptr[_r_u1]	
 fxch st(1)	

;	if (lzi0 > r_nearzi)	// for mipmap finding
;		r_nearzi = lzi0;
 fcom ds:dword ptr[_r_nearzi]	
 fnstsw ax	
 test ah,045h	
 jnz LP1	
 fst ds:dword ptr[_r_nearzi]	
LP1:	

; // for right edges, all we want is the effect on 1/z
;	if (r_nearzionly)
;		return;
 mov eax,ds:dword ptr[_r_nearzionly]	
 test eax,eax	
 jz LP2	
LPop5AndDone:	
 mov eax,ds:dword ptr[_cacheoffset]	
 mov edx,ds:dword ptr[_r_framecount]	
 cmp eax,07FFFFFFFh	
 jz LDoPop	
 and edx,offset FRAMECOUNT_MASK	
 or edx,offset FULLY_CLIPPED_CACHED	
 mov ds:dword ptr[_cacheoffset],edx	

LDoPop:	
 fstp st(0)	; u1 | v0 | v1 | u0
 fstp st(0)	; v0 | v1 | u0
 fstp st(0)	; v1 | u0
 fstp st(0)	; u0
 fstp st(0)	
 jmp Ldone	

LP2:	

; // create the edge
;	if (ceilv0 == r_ceilv1)
;		return;		// horizontal edge
 mov ebx,ds:dword ptr[Lceilv0]	
 mov edi,ds:dword ptr[_edge_p]	
 mov ecx,ds:dword ptr[_r_ceilv1]	
 mov edx,edi	
 mov esi,ds:dword ptr[_r_pedge]	
 add edx,offset et_size	
 cmp ebx,ecx	
 jz LPop5AndDone	

 mov eax,ds:dword ptr[_r_pedge]	
 mov ds:dword ptr[et_owner+edi],eax	

;	side = ceilv0 > r_ceilv1;
;
;	edge->nearzi = lzi0;
 fstp ds:dword ptr[et_nearzi+edi]	; u1 | v0 | v1 | u0

;	if (side == 1)
;	{
 jc LSide0	

LSide1:	

;	// leading edge (go from p2 to p1)

;		u_step = ((u0 - r_u1) / (v0 - r_v1));
 fsubp st(3),st(0)	; v0 | v1 | u0-u1
 fsub st(0),st(1)	; v0-v1 | v1 | u0-u1
 fdivp st(2),st(0)	; v1 | ustep

;	r_emitted = 1;
 mov ds:dword ptr[_r_emitted],1	

;	edge = edge_p++;
 mov ds:dword ptr[_edge_p],edx	

; pretouch next edge
 mov eax,ds:dword ptr[edx]	

;		v2 = ceilv0 - 1;
;		v = r_ceilv1;
 mov eax,ecx	
 lea ecx,ds:dword ptr[-1+ebx]	
 mov ebx,eax	

;		edge->surfs[0] = 0;
;		edge->surfs[1] = surface_p - surfaces;
 mov eax,ds:dword ptr[_surface_p]	
 mov esi,ds:dword ptr[_surfaces]	
 sub edx,edx	
 sub eax,esi	
 shr eax,offset SURF_T_SHIFT	
 mov ds:dword ptr[et_surfs+edi],edx	
 mov ds:dword ptr[et_surfs+2+edi],eax	

 sub esi,esi	

;		u = r_u1 + ((float)v - r_v1) * u_step;
 mov ds:dword ptr[Lv],ebx	
 fild ds:dword ptr[Lv]	; v | v1 | ustep
 fsubrp st(1),st(0)	; v-v1 | ustep
 fmul st(0),st(1)	; (v-v1)*ustep | ustep
 fadd ds:dword ptr[_r_u1]	; u | ustep

 jmp LSideDone	

;	}

LSide0:	

;	else
;	{
;	// trailing edge (go from p1 to p2)

;		u_step = ((r_u1 - u0) / (r_v1 - v0));
 fsub st(0),st(3)	; u1-u0 | v0 | v1 | u0
 fxch st(2)	; v1 | v0 | u1-u0 | u0
 fsub st(0),st(1)	; v1-v0 | v0 | u1-u0 | u0
 fdivp st(2),st(0)	; v0 | ustep | u0

;	r_emitted = 1;
 mov ds:dword ptr[_r_emitted],1	

;	edge = edge_p++;
 mov ds:dword ptr[_edge_p],edx	

; pretouch next edge
 mov eax,ds:dword ptr[edx]	

;		v = ceilv0;
;		v2 = r_ceilv1 - 1;
 dec ecx	

;		edge->surfs[0] = surface_p - surfaces;
;		edge->surfs[1] = 0;
 mov eax,ds:dword ptr[_surface_p]	
 mov esi,ds:dword ptr[_surfaces]	
 sub edx,edx	
 sub eax,esi	
 shr eax,offset SURF_T_SHIFT	
 mov ds:dword ptr[et_surfs+2+edi],edx	
 mov ds:dword ptr[et_surfs+edi],eax	

 mov esi,1	

;		u = u0 + ((float)v - v0) * u_step;
 mov ds:dword ptr[Lv],ebx	
 fild ds:dword ptr[Lv]	; v | v0 | ustep | u0
 fsubrp st(1),st(0)	; v-v0 | ustep | u0
 fmul st(0),st(1)	; (v-v0)*ustep | ustep | u0
 faddp st(2),st(0)	; ustep | u
 fxch st(1)	; u | ustep

;	}

LSideDone:	

;	edge->u_step = u_step*0x100000;
;	edge->u = u*0x100000 + 0xFFFFF;

 fmul ds:dword ptr[fp_1m]	; u*0x100000 | ustep
 fxch st(1)	; ustep | u*0x100000
 fmul ds:dword ptr[fp_1m]	; ustep*0x100000 | u*0x100000
 fxch st(1)	; u*0x100000 | ustep*0x100000
 fadd ds:dword ptr[fp_1m_minus_1]	; u*0x100000 + 0xFFFFF | ustep*0x100000
 fxch st(1)	; ustep*0x100000 | u*0x100000 + 0xFFFFF
 fistp ds:dword ptr[et_u_step+edi]	; u*0x100000 + 0xFFFFF
 fistp ds:dword ptr[et_u+edi]	

; // we need to do this to avoid stepping off the edges if a very nearly
; // horizontal edge is less than epsilon above a scan, and numeric error
; // causes it to incorrectly extend to the scan, and the extension of the
; // line goes off the edge of the screen
; // FIXME: is this actually needed?
;	if (edge->u < r_refdef.vrect_x_adj_shift20)
;		edge->u = r_refdef.vrect_x_adj_shift20;
;	if (edge->u > r_refdef.vrectright_adj_shift20)
;		edge->u = r_refdef.vrectright_adj_shift20;
 mov eax,ds:dword ptr[et_u+edi]	
 mov edx,ds:dword ptr[_r_refdef+rd_vrect_x_adj_shift20]	
 cmp eax,edx	
 jl LP4	
 mov edx,ds:dword ptr[_r_refdef+rd_vrectright_adj_shift20]	
 cmp eax,edx	
 jng LP5	
LP4:	
 mov ds:dword ptr[et_u+edi],edx	
 mov eax,edx	
LP5:	

; // sort the edge in normally
;	u_check = edge->u;
;
;	if (edge->surfs[0])
;		u_check++;	// sort trailers after leaders
 add eax,esi	

;	if (!newedges[v] || newedges[v]->u >= u_check)
;	{
 mov esi,ds:dword ptr[_newedges+ebx*4]	
 test esi,esi	

⌨️ 快捷键说明

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