diff --git a/AUTHORS b/AUTHORS index 4c6702f..81e2c9e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -20,3 +20,6 @@ Maintance of 3Dfx support: Maintance of the keyboard stuff: Zephaniah E. Hull + +Pointing out more common files: + Marcus Sundberg diff --git a/common/r_aclipa.s b/common/r_aclipa.s new file mode 100644 index 0000000..aee9837 --- /dev/null +++ b/common/r_aclipa.s @@ -0,0 +1,216 @@ +/* +Copyright (C) 1996-1997 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. + +*/ +// +// r_aliasa.s +// x86 assembly-language Alias model transform and project code. +// + +#include "asm_i386.h" +#include "quakeasm.h" +#include "asm_draw.h" +#include "d_ifacea.h" + +#if id386 + + .data +Ltemp0: .long 0 +Ltemp1: .long 0 + + .text + +#define pfv0 8+4 +#define pfv1 8+8 +#define out 8+12 + +.globl C(R_Alias_clip_bottom) +C(R_Alias_clip_bottom): + pushl %esi + pushl %edi + + movl pfv0(%esp),%esi + movl pfv1(%esp),%edi + + movl C(r_refdef)+rd_aliasvrectbottom,%eax + +LDoForwardOrBackward: + + movl fv_v+4(%esi),%edx + movl fv_v+4(%edi),%ecx + + cmpl %ecx,%edx + jl LDoForward + + movl fv_v+4(%esi),%ecx + movl fv_v+4(%edi),%edx + movl pfv0(%esp),%edi + movl pfv1(%esp),%esi + +LDoForward: + + subl %edx,%ecx + subl %edx,%eax + movl %ecx,Ltemp1 + movl %eax,Ltemp0 + fildl Ltemp1 + fildl Ltemp0 + movl out(%esp),%edx + movl $2,%eax + + fdivp %st(0),%st(1) // scale + +LDo3Forward: + fildl fv_v+0(%esi) // fv0v0 | scale + fildl fv_v+0(%edi) // fv1v0 | fv0v0 | scale + fildl fv_v+4(%esi) // fv0v1 | fv1v0 | fv0v0 | scale + fildl fv_v+4(%edi) // fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale + fildl fv_v+8(%esi) // fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale + fildl fv_v+8(%edi) // fv1v2 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 | + // scale + fxch %st(5) // fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv1v2 | + // scale + fsubr %st(0),%st(4) // fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0-fv0v0 | + // fv1v2 | scale + fxch %st(3) // fv0v1 | fv0v2 | fv1v1 | fv0v0 | fv1v0-fv0v0 | + // fv1v2 | scale + fsubr %st(0),%st(2) // fv0v1 | fv0v2 | fv1v1-fv0v1 | fv0v0 | + // fv1v0-fv0v0 | fv1v2 | scale + fxch %st(1) // fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 | + // fv1v0-fv0v0 | fv1v2 | scale + fsubr %st(0),%st(5) // fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 | + // fv1v0-fv0v0 | fv1v2-fv0v2 | scale + fxch %st(6) // scale | fv0v1 | fv1v1-fv0v1 | fv0v0 | + // fv1v0-fv0v0 | fv1v2-fv0v2 | fv0v2 + fmul %st(0),%st(4) // scale | fv0v1 | fv1v1-fv0v1 | fv0v0 | + // (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2 + addl $12,%edi + fmul %st(0),%st(2) // scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 | + // (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2 + addl $12,%esi + addl $12,%edx + fmul %st(0),%st(5) // scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 | + // (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale | + // fv0v2 + fxch %st(3) // fv0v0 | fv0v1 | (fv1v1-fv0v1)*scale | scale | + // (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale | + // fv0v2 + faddp %st(0),%st(4) // fv0v1 | (fv1v1-fv0v1)*scale | scale | + // fv0v0+(fv1v0-fv0v0)*scale | + // (fv1v2-fv0v2)*scale | fv0v2 + faddp %st(0),%st(1) // fv0v1+(fv1v1-fv0v1)*scale | scale | + // fv0v0+(fv1v0-fv0v0)*scale | + // (fv1v2-fv0v2)*scale | fv0v2 + fxch %st(4) // fv0v2 | scale | fv0v0+(fv1v0-fv0v0)*scale | + // (fv1v2-fv0v2)*scale | fv0v1+(fv1v1-fv0v1)*scale + faddp %st(0),%st(3) // scale | fv0v0+(fv1v0-fv0v0)*scale | + // fv0v2+(fv1v2-fv0v2)*scale | + // fv0v1+(fv1v1-fv0v1)*scale + fxch %st(1) // fv0v0+(fv1v0-fv0v0)*scale | scale | + // fv0v2+(fv1v2-fv0v2)*scale | + // fv0v1+(fv1v1-fv0v1)*scale + fadds float_point5 + fxch %st(3) // fv0v1+(fv1v1-fv0v1)*scale | scale | + // fv0v2+(fv1v2-fv0v2)*scale | + // fv0v0+(fv1v0-fv0v0)*scale + fadds float_point5 + fxch %st(2) // fv0v2+(fv1v2-fv0v2)*scale | scale | + // fv0v1+(fv1v1-fv0v1)*scale | + // fv0v0+(fv1v0-fv0v0)*scale + fadds float_point5 + fxch %st(3) // fv0v0+(fv1v0-fv0v0)*scale | scale | + // fv0v1+(fv1v1-fv0v1)*scale | + // fv0v2+(fv1v2-fv0v2)*scale + fistpl fv_v+0-12(%edx) // scale | fv0v1+(fv1v1-fv0v1)*scale | + // fv0v2+(fv1v2-fv0v2)*scale + fxch %st(1) // fv0v1+(fv1v1-fv0v1)*scale | scale | + // fv0v2+(fv1v2-fv0v2)*scale | scale + fistpl fv_v+4-12(%edx) // scale | fv0v2+(fv1v2-fv0v2)*scale + fxch %st(1) // fv0v2+(fv1v2-fv0v2)*sc | scale + fistpl fv_v+8-12(%edx) // scale + + decl %eax + jnz LDo3Forward + + fstp %st(0) + + popl %edi + popl %esi + + ret + + +.globl C(R_Alias_clip_top) +C(R_Alias_clip_top): + pushl %esi + pushl %edi + + movl pfv0(%esp),%esi + movl pfv1(%esp),%edi + + movl C(r_refdef)+rd_aliasvrect+4,%eax + jmp LDoForwardOrBackward + + + +.globl C(R_Alias_clip_right) +C(R_Alias_clip_right): + pushl %esi + pushl %edi + + movl pfv0(%esp),%esi + movl pfv1(%esp),%edi + + movl C(r_refdef)+rd_aliasvrectright,%eax + +LRightLeftEntry: + + + movl fv_v+4(%esi),%edx + movl fv_v+4(%edi),%ecx + + cmpl %ecx,%edx + movl fv_v+0(%esi),%edx + + movl fv_v+0(%edi),%ecx + jl LDoForward2 + + movl fv_v+0(%esi),%ecx + movl fv_v+0(%edi),%edx + movl pfv0(%esp),%edi + movl pfv1(%esp),%esi + +LDoForward2: + + jmp LDoForward + + +.globl C(R_Alias_clip_left) +C(R_Alias_clip_left): + pushl %esi + pushl %edi + + movl pfv0(%esp),%esi + movl pfv1(%esp),%edi + + movl C(r_refdef)+rd_aliasvrect+0,%eax + jmp LRightLeftEntry + + +#endif // id386 + diff --git a/common/r_aliasa.s b/common/r_aliasa.s new file mode 100644 index 0000000..b19e97a --- /dev/null +++ b/common/r_aliasa.s @@ -0,0 +1,237 @@ +/* +Copyright (C) 1996-1997 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. + +*/ +// +// r_aliasa.s +// x86 assembly-language Alias model transform and project code. +// + +#include "asm_i386.h" +#include "quakeasm.h" +#include "asm_draw.h" +#include "d_ifacea.h" + +#if id386 + + .data + +Lfloat_1: .single 1.0 +Ltemp: .long 0 +Lcoords: .long 0, 0, 0 + + .text + +#define fv 12+4 +#define pstverts 12+8 + +.globl C(R_AliasTransformAndProjectFinalVerts) +C(R_AliasTransformAndProjectFinalVerts): + pushl %ebp // preserve caller's stack frame + pushl %edi + pushl %esi // preserve register variables + +// int i, temp; +// float lightcos, *plightnormal, zi; +// trivertx_t *pverts; + +// pverts = r_apverts; + movl C(r_apverts),%esi + +// for (i=0 ; iv, aliastransform[2]) + +// aliastransform[2][3]); + movb (%esi),%dl + movb %dl,Lcoords + fildl Lcoords // v[0] + movb 1(%esi),%dl + movb %dl,Lcoords+4 + fildl Lcoords+4 // v[1] | v[0] + movb 2(%esi),%dl + movb %dl,Lcoords+8 + fildl Lcoords+8 // v[2] | v[1] | v[0] + + fld %st(2) // v[0] | v[2] | v[1] | v[0] + fmuls C(aliastransform)+32 // accum | v[2] | v[1] | v[0] + fld %st(2) // v[1] | accum | v[2] | v[1] | v[0] + fmuls C(aliastransform)+36 // accum2 | accum | v[2] | v[1] | v[0] + fxch %st(1) // accum | accum2 | v[2] | v[1] | v[0] + fadds C(aliastransform)+44 // accum | accum2 | v[2] | v[1] | v[0] + fld %st(2) // v[2] | accum | accum2 | v[2] | v[1] | v[0] + fmuls C(aliastransform)+40 // accum3 | accum | accum2 | v[2] | v[1] | + // v[0] + fxch %st(1) // accum | accum3 | accum2 | v[2] | v[1] | v[0] + faddp %st(0),%st(2) // accum3 | accum | v[2] | v[1] | v[0] + movb tv_lightnormalindex(%esi),%dl + movl stv_s(%ebp),%eax + movl %eax,fv_v+8(%edi) + faddp %st(0),%st(1) // z | v[2] | v[1] | v[0] + + movl stv_t(%ebp),%eax + movl %eax,fv_v+12(%edi) + +// // lighting +// plightnormal = r_avertexnormals[pverts->lightnormalindex]; + + fdivrs Lfloat_1 // zi | v[2] | v[1] | v[0] + +// fv->v[2] = pstverts->s; +// fv->v[3] = pstverts->t; +// fv->flags = pstverts->onseam; + movl stv_onseam(%ebp),%eax + movl %eax,fv_flags(%edi) + + movl fv_size(%edi),%eax + movl stv_size(%ebp),%eax + movl 4(%esi),%eax + + leal (%edx,%edx,2),%eax // index*3 + + fxch %st(3) // v[0] | v[2] | v[1] | zi + +// lightcos = DotProduct (plightnormal, r_plightvec); + flds C(r_avertexnormals)(,%eax,4) + fmuls C(r_plightvec) + flds C(r_avertexnormals)+4(,%eax,4) + fmuls C(r_plightvec)+4 + flds C(r_avertexnormals)+8(,%eax,4) + fmuls C(r_plightvec)+8 + fxch %st(1) + faddp %st(0),%st(2) + fld %st(2) // v[0] | laccum | laccum2 | v[0] | v[2] | + // v[1] | zi + fmuls C(aliastransform)+0 // xaccum | laccum | laccum2 | v[0] | v[2] | + // v[1] | zi + fxch %st(2) // laccum2 | laccum | xaccum | v[0] | v[2] | + // v[1] | zi + faddp %st(0),%st(1) // laccum | xaccum | v[0] | v[2] | v[1] | zi + +// temp = r_ambientlight; +// if (lightcos < 0) +// { + fsts Ltemp + movl C(r_ambientlight),%eax + movb Ltemp+3,%dl + testb $0x80,%dl + jz Lsavelight // no need to clamp if only ambient lit, because + // r_ambientlight is preclamped + +// temp += (int)(r_shadelight * lightcos); + fmuls C(r_shadelight) +// FIXME: fast float->int conversion? + fistpl Ltemp + addl Ltemp,%eax + +// // clamp; because we limited the minimum ambient and shading light, we +// // don't have to clamp low light, just bright +// if (temp < 0) +// temp = 0; + jns Lp1 + subl %eax,%eax + +// } + +Lp1: + +// fv->v[4] = temp; +// +// // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is +// // scaled up by 1/2**31, and the scaling cancels out for x and y in the +// // projection +// fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) + +// aliastransform[0][3]) * zi) + aliasxcenter; +// fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) + +// aliastransform[1][3]) * zi) + aliasycenter; +// fv->v[5] = zi; + fxch %st(1) // v[0] | xaccum | v[2] | v[1] | zi + fmuls C(aliastransform)+16 // yaccum | xaccum | v[2] | v[1] | zi + fxch %st(3) // v[1] | xaccum | v[2] | yaccum | zi + fld %st(0) // v[1] | v[1] | xaccum | v[2] | yaccum | zi + fmuls C(aliastransform)+4 // xaccum2 | v[1] | xaccum | v[2] | yaccum |zi + fxch %st(1) // v[1] | xaccum2 | xaccum | v[2] | yaccum |zi + movl %eax,fv_v+16(%edi) + fmuls C(aliastransform)+20 // yaccum2 | xaccum2 | xaccum | v[2] | yaccum| + // zi + fxch %st(2) // xaccum | xaccum2 | yaccum2 | v[2] | yaccum| + // zi + fadds C(aliastransform)+12 // xaccum | xaccum2 | yaccum2 | v[2] | yaccum| + // zi + fxch %st(4) // yaccum | xaccum2 | yaccum2 | v[2] | xaccum| + // zi + fadds C(aliastransform)+28 // yaccum | xaccum2 | yaccum2 | v[2] | xaccum| + // zi + fxch %st(3) // v[2] | xaccum2 | yaccum2 | yaccum | xaccum| + // zi + fld %st(0) // v[2] | v[2] | xaccum2 | yaccum2 | yaccum | + // xaccum | zi + fmuls C(aliastransform)+8 // xaccum3 | v[2] | xaccum2 | yaccum2 |yaccum| + // xaccum | zi + fxch %st(1) // v[2] | xaccum3 | xaccum2 | yaccum2 |yaccum| + // xaccum | zi + fmuls C(aliastransform)+24 // yaccum3 | xaccum3 | xaccum2 | yaccum2 | + // yaccum | xaccum | zi + fxch %st(5) // xaccum | xaccum3 | xaccum2 | yaccum2 | + // yaccum | yaccum3 | zi + faddp %st(0),%st(2) // xaccum3 | xaccum | yaccum2 | yaccum | + // yaccum3 | zi + fxch %st(3) // yaccum | xaccum | yaccum2 | xaccum3 | + // yaccum3 | zi + faddp %st(0),%st(2) // xaccum | yaccum | xaccum3 | yaccum3 | zi + addl $(tv_size),%esi + faddp %st(0),%st(2) // yaccum | x | yaccum3 | zi + faddp %st(0),%st(2) // x | y | zi + addl $(stv_size),%ebp + fmul %st(2),%st(0) // x/z | y | zi + fxch %st(1) // y | x/z | zi + fmul %st(2),%st(0) // y/z | x/z | zi + fxch %st(1) // x/z | y/z | zi + fadds C(aliasxcenter) // u | y/z | zi + fxch %st(1) // y/z | u | zi + fadds C(aliasycenter) // v | u | zi + fxch %st(2) // zi | u | v +// FIXME: fast float->int conversion? + fistpl fv_v+20(%edi) // u | v + fistpl fv_v+0(%edi) // v + fistpl fv_v+4(%edi) + +// } + + addl $(fv_size),%edi + decl %ecx + jnz Lloop + + popl %esi // restore register variables + popl %edi + popl %ebp // restore the caller's stack frame + ret + +Lsavelight: + fstp %st(0) + jmp Lp1 + +#endif // id386 + diff --git a/common/r_drawa.s b/common/r_drawa.s new file mode 100644 index 0000000..3cb2239 --- /dev/null +++ b/common/r_drawa.s @@ -0,0 +1,838 @@ +/* +Copyright (C) 1996-1997 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. + +*/ +// +// r_drawa.s +// x86 assembly-language edge clipping and emission code +// + +#include "asm_i386.h" +#include "quakeasm.h" +#include "asm_draw.h" +#include "d_ifacea.h" + +#if id386 + +// !!! if these are changed, they must be changed in r_draw.c too !!! +#define FULLY_CLIPPED_CACHED 0x80000000 +#define FRAMECOUNT_MASK 0x7FFFFFFF + + .data + +Ld0: .single 0.0 +Ld1: .single 0.0 +Lstack: .long 0 +Lfp_near_clip: .single NEAR_CLIP +Lceilv0: .long 0 +Lv: .long 0 +Lu0: .long 0 +Lv0: .long 0 +Lzi0: .long 0 + + .text + +//---------------------------------------------------------------------- +// edge clipping code +//---------------------------------------------------------------------- + +#define pv0 4+12 +#define pv1 8+12 +#define clip 12+12 + + .align 4 +.globl C(R_ClipEdge) +C(R_ClipEdge): + pushl %esi // preserve register variables + pushl %edi + pushl %ebx + movl %esp,Lstack // for clearing the stack later + +// float d0, d1, f; +// mvertex_t clipvert; + + movl clip(%esp),%ebx + movl pv0(%esp),%esi + movl pv1(%esp),%edx + +// if (clip) +// { + testl %ebx,%ebx + jz Lemit + +// do +// { + +Lcliploop: + +// d0 = DotProduct (pv0->position, clip->normal) - clip->dist; +// d1 = DotProduct (pv1->position, clip->normal) - clip->dist; + flds mv_position+0(%esi) + fmuls cp_normal+0(%ebx) + flds mv_position+4(%esi) + fmuls cp_normal+4(%ebx) + flds mv_position+8(%esi) + fmuls cp_normal+8(%ebx) + fxch %st(1) + faddp %st(0),%st(2) // d0mul2 | d0add0 + + flds mv_position+0(%edx) + fmuls cp_normal+0(%ebx) + flds mv_position+4(%edx) + fmuls cp_normal+4(%ebx) + flds mv_position+8(%edx) + fmuls cp_normal+8(%ebx) + fxch %st(1) + faddp %st(0),%st(2) // d1mul2 | d1add0 | d0mul2 | d0add0 + fxch %st(3) // d0add0 | d1add0 | d0mul2 | d1mul2 + + faddp %st(0),%st(2) // d1add0 | dot0 | d1mul2 + faddp %st(0),%st(2) // dot0 | dot1 + + fsubs cp_dist(%ebx) // d0 | dot1 + fxch %st(1) // dot1 | d0 + fsubs cp_dist(%ebx) // d1 | d0 + fxch %st(1) + fstps Ld0 + fstps Ld1 + +// if (d0 >= 0) +// { + movl Ld0,%eax + movl Ld1,%ecx + orl %eax,%ecx + js Lp2 + +// both points are unclipped + +Lcontinue: + +// +// R_ClipEdge (&clipvert, pv1, clip->next); +// return; +// } +// } while ((clip = clip->next) != NULL); + movl cp_next(%ebx),%ebx + testl %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 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) +// { + cmpl $0,C(r_lastvertvalid) + jz LCalcFirst + +// u0 = r_u1; +// v0 = r_v1; +// lzi0 = r_lzi1; +// ceilv0 = r_ceilv1; + movl C(r_lzi1),%eax + movl C(r_u1),%ecx + movl %eax,Lzi0 + movl %ecx,Lu0 + movl C(r_v1),%ecx + movl C(r_ceilv1),%eax + movl %ecx,Lv0 + movl %eax,Lceilv0 + jmp LCalcSecond + +// } + +LCalcFirst: + +// else +// { +// world = &pv0->position[0]; + + call LTransformAndProject // v0 | lzi0 | u0 + + fsts Lv0 + fxch %st(2) // u0 | lzi0 | v0 + fstps Lu0 // lzi0 | v0 + fstps Lzi0 // v0 + +// ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0); + fistpl Lceilv0 + +// } + +LCalcSecond: + +// world = &pv1->position[0]; + movl %edx,%esi + + call LTransformAndProject // v1 | lzi1 | u1 + + flds Lu0 // u0 | v1 | lzi1 | u1 + fxch %st(3) // u1 | v1 | lzi1 | u0 + flds Lzi0 // lzi0 | u1 | v1 | lzi1 | u0 + fxch %st(3) // lzi1 | u1 | v1 | lzi0 | u0 + flds 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); + fistl C(r_ceilv1) + + fldcw single_cw // put back normal floating-point state + + fsts C(r_v1) + fxch %st(4) // lzi0 | lzi1 | u1 | v0 | v1 | u0 + +// if (r_lzi1 > lzi0) +// lzi0 = r_lzi1; + fcom %st(1) + fnstsw %ax + testb $1,%ah + jz LP0 + fstp %st(0) + fld %st(0) +LP0: + + fxch %st(1) // lzi1 | lzi0 | u1 | v0 | v1 | u0 + fstps C(r_lzi1) // lzi0 | u1 | v0 | v1 | u0 + fxch %st(1) + fsts C(r_u1) + fxch %st(1) + +// if (lzi0 > r_nearzi) // for mipmap finding +// r_nearzi = lzi0; + fcoms C(r_nearzi) + fnstsw %ax + testb $0x45,%ah + jnz LP1 + fsts C(r_nearzi) +LP1: + +// // for right edges, all we want is the effect on 1/z +// if (r_nearzionly) +// return; + movl C(r_nearzionly),%eax + testl %eax,%eax + jz LP2 +LPop5AndDone: + movl C(cacheoffset),%eax + movl C(r_framecount),%edx + cmpl $0x7FFFFFFF,%eax + jz LDoPop + andl $(FRAMECOUNT_MASK),%edx + orl $(FULLY_CLIPPED_CACHED),%edx + movl %edx,C(cacheoffset) + +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 + movl Lceilv0,%ebx + movl C(edge_p),%edi + movl C(r_ceilv1),%ecx + movl %edi,%edx + movl C(r_pedge),%esi + addl $(et_size),%edx + cmpl %ecx,%ebx + jz LPop5AndDone + + movl C(r_pedge),%eax + movl %eax,et_owner(%edi) + +// side = ceilv0 > r_ceilv1; +// +// edge->nearzi = lzi0; + fstps 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)); + fsubrp %st(0),%st(3) // v0 | v1 | u0-u1 + fsub %st(1),%st(0) // v0-v1 | v1 | u0-u1 + fdivrp %st(0),%st(2) // v1 | ustep + +// r_emitted = 1; + movl $1,C(r_emitted) + +// edge = edge_p++; + movl %edx,C(edge_p) + +// pretouch next edge + movl (%edx),%eax + +// v2 = ceilv0 - 1; +// v = r_ceilv1; + movl %ecx,%eax + leal -1(%ebx),%ecx + movl %eax,%ebx + +// edge->surfs[0] = 0; +// edge->surfs[1] = surface_p - surfaces; + movl C(surface_p),%eax + movl C(surfaces),%esi + subl %edx,%edx + subl %esi,%eax + shrl $(SURF_T_SHIFT),%eax + movl %edx,et_surfs(%edi) + movl %eax,et_surfs+2(%edi) + + subl %esi,%esi + +// u = r_u1 + ((float)v - r_v1) * u_step; + movl %ebx,Lv + fildl Lv // v | v1 | ustep + fsubp %st(0),%st(1) // v-v1 | ustep + fmul %st(1),%st(0) // (v-v1)*ustep | ustep + fadds C(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(3),%st(0) // u1-u0 | v0 | v1 | u0 + fxch %st(2) // v1 | v0 | u1-u0 | u0 + fsub %st(1),%st(0) // v1-v0 | v0 | u1-u0 | u0 + fdivrp %st(0),%st(2) // v0 | ustep | u0 + +// r_emitted = 1; + movl $1,C(r_emitted) + +// edge = edge_p++; + movl %edx,C(edge_p) + +// pretouch next edge + movl (%edx),%eax + +// v = ceilv0; +// v2 = r_ceilv1 - 1; + decl %ecx + +// edge->surfs[0] = surface_p - surfaces; +// edge->surfs[1] = 0; + movl C(surface_p),%eax + movl C(surfaces),%esi + subl %edx,%edx + subl %esi,%eax + shrl $(SURF_T_SHIFT),%eax + movl %edx,et_surfs+2(%edi) + movl %eax,et_surfs(%edi) + + movl $1,%esi + +// u = u0 + ((float)v - v0) * u_step; + movl %ebx,Lv + fildl Lv // v | v0 | ustep | u0 + fsubp %st(0),%st(1) // v-v0 | ustep | u0 + fmul %st(1),%st(0) // (v-v0)*ustep | ustep | u0 + faddp %st(0),%st(2) // ustep | u + fxch %st(1) // u | ustep + +// } + +LSideDone: + +// edge->u_step = u_step*0x100000; +// edge->u = u*0x100000 + 0xFFFFF; + + fmuls fp_1m // u*0x100000 | ustep + fxch %st(1) // ustep | u*0x100000 + fmuls fp_1m // ustep*0x100000 | u*0x100000 + fxch %st(1) // u*0x100000 | ustep*0x100000 + fadds fp_1m_minus_1 // u*0x100000 + 0xFFFFF | ustep*0x100000 + fxch %st(1) // ustep*0x100000 | u*0x100000 + 0xFFFFF + fistpl et_u_step(%edi) // u*0x100000 + 0xFFFFF + fistpl 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; + movl et_u(%edi),%eax + movl C(r_refdef)+rd_vrect_x_adj_shift20,%edx + cmpl %edx,%eax + jl LP4 + movl C(r_refdef)+rd_vrectright_adj_shift20,%edx + cmpl %edx,%eax + jng LP5 +LP4: + movl %edx,et_u(%edi) + movl %edx,%eax +LP5: + +// // sort the edge in normally +// u_check = edge->u; +// +// if (edge->surfs[0]) +// u_check++; // sort trailers after leaders + addl %esi,%eax + +// if (!newedges[v] || newedges[v]->u >= u_check) +// { + movl C(newedges)(,%ebx,4),%esi + testl %esi,%esi + jz LDoFirst + cmpl %eax,et_u(%esi) + jl LNotFirst +LDoFirst: + +// edge->next = newedges[v]; +// newedges[v] = edge; + movl %esi,et_next(%edi) + movl %edi,C(newedges)(,%ebx,4) + + jmp LSetRemove + +// } + +LNotFirst: + +// else +// { +// pcheck = newedges[v]; +// +// while (pcheck->next && pcheck->next->u < u_check) +// pcheck = pcheck->next; +LFindInsertLoop: + movl %esi,%edx + movl et_next(%esi),%esi + testl %esi,%esi + jz LInsertFound + cmpl %eax,et_u(%esi) + jl LFindInsertLoop + +LInsertFound: + +// edge->next = pcheck->next; +// pcheck->next = edge; + movl %esi,et_next(%edi) + movl %edi,et_next(%edx) + +// } + +LSetRemove: + +// edge->nextremove = removeedges[v2]; +// removeedges[v2] = edge; + movl C(removeedges)(,%ecx,4),%eax + movl %edi,C(removeedges)(,%ecx,4) + movl %eax,et_nextremove(%edi) + +Ldone: + movl Lstack,%esp // clear temporary variables from stack + + popl %ebx // restore register variables + popl %edi + popl %esi + ret + +// at least one point is clipped + +Lp2: + testl %eax,%eax + jns Lp1 + +// else +// { +// // point 0 is clipped + +// if (d1 < 0) +// { + movl Ld1,%eax + testl %eax,%eax + jns Lp3 + +// // both points are clipped +// // we do cache fully clipped edges +// if (!leftclipped) + movl C(r_leftclipped),%eax + movl C(r_pedge),%ecx + testl %eax,%eax + jnz Ldone + +// r_pedge->framecount = r_framecount; + movl C(r_framecount),%eax + andl $(FRAMECOUNT_MASK),%eax + orl $(FULLY_CLIPPED_CACHED),%eax + movl %eax,C(cacheoffset) + +// return; + jmp Ldone + +// } + +Lp1: + +// // point 0 is unclipped +// if (d1 >= 0) +// { +// // both points are unclipped +// continue; + +// // only point 1 is clipped + +// f = d0 / (d0 - d1); + flds Ld0 + flds Ld1 + fsubr %st(1),%st(0) + +// // we don't cache partially clipped edges + movl $0x7FFFFFFF,C(cacheoffset) + + fdivrp %st(0),%st(1) + + subl $(mv_size),%esp // allocate space for clipvert + +// clipvert.position[0] = pv0->position[0] + +// f * (pv1->position[0] - pv0->position[0]); +// clipvert.position[1] = pv0->position[1] + +// f * (pv1->position[1] - pv0->position[1]); +// clipvert.position[2] = pv0->position[2] + +// f * (pv1->position[2] - pv0->position[2]); + flds mv_position+8(%edx) + fsubs mv_position+8(%esi) + flds mv_position+4(%edx) + fsubs mv_position+4(%esi) + flds mv_position+0(%edx) + fsubs mv_position+0(%esi) // 0 | 1 | 2 + +// replace pv1 with the clip point + movl %esp,%edx + movl cp_leftedge(%ebx),%eax + testb %al,%al + + fmul %st(3),%st(0) + fxch %st(1) // 1 | 0 | 2 + fmul %st(3),%st(0) + fxch %st(2) // 2 | 0 | 1 + fmulp %st(0),%st(3) // 0 | 1 | 2 + fadds mv_position+0(%esi) + fxch %st(1) // 1 | 0 | 2 + fadds mv_position+4(%esi) + fxch %st(2) // 2 | 0 | 1 + fadds mv_position+8(%esi) + fxch %st(1) // 0 | 2 | 1 + fstps mv_position+0(%esp) // 2 | 1 + fstps mv_position+8(%esp) // 1 + fstps mv_position+4(%esp) + +// if (clip->leftedge) +// { + jz Ltestright + +// r_leftclipped = true; +// r_leftexit = clipvert; + movl $1,C(r_leftclipped) + movl mv_position+0(%esp),%eax + movl %eax,C(r_leftexit)+mv_position+0 + movl mv_position+4(%esp),%eax + movl %eax,C(r_leftexit)+mv_position+4 + movl mv_position+8(%esp),%eax + movl %eax,C(r_leftexit)+mv_position+8 + + jmp Lcontinue + +// } + +Ltestright: +// else if (clip->rightedge) +// { + testb %ah,%ah + jz Lcontinue + +// r_rightclipped = true; +// r_rightexit = clipvert; + movl $1,C(r_rightclipped) + movl mv_position+0(%esp),%eax + movl %eax,C(r_rightexit)+mv_position+0 + movl mv_position+4(%esp),%eax + movl %eax,C(r_rightexit)+mv_position+4 + movl mv_position+8(%esp),%eax + movl %eax,C(r_rightexit)+mv_position+8 + +// } +// +// R_ClipEdge (pv0, &clipvert, clip->next); +// return; +// } + jmp Lcontinue + +// } + +Lp3: + +// // only point 0 is clipped +// r_lastvertvalid = false; + + movl $0,C(r_lastvertvalid) + +// f = d0 / (d0 - d1); + flds Ld0 + flds Ld1 + fsubr %st(1),%st(0) + +// // we don't cache partially clipped edges + movl $0x7FFFFFFF,C(cacheoffset) + + fdivrp %st(0),%st(1) + + subl $(mv_size),%esp // allocate space for clipvert + +// clipvert.position[0] = pv0->position[0] + +// f * (pv1->position[0] - pv0->position[0]); +// clipvert.position[1] = pv0->position[1] + +// f * (pv1->position[1] - pv0->position[1]); +// clipvert.position[2] = pv0->position[2] + +// f * (pv1->position[2] - pv0->position[2]); + flds mv_position+8(%edx) + fsubs mv_position+8(%esi) + flds mv_position+4(%edx) + fsubs mv_position+4(%esi) + flds mv_position+0(%edx) + fsubs mv_position+0(%esi) // 0 | 1 | 2 + + movl cp_leftedge(%ebx),%eax + testb %al,%al + + fmul %st(3),%st(0) + fxch %st(1) // 1 | 0 | 2 + fmul %st(3),%st(0) + fxch %st(2) // 2 | 0 | 1 + fmulp %st(0),%st(3) // 0 | 1 | 2 + fadds mv_position+0(%esi) + fxch %st(1) // 1 | 0 | 2 + fadds mv_position+4(%esi) + fxch %st(2) // 2 | 0 | 1 + fadds mv_position+8(%esi) + fxch %st(1) // 0 | 2 | 1 + fstps mv_position+0(%esp) // 2 | 1 + fstps mv_position+8(%esp) // 1 + fstps mv_position+4(%esp) + +// replace pv0 with the clip point + movl %esp,%esi + +// if (clip->leftedge) +// { + jz Ltestright2 + +// r_leftclipped = true; +// r_leftenter = clipvert; + movl $1,C(r_leftclipped) + movl mv_position+0(%esp),%eax + movl %eax,C(r_leftenter)+mv_position+0 + movl mv_position+4(%esp),%eax + movl %eax,C(r_leftenter)+mv_position+4 + movl mv_position+8(%esp),%eax + movl %eax,C(r_leftenter)+mv_position+8 + + jmp Lcontinue + +// } + +Ltestright2: +// else if (clip->rightedge) +// { + testb %ah,%ah + jz Lcontinue + +// r_rightclipped = true; +// r_rightenter = clipvert; + movl $1,C(r_rightclipped) + movl mv_position+0(%esp),%eax + movl %eax,C(r_rightenter)+mv_position+0 + movl mv_position+4(%esp),%eax + movl %eax,C(r_rightenter)+mv_position+4 + movl mv_position+8(%esp),%eax + movl %eax,C(r_rightenter)+mv_position+8 + +// } + jmp Lcontinue + +// %esi = vec3_t point to transform and project +// %edx preserved +LTransformAndProject: + +// // transform and project +// VectorSubtract (world, modelorg, local); + flds mv_position+0(%esi) + fsubs C(modelorg)+0 + flds mv_position+4(%esi) + fsubs C(modelorg)+4 + flds mv_position+8(%esi) + fsubs C(modelorg)+8 + fxch %st(2) // local[0] | local[1] | local[2] + +// TransformVector (local, transformed); +// +// if (transformed[2] < NEAR_CLIP) +// transformed[2] = NEAR_CLIP; +// +// lzi0 = 1.0 / transformed[2]; + fld %st(0) // local[0] | local[0] | local[1] | local[2] + fmuls C(vpn)+0 // zm0 | local[0] | local[1] | local[2] + fld %st(1) // local[0] | zm0 | local[0] | local[1] | + // local[2] + fmuls C(vright)+0 // xm0 | zm0 | local[0] | local[1] | local[2] + fxch %st(2) // local[0] | zm0 | xm0 | local[1] | local[2] + fmuls C(vup)+0 // ym0 | zm0 | xm0 | local[1] | local[2] + fld %st(3) // local[1] | ym0 | zm0 | xm0 | local[1] | + // local[2] + fmuls C(vpn)+4 // zm1 | ym0 | zm0 | xm0 | local[1] | + // local[2] + fld %st(4) // local[1] | zm1 | ym0 | zm0 | xm0 | + // local[1] | local[2] + fmuls C(vright)+4 // xm1 | zm1 | ym0 | zm0 | xm0 | + // local[1] | local[2] + fxch %st(5) // local[1] | zm1 | ym0 | zm0 | xm0 | + // xm1 | local[2] + fmuls C(vup)+4 // ym1 | zm1 | ym0 | zm0 | xm0 | + // xm1 | local[2] + fxch %st(1) // zm1 | ym1 | ym0 | zm0 | xm0 | + // xm1 | local[2] + faddp %st(0),%st(3) // ym1 | ym0 | zm2 | xm0 | xm1 | local[2] + fxch %st(3) // xm0 | ym0 | zm2 | ym1 | xm1 | local[2] + faddp %st(0),%st(4) // ym0 | zm2 | ym1 | xm2 | local[2] + faddp %st(0),%st(2) // zm2 | ym2 | xm2 | local[2] + fld %st(3) // local[2] | zm2 | ym2 | xm2 | local[2] + fmuls C(vpn)+8 // zm3 | zm2 | ym2 | xm2 | local[2] + fld %st(4) // local[2] | zm3 | zm2 | ym2 | xm2 | local[2] + fmuls C(vright)+8 // xm3 | zm3 | zm2 | ym2 | xm2 | local[2] + fxch %st(5) // local[2] | zm3 | zm2 | ym2 | xm2 | xm3 + fmuls C(vup)+8 // ym3 | zm3 | zm2 | ym2 | xm2 | xm3 + fxch %st(1) // zm3 | ym3 | zm2 | ym2 | xm2 | xm3 + faddp %st(0),%st(2) // ym3 | zm4 | ym2 | xm2 | xm3 + fxch %st(4) // xm3 | zm4 | ym2 | xm2 | ym3 + faddp %st(0),%st(3) // zm4 | ym2 | xm4 | ym3 + fxch %st(1) // ym2 | zm4 | xm4 | ym3 + faddp %st(0),%st(3) // zm4 | xm4 | ym4 + + fcoms Lfp_near_clip + fnstsw %ax + testb $1,%ah + jz LNoClip + fstp %st(0) + flds Lfp_near_clip + +LNoClip: + + fdivrs float_1 // lzi0 | x | y + fxch %st(1) // x | lzi0 | y + +// // FIXME: build x/yscale into transform? +// scale = xscale * lzi0; +// u0 = (xcenter + scale*transformed[0]); + flds C(xscale) // xscale | x | lzi0 | y + fmul %st(2),%st(0) // scale | x | lzi0 | y + fmulp %st(0),%st(1) // scale*x | lzi0 | y + fadds C(xcenter) // u0 | lzi0 | y + +// if (u0 < r_refdef.fvrectx_adj) +// u0 = r_refdef.fvrectx_adj; +// if (u0 > r_refdef.fvrectright_adj) +// u0 = r_refdef.fvrectright_adj; +// FIXME: use integer compares of floats? + fcoms C(r_refdef)+rd_fvrectx_adj + fnstsw %ax + testb $1,%ah + jz LClampP0 + fstp %st(0) + flds C(r_refdef)+rd_fvrectx_adj +LClampP0: + fcoms C(r_refdef)+rd_fvrectright_adj + fnstsw %ax + testb $0x45,%ah + jnz LClampP1 + fstp %st(0) + flds C(r_refdef)+rd_fvrectright_adj +LClampP1: + + fld %st(1) // lzi0 | u0 | lzi0 | y + +// scale = yscale * lzi0; +// v0 = (ycenter - scale*transformed[1]); + fmuls C(yscale) // scale | u0 | lzi0 | y + fmulp %st(0),%st(3) // u0 | lzi0 | scale*y + fxch %st(2) // scale*y | lzi0 | u0 + fsubrs C(ycenter) // v0 | lzi0 | u0 + +// if (v0 < r_refdef.fvrecty_adj) +// v0 = r_refdef.fvrecty_adj; +// if (v0 > r_refdef.fvrectbottom_adj) +// v0 = r_refdef.fvrectbottom_adj; +// FIXME: use integer compares of floats? + fcoms C(r_refdef)+rd_fvrecty_adj + fnstsw %ax + testb $1,%ah + jz LClampP2 + fstp %st(0) + flds C(r_refdef)+rd_fvrecty_adj +LClampP2: + fcoms C(r_refdef)+rd_fvrectbottom_adj + fnstsw %ax + testb $0x45,%ah + jnz LClampP3 + fstp %st(0) + flds C(r_refdef)+rd_fvrectbottom_adj +LClampP3: + ret + +#endif // id386 + diff --git a/common/r_edgea.s b/common/r_edgea.s new file mode 100644 index 0000000..f67130f --- /dev/null +++ b/common/r_edgea.s @@ -0,0 +1,750 @@ +/* +Copyright (C) 1996-1997 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. + +*/ +// +// r_edgea.s +// x86 assembly-language edge-processing code. +// + +#include "asm_i386.h" +#include "quakeasm.h" +#include "asm_draw.h" + +#if id386 + + .data +Ltemp: .long 0 +float_1_div_0100000h: .long 0x35800000 // 1.0/(float)0x100000 +float_point_999: .single 0.999 +float_1_point_001: .single 1.001 + + .text + +//-------------------------------------------------------------------- + +#define edgestoadd 4+8 // note odd stack offsets because of interleaving +#define edgelist 8+12 // with pushes + +.globl C(R_EdgeCodeStart) +C(R_EdgeCodeStart): + +.globl C(R_InsertNewEdges) +C(R_InsertNewEdges): + pushl %edi + pushl %esi // preserve register variables + movl edgestoadd(%esp),%edx + pushl %ebx + movl edgelist(%esp),%ecx + +LDoNextEdge: + movl et_u(%edx),%eax + movl %edx,%edi + +LContinueSearch: + movl et_u(%ecx),%ebx + movl et_next(%ecx),%esi + cmpl %ebx,%eax + jle LAddedge + movl et_u(%esi),%ebx + movl et_next(%esi),%ecx + cmpl %ebx,%eax + jle LAddedge2 + movl et_u(%ecx),%ebx + movl et_next(%ecx),%esi + cmpl %ebx,%eax + jle LAddedge + movl et_u(%esi),%ebx + movl et_next(%esi),%ecx + cmpl %ebx,%eax + jg LContinueSearch + +LAddedge2: + movl et_next(%edx),%edx + movl et_prev(%esi),%ebx + movl %esi,et_next(%edi) + movl %ebx,et_prev(%edi) + movl %edi,et_next(%ebx) + movl %edi,et_prev(%esi) + movl %esi,%ecx + + cmpl $0,%edx + jnz LDoNextEdge + jmp LDone + + .align 4 +LAddedge: + movl et_next(%edx),%edx + movl et_prev(%ecx),%ebx + movl %ecx,et_next(%edi) + movl %ebx,et_prev(%edi) + movl %edi,et_next(%ebx) + movl %edi,et_prev(%ecx) + + cmpl $0,%edx + jnz LDoNextEdge + +LDone: + popl %ebx // restore register variables + popl %esi + popl %edi + + ret + +//-------------------------------------------------------------------- + +#define predge 4+4 + +.globl C(R_RemoveEdges) +C(R_RemoveEdges): + pushl %ebx + movl predge(%esp),%eax + +Lre_loop: + movl et_next(%eax),%ecx + movl et_nextremove(%eax),%ebx + movl et_prev(%eax),%edx + testl %ebx,%ebx + movl %edx,et_prev(%ecx) + jz Lre_done + movl %ecx,et_next(%edx) + + movl et_next(%ebx),%ecx + movl et_prev(%ebx),%edx + movl et_nextremove(%ebx),%eax + movl %edx,et_prev(%ecx) + testl %eax,%eax + movl %ecx,et_next(%edx) + jnz Lre_loop + + popl %ebx + ret + +Lre_done: + movl %ecx,et_next(%edx) + popl %ebx + + ret + +//-------------------------------------------------------------------- + +#define pedgelist 4+4 // note odd stack offset because of interleaving + // with pushes + +.globl C(R_StepActiveU) +C(R_StepActiveU): + pushl %edi + movl pedgelist(%esp),%edx + pushl %esi // preserve register variables + pushl %ebx + + movl et_prev(%edx),%esi + +LNewEdge: + movl et_u(%esi),%edi + +LNextEdge: + movl et_u(%edx),%eax + movl et_u_step(%edx),%ebx + addl %ebx,%eax + movl et_next(%edx),%esi + movl %eax,et_u(%edx) + cmpl %edi,%eax + jl LPushBack + + movl et_u(%esi),%edi + movl et_u_step(%esi),%ebx + addl %ebx,%edi + movl et_next(%esi),%edx + movl %edi,et_u(%esi) + cmpl %eax,%edi + jl LPushBack2 + + movl et_u(%edx),%eax + movl et_u_step(%edx),%ebx + addl %ebx,%eax + movl et_next(%edx),%esi + movl %eax,et_u(%edx) + cmpl %edi,%eax + jl LPushBack + + movl et_u(%esi),%edi + movl et_u_step(%esi),%ebx + addl %ebx,%edi + movl et_next(%esi),%edx + movl %edi,et_u(%esi) + cmpl %eax,%edi + jnl LNextEdge + +LPushBack2: + movl %edx,%ebx + movl %edi,%eax + movl %esi,%edx + movl %ebx,%esi + +LPushBack: +// push it back to keep it sorted + movl et_prev(%edx),%ecx + movl et_next(%edx),%ebx + +// done if the -1 in edge_aftertail triggered this + cmpl $(C(edge_aftertail)),%edx + jz LUDone + +// pull the edge out of the edge list + movl et_prev(%ecx),%edi + movl %ecx,et_prev(%esi) + movl %ebx,et_next(%ecx) + +// find out where the edge goes in the edge list +LPushBackLoop: + movl et_prev(%edi),%ecx + movl et_u(%edi),%ebx + cmpl %ebx,%eax + jnl LPushBackFound + + movl et_prev(%ecx),%edi + movl et_u(%ecx),%ebx + cmpl %ebx,%eax + jl LPushBackLoop + + movl %ecx,%edi + +// put the edge back into the edge list +LPushBackFound: + movl et_next(%edi),%ebx + movl %edi,et_prev(%edx) + movl %ebx,et_next(%edx) + movl %edx,et_next(%edi) + movl %edx,et_prev(%ebx) + + movl %esi,%edx + movl et_prev(%esi),%esi + + cmpl $(C(edge_tail)),%edx + jnz LNewEdge + +LUDone: + popl %ebx // restore register variables + popl %esi + popl %edi + + ret + +//-------------------------------------------------------------------- + +#define surf 4 // note this is loaded before any pushes + + .align 4 +TrailingEdge: + movl st_spanstate(%esi),%eax // check for edge inversion + decl %eax + jnz LInverted + + movl %eax,st_spanstate(%esi) + movl st_insubmodel(%esi),%ecx + movl 0x12345678,%edx // surfaces[1].st_next +LPatch0: + movl C(r_bmodelactive),%eax + subl %ecx,%eax + cmpl %esi,%edx + movl %eax,C(r_bmodelactive) + jnz LNoEmit // surface isn't on top, just remove + +// emit a span (current top going away) + movl et_u(%ebx),%eax + shrl $20,%eax // iu = integral pixel u + movl st_last_u(%esi),%edx + movl st_next(%esi),%ecx + cmpl %edx,%eax + jle LNoEmit2 // iu <= surf->last_u, so nothing to emit + + movl %eax,st_last_u(%ecx) // surf->next->last_u = iu; + subl %edx,%eax + movl %edx,espan_t_u(%ebp) // span->u = surf->last_u; + + movl %eax,espan_t_count(%ebp) // span->count = iu - span->u; + movl C(current_iv),%eax + movl %eax,espan_t_v(%ebp) // span->v = current_iv; + movl st_spans(%esi),%eax + movl %eax,espan_t_pnext(%ebp) // span->pnext = surf->spans; + movl %ebp,st_spans(%esi) // surf->spans = span; + addl $(espan_t_size),%ebp + + movl st_next(%esi),%edx // remove the surface from the surface + movl st_prev(%esi),%esi // stack + + movl %edx,st_next(%esi) + movl %esi,st_prev(%edx) + ret + +LNoEmit2: + movl %eax,st_last_u(%ecx) // surf->next->last_u = iu; + movl st_next(%esi),%edx // remove the surface from the surface + movl st_prev(%esi),%esi // stack + + movl %edx,st_next(%esi) + movl %esi,st_prev(%edx) + ret + +LNoEmit: + movl st_next(%esi),%edx // remove the surface from the surface + movl st_prev(%esi),%esi // stack + + movl %edx,st_next(%esi) + movl %esi,st_prev(%edx) + ret + +LInverted: + movl %eax,st_spanstate(%esi) + ret + +//-------------------------------------------------------------------- + +// trailing edge only +Lgs_trailing: + pushl $Lgs_nextedge + jmp TrailingEdge + + +.globl C(R_GenerateSpans) +C(R_GenerateSpans): + pushl %ebp // preserve caller's stack frame + pushl %edi + pushl %esi // preserve register variables + pushl %ebx + +// clear active surfaces to just the background surface + movl C(surfaces),%eax + movl C(edge_head_u_shift20),%edx + addl $(st_size),%eax +// %ebp = span_p throughout + movl C(span_p),%ebp + + movl $0,C(r_bmodelactive) + + movl %eax,st_next(%eax) + movl %eax,st_prev(%eax) + movl %edx,st_last_u(%eax) + movl C(edge_head)+et_next,%ebx // edge=edge_head.next + +// generate spans + cmpl $(C(edge_tail)),%ebx // done if empty list + jz Lgs_lastspan + +Lgs_edgeloop: + + movl et_surfs(%ebx),%edi + movl C(surfaces),%eax + movl %edi,%esi + andl $0xFFFF0000,%edi + andl $0xFFFF,%esi + jz Lgs_leading // not a trailing edge + +// it has a left surface, so a surface is going away for this span + shll $(SURF_T_SHIFT),%esi + addl %eax,%esi + testl %edi,%edi + jz Lgs_trailing + +// both leading and trailing + call TrailingEdge + movl C(surfaces),%eax + +// --------------------------------------------------------------- +// handle a leading edge +// --------------------------------------------------------------- + +Lgs_leading: + shrl $16-SURF_T_SHIFT,%edi + movl C(surfaces),%eax + addl %eax,%edi + movl 0x12345678,%esi // surf2 = surfaces[1].next; +LPatch2: + movl st_spanstate(%edi),%edx + movl st_insubmodel(%edi),%eax + testl %eax,%eax + jnz Lbmodel_leading + +// handle a leading non-bmodel edge + +// don't start a span if this is an inverted span, with the end edge preceding +// the start edge (that is, we've already seen the end edge) + testl %edx,%edx + jnz Lxl_done + + +// if (surf->key < surf2->key) +// goto newtop; + incl %edx + movl st_key(%edi),%eax + movl %edx,st_spanstate(%edi) + movl st_key(%esi),%ecx + cmpl %ecx,%eax + jl Lnewtop + +// main sorting loop to search through surface stack until insertion point +// found. Always terminates because background surface is sentinel +// do +// { +// surf2 = surf2->next; +// } while (surf->key >= surf2->key); +Lsortloopnb: + movl st_next(%esi),%esi + movl st_key(%esi),%ecx + cmpl %ecx,%eax + jge Lsortloopnb + + jmp LInsertAndExit + + +// handle a leading bmodel edge + .align 4 +Lbmodel_leading: + +// don't start a span if this is an inverted span, with the end edge preceding +// the start edge (that is, we've already seen the end edge) + testl %edx,%edx + jnz Lxl_done + + movl C(r_bmodelactive),%ecx + incl %edx + incl %ecx + movl %edx,st_spanstate(%edi) + movl %ecx,C(r_bmodelactive) + +// if (surf->key < surf2->key) +// goto newtop; + movl st_key(%edi),%eax + movl st_key(%esi),%ecx + cmpl %ecx,%eax + jl Lnewtop + +// if ((surf->key == surf2->key) && surf->insubmodel) +// { + jz Lzcheck_for_newtop + +// main sorting loop to search through surface stack until insertion point +// found. Always terminates because background surface is sentinel +// do +// { +// surf2 = surf2->next; +// } while (surf->key > surf2->key); +Lsortloop: + movl st_next(%esi),%esi + movl st_key(%esi),%ecx + cmpl %ecx,%eax + jg Lsortloop + + jne LInsertAndExit + +// Do 1/z sorting to see if we've arrived in the right position + movl et_u(%ebx),%eax + subl $0xFFFFF,%eax + movl %eax,Ltemp + fildl Ltemp + + fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) * + // (1.0 / 0x100000); + + fld %st(0) // fu | fu + fmuls st_d_zistepu(%edi) // fu*surf->d_zistepu | fu + flds C(fv) // fv | fu*surf->d_zistepu | fu + fmuls st_d_zistepv(%edi) // fv*surf->d_zistepv | fu*surf->d_zistepu | fu + fxch %st(1) // fu*surf->d_zistepu | fv*surf->d_zistepv | fu + fadds st_d_ziorigin(%edi) // fu*surf->d_zistepu + surf->d_ziorigin | + // fv*surf->d_zistepv | fu + + flds st_d_zistepu(%esi) // surf2->d_zistepu | + // fu*surf->d_zistepu + surf->d_ziorigin | + // fv*surf->d_zistepv | fu + fmul %st(3),%st(0) // fu*surf2->d_zistepu | + // fu*surf->d_zistepu + surf->d_ziorigin | + // fv*surf->d_zistepv | fu + fxch %st(1) // fu*surf->d_zistepu + surf->d_ziorigin | + // fu*surf2->d_zistepu | + // fv*surf->d_zistepv | fu + faddp %st(0),%st(2) // fu*surf2->d_zistepu | newzi | fu + + flds C(fv) // fv | fu*surf2->d_zistepu | newzi | fu + fmuls st_d_zistepv(%esi) // fv*surf2->d_zistepv | + // fu*surf2->d_zistepu | newzi | fu + fld %st(2) // newzi | fv*surf2->d_zistepv | + // fu*surf2->d_zistepu | newzi | fu + fmuls float_point_999 // newzibottom | fv*surf2->d_zistepv | + // fu*surf2->d_zistepu | newzi | fu + + fxch %st(2) // fu*surf2->d_zistepu | fv*surf2->d_zistepv | + // newzibottom | newzi | fu + fadds st_d_ziorigin(%esi) // fu*surf2->d_zistepu + surf2->d_ziorigin | + // fv*surf2->d_zistepv | newzibottom | newzi | + // fu + faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu + fxch %st(1) // newzibottom | testzi | newzi | fu + +// if (newzibottom >= testzi) +// goto Lgotposition; + + fcomp %st(1) // testzi | newzi | fu + + fxch %st(1) // newzi | testzi | fu + fmuls float_1_point_001 // newzitop | testzi | fu + fxch %st(1) // testzi | newzitop | fu + + fnstsw %ax + testb $0x01,%ah + jz Lgotposition_fpop3 + +// if (newzitop >= testzi) +// { + + fcomp %st(1) // newzitop | fu + fnstsw %ax + testb $0x45,%ah + jz Lsortloop_fpop2 + +// if (surf->d_zistepu >= surf2->d_zistepu) +// goto newtop; + + flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop| fu + fcomps st_d_zistepu(%esi) // newzitop | fu + fnstsw %ax + testb $0x01,%ah + jz Lgotposition_fpop2 + + fstp %st(0) // clear the FPstack + fstp %st(0) + movl st_key(%edi),%eax + jmp Lsortloop + + +Lgotposition_fpop3: + fstp %st(0) +Lgotposition_fpop2: + fstp %st(0) + fstp %st(0) + jmp LInsertAndExit + + +// emit a span (obscures current top) + +Lnewtop_fpop3: + fstp %st(0) +Lnewtop_fpop2: + fstp %st(0) + fstp %st(0) + movl st_key(%edi),%eax // reload the sorting key + +Lnewtop: + movl et_u(%ebx),%eax + movl st_last_u(%esi),%edx + shrl $20,%eax // iu = integral pixel u + movl %eax,st_last_u(%edi) // surf->last_u = iu; + cmpl %edx,%eax + jle LInsertAndExit // iu <= surf->last_u, so nothing to emit + + subl %edx,%eax + movl %edx,espan_t_u(%ebp) // span->u = surf->last_u; + + movl %eax,espan_t_count(%ebp) // span->count = iu - span->u; + movl C(current_iv),%eax + movl %eax,espan_t_v(%ebp) // span->v = current_iv; + movl st_spans(%esi),%eax + movl %eax,espan_t_pnext(%ebp) // span->pnext = surf->spans; + movl %ebp,st_spans(%esi) // surf->spans = span; + addl $(espan_t_size),%ebp + +LInsertAndExit: +// insert before surf2 + movl %esi,st_next(%edi) // surf->next = surf2; + movl st_prev(%esi),%eax + movl %eax,st_prev(%edi) // surf->prev = surf2->prev; + movl %edi,st_prev(%esi) // surf2->prev = surf; + movl %edi,st_next(%eax) // surf2->prev->next = surf; + +// --------------------------------------------------------------- +// leading edge done +// --------------------------------------------------------------- + +// --------------------------------------------------------------- +// see if there are any more edges +// --------------------------------------------------------------- + +Lgs_nextedge: + movl et_next(%ebx),%ebx + cmpl $(C(edge_tail)),%ebx + jnz Lgs_edgeloop + +// clean up at the right edge +Lgs_lastspan: + +// now that we've reached the right edge of the screen, we're done with any +// unfinished surfaces, so emit a span for whatever's on top + movl 0x12345678,%esi // surfaces[1].st_next +LPatch3: + movl C(edge_tail_u_shift20),%eax + xorl %ecx,%ecx + movl st_last_u(%esi),%edx + subl %edx,%eax + jle Lgs_resetspanstate + + movl %edx,espan_t_u(%ebp) + movl %eax,espan_t_count(%ebp) + movl C(current_iv),%eax + movl %eax,espan_t_v(%ebp) + movl st_spans(%esi),%eax + movl %eax,espan_t_pnext(%ebp) + movl %ebp,st_spans(%esi) + addl $(espan_t_size),%ebp + +// reset spanstate for all surfaces in the surface stack +Lgs_resetspanstate: + movl %ecx,st_spanstate(%esi) + movl st_next(%esi),%esi + cmpl $0x12345678,%esi // &surfaces[1] +LPatch4: + jnz Lgs_resetspanstate + +// store the final span_p + movl %ebp,C(span_p) + + popl %ebx // restore register variables + popl %esi + popl %edi + popl %ebp // restore the caller's stack frame + ret + + +// --------------------------------------------------------------- +// 1/z sorting for bmodels in the same leaf +// --------------------------------------------------------------- + .align 4 +Lxl_done: + incl %edx + movl %edx,st_spanstate(%edi) + + jmp Lgs_nextedge + + + .align 4 +Lzcheck_for_newtop: + movl et_u(%ebx),%eax + subl $0xFFFFF,%eax + movl %eax,Ltemp + fildl Ltemp + + fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) * + // (1.0 / 0x100000); + + fld %st(0) // fu | fu + fmuls st_d_zistepu(%edi) // fu*surf->d_zistepu | fu + flds C(fv) // fv | fu*surf->d_zistepu | fu + fmuls st_d_zistepv(%edi) // fv*surf->d_zistepv | fu*surf->d_zistepu | fu + fxch %st(1) // fu*surf->d_zistepu | fv*surf->d_zistepv | fu + fadds st_d_ziorigin(%edi) // fu*surf->d_zistepu + surf->d_ziorigin | + // fv*surf->d_zistepv | fu + + flds st_d_zistepu(%esi) // surf2->d_zistepu | + // fu*surf->d_zistepu + surf->d_ziorigin | + // fv*surf->d_zistepv | fu + fmul %st(3),%st(0) // fu*surf2->d_zistepu | + // fu*surf->d_zistepu + surf->d_ziorigin | + // fv*surf->d_zistepv | fu + fxch %st(1) // fu*surf->d_zistepu + surf->d_ziorigin | + // fu*surf2->d_zistepu | + // fv*surf->d_zistepv | fu + faddp %st(0),%st(2) // fu*surf2->d_zistepu | newzi | fu + + flds C(fv) // fv | fu*surf2->d_zistepu | newzi | fu + fmuls st_d_zistepv(%esi) // fv*surf2->d_zistepv | + // fu*surf2->d_zistepu | newzi | fu + fld %st(2) // newzi | fv*surf2->d_zistepv | + // fu*surf2->d_zistepu | newzi | fu + fmuls float_point_999 // newzibottom | fv*surf2->d_zistepv | + // fu*surf2->d_zistepu | newzi | fu + + fxch %st(2) // fu*surf2->d_zistepu | fv*surf2->d_zistepv | + // newzibottom | newzi | fu + fadds st_d_ziorigin(%esi) // fu*surf2->d_zistepu + surf2->d_ziorigin | + // fv*surf2->d_zistepv | newzibottom | newzi | + // fu + faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu + fxch %st(1) // newzibottom | testzi | newzi | fu + +// if (newzibottom >= testzi) +// goto newtop; + + fcomp %st(1) // testzi | newzi | fu + + fxch %st(1) // newzi | testzi | fu + fmuls float_1_point_001 // newzitop | testzi | fu + fxch %st(1) // testzi | newzitop | fu + + fnstsw %ax + testb $0x01,%ah + jz Lnewtop_fpop3 + +// if (newzitop >= testzi) +// { + + fcomp %st(1) // newzitop | fu + fnstsw %ax + testb $0x45,%ah + jz Lsortloop_fpop2 + +// if (surf->d_zistepu >= surf2->d_zistepu) +// goto newtop; + + flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop | fu + fcomps st_d_zistepu(%esi) // newzitop | fu + fnstsw %ax + testb $0x01,%ah + jz Lnewtop_fpop2 + +Lsortloop_fpop2: + fstp %st(0) // clear the FP stack + fstp %st(0) + movl st_key(%edi),%eax + jmp Lsortloop + + +.globl C(R_EdgeCodeEnd) +C(R_EdgeCodeEnd): + + +//---------------------------------------------------------------------- +// Surface array address code patching routine +//---------------------------------------------------------------------- + + .align 4 +.globl C(R_SurfacePatch) +C(R_SurfacePatch): + + movl C(surfaces),%eax + addl $(st_size),%eax + movl %eax,LPatch4-4 + + addl $(st_next),%eax + movl %eax,LPatch0-4 + movl %eax,LPatch2-4 + movl %eax,LPatch3-4 + + ret + +#endif // id386 + diff --git a/common/r_light.c b/common/r_light.c new file mode 100644 index 0000000..f735d50 --- /dev/null +++ b/common/r_light.c @@ -0,0 +1,260 @@ +/* +Copyright (C) 1996-1997 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. + +*/ +// r_light.c + +#include "quakedef.h" +#include "r_local.h" + +int r_dlightframecount; + + +/* +================== +R_AnimateLight +================== +*/ +void R_AnimateLight (void) +{ + int i,j,k; + +// +// light animations +// 'm' is normal light, 'a' is no light, 'z' is double bright + i = (int)(cl.time*10); + for (j=0 ; jcontents < 0) + return; + + splitplane = node->plane; + dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; + + if (dist > light->radius) + { + R_MarkLights (light, bit, node->children[0]); + return; + } + if (dist < -light->radius) + { + R_MarkLights (light, bit, node->children[1]); + return; + } + +// mark the polygons + surf = cl.worldmodel->surfaces + node->firstsurface; + for (i=0 ; inumsurfaces ; i++, surf++) + { + if (surf->dlightframe != r_dlightframecount) + { + surf->dlightbits = 0; + surf->dlightframe = r_dlightframecount; + } + surf->dlightbits |= bit; + } + + R_MarkLights (light, bit, node->children[0]); + R_MarkLights (light, bit, node->children[1]); +} + + +/* +============= +R_PushDlights +============= +*/ +void R_PushDlights (void) +{ + int i; + dlight_t *l; + + r_dlightframecount = r_framecount + 1; // because the count hasn't + // advanced yet for this frame + l = cl_dlights; + + for (i=0 ; idie < cl.time || !l->radius) + continue; + R_MarkLights ( l, 1<nodes ); + } +} + + +/* +============================================================================= + +LIGHT SAMPLING + +============================================================================= +*/ + +int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) +{ + int r; + float front, back, frac; + int side; + mplane_t *plane; + vec3_t mid; + msurface_t *surf; + int s, t, ds, dt; + int i; + mtexinfo_t *tex; + byte *lightmap; + unsigned scale; + int maps; + + if (node->contents < 0) + return -1; // didn't hit anything + +// calculate mid point + +// FIXME: optimize for axial + plane = node->plane; + front = DotProduct (start, plane->normal) - plane->dist; + back = DotProduct (end, plane->normal) - plane->dist; + side = front < 0; + + if ( (back < 0) == side) + return RecursiveLightPoint (node->children[side], start, end); + + frac = front / (front-back); + mid[0] = start[0] + (end[0] - start[0])*frac; + mid[1] = start[1] + (end[1] - start[1])*frac; + mid[2] = start[2] + (end[2] - start[2])*frac; + +// go down front side + r = RecursiveLightPoint (node->children[side], start, mid); + if (r >= 0) + return r; // hit something + + if ( (back < 0) == side ) + return -1; // didn't hit anuthing + +// check for impact on this node + + surf = cl.worldmodel->surfaces + node->firstsurface; + for (i=0 ; inumsurfaces ; i++, surf++) + { + if (surf->flags & SURF_DRAWTILED) + continue; // no lightmaps + + tex = surf->texinfo; + + s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; + t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; + + if (s < surf->texturemins[0] || + t < surf->texturemins[1]) + continue; + + ds = s - surf->texturemins[0]; + dt = t - surf->texturemins[1]; + + if ( ds > surf->extents[0] || dt > surf->extents[1] ) + continue; + + if (!surf->samples) + return 0; + + ds >>= 4; + dt >>= 4; + + lightmap = surf->samples; + r = 0; + if (lightmap) + { + + lightmap += dt * ((surf->extents[0]>>4)+1) + ds; + + for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; + maps++) + { + scale = d_lightstylevalue[surf->styles[maps]]; + r += *lightmap * scale; + lightmap += ((surf->extents[0]>>4)+1) * + ((surf->extents[1]>>4)+1); + } + + r >>= 8; + } + + return r; + } + +// go down back side + return RecursiveLightPoint (node->children[!side], mid, end); +} + +int R_LightPoint (vec3_t p) +{ + vec3_t end; + int r; + + if (!cl.worldmodel->lightdata) + return 255; + + end[0] = p[0]; + end[1] = p[1]; + end[2] = p[2] - 2048; + + r = RecursiveLightPoint (cl.worldmodel->nodes, p, end); + + if (r == -1) + r = 0; + + if (r < r_refdef.ambientlight) + r = r_refdef.ambientlight; + + return r; +} + diff --git a/common/r_sky.c b/common/r_sky.c new file mode 100644 index 0000000..c8bfffd --- /dev/null +++ b/common/r_sky.c @@ -0,0 +1,280 @@ +/* +Copyright (C) 1996-1997 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. + +*/ +// r_sky.c + +#include "quakedef.h" +#include "r_local.h" +#include "d_local.h" + + +int iskyspeed = 8; +int iskyspeed2 = 2; +float skyspeed, skyspeed2; + +float skytime; + +byte *r_skysource; + +int r_skymade; +int r_skydirect; // not used? + + +// TODO: clean up these routines + +byte bottomsky[128*131]; +byte bottommask[128*131]; +byte newsky[128*256]; // newsky and topsky both pack in here, 128 bytes + // of newsky on the left of each scan, 128 bytes + // of topsky on the right, because the low-level + // drawers need 256-byte scan widths + + +/* +============= +R_InitSky + +A sky texture is 256*128, with the right side being a masked overlay +============== +*/ +void R_InitSky (texture_t *mt) +{ + int i, j; + byte *src; + + src = (byte *)mt + mt->offsets[0]; + + for (i=0 ; i<128 ; i++) + { + for (j=0 ; j<128 ; j++) + { + newsky[(i*256) + j + 128] = src[i*256 + j + 128]; + } + } + + for (i=0 ; i<128 ; i++) + { + for (j=0 ; j<131 ; j++) + { + if (src[i*256 + (j & 0x7F)]) + { + bottomsky[(i*131) + j] = src[i*256 + (j & 0x7F)]; + bottommask[(i*131) + j] = 0; + } + else + { + bottomsky[(i*131) + j] = 0; + bottommask[(i*131) + j] = 0xff; + } + } + } + + r_skysource = newsky; +} + + +/* +================= +R_MakeSky +================= +*/ +void R_MakeSky (void) +{ + int x, y; + int ofs, baseofs; + int xshift, yshift; + unsigned *pnewsky; + static int xlast = -1, ylast = -1; + + xshift = skytime*skyspeed; + yshift = skytime*skyspeed; + + if ((xshift == xlast) && (yshift == ylast)) + return; + + xlast = xshift; + ylast = yshift; + + pnewsky = (unsigned *)&newsky[0]; + + for (y=0 ; y> blockdivshift; +// lightrightstep = (lightptr[1] - lightright) >> blockdivshift; +// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) | +// 0xF0000000; + movl 4(%ebx),%ecx // lightptr[1] + movl (%ebx),%ebx // lightptr[0] + + subl %eax,%ebx + subl %edx,%ecx + + sarl $4,%ecx + orl $0xF0000000,%ebp + + sarl $4,%ebx + movl %ecx,C(lightrightstep) + + subl %ecx,%ebx + andl $0xFFFFF,%ebx + + orl $0xF0000000,%ebx + subl %ecx,%ecx // high word must be 0 in loop for addressing + + movl %ebx,C(lightdeltastep) + subl %ebx,%ebx // high word must be 0 in loop for addressing + +Lblockloop8_mip0: + movl %ebp,C(lightdelta) + movb 14(%esi),%cl + + sarl $4,%ebp + movb %dh,%bh + + movb 15(%esi),%bl + addl %ebp,%edx + + movb %dh,%ch + addl %ebp,%edx + + movb 0x12345678(%ebx),%ah +LBPatch0: + movb 13(%esi),%bl + + movb 0x12345678(%ecx),%al +LBPatch1: + movb 12(%esi),%cl + + movb %dh,%bh + addl %ebp,%edx + + rorl $16,%eax + movb %dh,%ch + + addl %ebp,%edx + movb 0x12345678(%ebx),%ah +LBPatch2: + + movb 11(%esi),%bl + movb 0x12345678(%ecx),%al +LBPatch3: + + movb 10(%esi),%cl + movl %eax,12(%edi) + + movb %dh,%bh + addl %ebp,%edx + + movb %dh,%ch + addl %ebp,%edx + + movb 0x12345678(%ebx),%ah +LBPatch4: + movb 9(%esi),%bl + + movb 0x12345678(%ecx),%al +LBPatch5: + movb 8(%esi),%cl + + movb %dh,%bh + addl %ebp,%edx + + rorl $16,%eax + movb %dh,%ch + + addl %ebp,%edx + movb 0x12345678(%ebx),%ah +LBPatch6: + + movb 7(%esi),%bl + movb 0x12345678(%ecx),%al +LBPatch7: + + movb 6(%esi),%cl + movl %eax,8(%edi) + + movb %dh,%bh + addl %ebp,%edx + + movb %dh,%ch + addl %ebp,%edx + + movb 0x12345678(%ebx),%ah +LBPatch8: + movb 5(%esi),%bl + + movb 0x12345678(%ecx),%al +LBPatch9: + movb 4(%esi),%cl + + movb %dh,%bh + addl %ebp,%edx + + rorl $16,%eax + movb %dh,%ch + + addl %ebp,%edx + movb 0x12345678(%ebx),%ah +LBPatch10: + + movb 3(%esi),%bl + movb 0x12345678(%ecx),%al +LBPatch11: + + movb 2(%esi),%cl + movl %eax,4(%edi) + + movb %dh,%bh + addl %ebp,%edx + + movb %dh,%ch + addl %ebp,%edx + + movb 0x12345678(%ebx),%ah +LBPatch12: + movb 1(%esi),%bl + + movb 0x12345678(%ecx),%al +LBPatch13: + movb (%esi),%cl + + movb %dh,%bh + addl %ebp,%edx + + rorl $16,%eax + movb %dh,%ch + + movb 0x12345678(%ebx),%ah +LBPatch14: + movl C(lightright),%edx + + movb 0x12345678(%ecx),%al +LBPatch15: + movl C(lightdelta),%ebp + + movl %eax,(%edi) + + addl C(sourcetstep),%esi + addl C(surfrowbytes),%edi + + addl C(lightrightstep),%edx + addl C(lightdeltastep),%ebp + + movl %edx,C(lightright) + jc Lblockloop8_mip0 + +// if (pbasesource >= r_sourcemax) +// pbasesource -= stepback; + + cmpl C(r_sourcemax),%esi + jb LSkip_mip0 + subl C(r_stepback),%esi +LSkip_mip0: + + movl C(r_lightptr),%ebx + decl sb_v + + jnz Lv_loop_mip0 + + popl %ebx // restore register variables + popl %esi + popl %edi + popl %ebp // restore the caller's stack frame + ret + + +//---------------------------------------------------------------------- +// Surface block drawer for mip level 1 +//---------------------------------------------------------------------- + + .align 4 +.globl C(R_DrawSurfaceBlock8_mip1) +C(R_DrawSurfaceBlock8_mip1): + pushl %ebp // preserve caller's stack frame + pushl %edi + pushl %esi // preserve register variables + pushl %ebx + +// for (v=0 ; v> blockdivshift; +// lightrightstep = (lightptr[1] - lightright) >> blockdivshift; +// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) | +// 0xF0000000; + movl 4(%ebx),%ecx // lightptr[1] + movl (%ebx),%ebx // lightptr[0] + + subl %eax,%ebx + subl %edx,%ecx + + sarl $3,%ecx + orl $0x70000000,%ebp + + sarl $3,%ebx + movl %ecx,C(lightrightstep) + + subl %ecx,%ebx + andl $0xFFFFF,%ebx + + orl $0xF0000000,%ebx + subl %ecx,%ecx // high word must be 0 in loop for addressing + + movl %ebx,C(lightdeltastep) + subl %ebx,%ebx // high word must be 0 in loop for addressing + +Lblockloop8_mip1: + movl %ebp,C(lightdelta) + movb 6(%esi),%cl + + sarl $3,%ebp + movb %dh,%bh + + movb 7(%esi),%bl + addl %ebp,%edx + + movb %dh,%ch + addl %ebp,%edx + + movb 0x12345678(%ebx),%ah +LBPatch22: + movb 5(%esi),%bl + + movb 0x12345678(%ecx),%al +LBPatch23: + movb 4(%esi),%cl + + movb %dh,%bh + addl %ebp,%edx + + rorl $16,%eax + movb %dh,%ch + + addl %ebp,%edx + movb 0x12345678(%ebx),%ah +LBPatch24: + + movb 3(%esi),%bl + movb 0x12345678(%ecx),%al +LBPatch25: + + movb 2(%esi),%cl + movl %eax,4(%edi) + + movb %dh,%bh + addl %ebp,%edx + + movb %dh,%ch + addl %ebp,%edx + + movb 0x12345678(%ebx),%ah +LBPatch26: + movb 1(%esi),%bl + + movb 0x12345678(%ecx),%al +LBPatch27: + movb (%esi),%cl + + movb %dh,%bh + addl %ebp,%edx + + rorl $16,%eax + movb %dh,%ch + + movb 0x12345678(%ebx),%ah +LBPatch28: + movl C(lightright),%edx + + movb 0x12345678(%ecx),%al +LBPatch29: + movl C(lightdelta),%ebp + + movl %eax,(%edi) + movl C(sourcetstep),%eax + + addl %eax,%esi + movl C(surfrowbytes),%eax + + addl %eax,%edi + movl C(lightrightstep),%eax + + addl %eax,%edx + movl C(lightdeltastep),%eax + + addl %eax,%ebp + movl %edx,C(lightright) + + jc Lblockloop8_mip1 + +// if (pbasesource >= r_sourcemax) +// pbasesource -= stepback; + + cmpl C(r_sourcemax),%esi + jb LSkip_mip1 + subl C(r_stepback),%esi +LSkip_mip1: + + movl C(r_lightptr),%ebx + decl sb_v + + jnz Lv_loop_mip1 + + popl %ebx // restore register variables + popl %esi + popl %edi + popl %ebp // restore the caller's stack frame + ret + + +//---------------------------------------------------------------------- +// Surface block drawer for mip level 2 +//---------------------------------------------------------------------- + + .align 4 +.globl C(R_DrawSurfaceBlock8_mip2) +C(R_DrawSurfaceBlock8_mip2): + pushl %ebp // preserve caller's stack frame + pushl %edi + pushl %esi // preserve register variables + pushl %ebx + +// for (v=0 ; v> blockdivshift; +// lightrightstep = (lightptr[1] - lightright) >> blockdivshift; +// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) | +// 0xF0000000; + movl 4(%ebx),%ecx // lightptr[1] + movl (%ebx),%ebx // lightptr[0] + + subl %eax,%ebx + subl %edx,%ecx + + sarl $2,%ecx + orl $0x30000000,%ebp + + sarl $2,%ebx + movl %ecx,C(lightrightstep) + + subl %ecx,%ebx + + andl $0xFFFFF,%ebx + + orl $0xF0000000,%ebx + subl %ecx,%ecx // high word must be 0 in loop for addressing + + movl %ebx,C(lightdeltastep) + subl %ebx,%ebx // high word must be 0 in loop for addressing + +Lblockloop8_mip2: + movl %ebp,C(lightdelta) + movb 2(%esi),%cl + + sarl $2,%ebp + movb %dh,%bh + + movb 3(%esi),%bl + addl %ebp,%edx + + movb %dh,%ch + addl %ebp,%edx + + movb 0x12345678(%ebx),%ah +LBPatch18: + movb 1(%esi),%bl + + movb 0x12345678(%ecx),%al +LBPatch19: + movb (%esi),%cl + + movb %dh,%bh + addl %ebp,%edx + + rorl $16,%eax + movb %dh,%ch + + movb 0x12345678(%ebx),%ah +LBPatch20: + movl C(lightright),%edx + + movb 0x12345678(%ecx),%al +LBPatch21: + movl C(lightdelta),%ebp + + movl %eax,(%edi) + movl C(sourcetstep),%eax + + addl %eax,%esi + movl C(surfrowbytes),%eax + + addl %eax,%edi + movl C(lightrightstep),%eax + + addl %eax,%edx + movl C(lightdeltastep),%eax + + addl %eax,%ebp + movl %edx,C(lightright) + + jc Lblockloop8_mip2 + +// if (pbasesource >= r_sourcemax) +// pbasesource -= stepback; + + cmpl C(r_sourcemax),%esi + jb LSkip_mip2 + subl C(r_stepback),%esi +LSkip_mip2: + + movl C(r_lightptr),%ebx + decl sb_v + + jnz Lv_loop_mip2 + + popl %ebx // restore register variables + popl %esi + popl %edi + popl %ebp // restore the caller's stack frame + ret + + +//---------------------------------------------------------------------- +// Surface block drawer for mip level 3 +//---------------------------------------------------------------------- + + .align 4 +.globl C(R_DrawSurfaceBlock8_mip3) +C(R_DrawSurfaceBlock8_mip3): + pushl %ebp // preserve caller's stack frame + pushl %edi + pushl %esi // preserve register variables + pushl %ebx + +// for (v=0 ; v> blockdivshift; +// lightrightstep = (lightptr[1] - lightright) >> blockdivshift; +// lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) | +// 0xF0000000; + movl 4(%ebx),%ecx // lightptr[1] + movl (%ebx),%ebx // lightptr[0] + + subl %eax,%ebx + subl %edx,%ecx + + sarl $1,%ecx + + sarl $1,%ebx + movl %ecx,C(lightrightstep) + + subl %ecx,%ebx + andl $0xFFFFF,%ebx + + sarl $1,%ebp + orl $0xF0000000,%ebx + + movl %ebx,C(lightdeltastep) + subl %ebx,%ebx // high word must be 0 in loop for addressing + + movb 1(%esi),%bl + subl %ecx,%ecx // high word must be 0 in loop for addressing + + movb %dh,%bh + movb (%esi),%cl + + addl %ebp,%edx + movb %dh,%ch + + movb 0x12345678(%ebx),%al +LBPatch16: + movl C(lightright),%edx + + movb %al,1(%edi) + movb 0x12345678(%ecx),%al +LBPatch17: + + movb %al,(%edi) + movl C(sourcetstep),%eax + + addl %eax,%esi + movl C(surfrowbytes),%eax + + addl %eax,%edi + movl C(lightdeltastep),%eax + + movl C(lightdelta),%ebp + movb (%esi),%cl + + addl %eax,%ebp + movl C(lightrightstep),%eax + + sarl $1,%ebp + addl %eax,%edx + + movb %dh,%bh + movb 1(%esi),%bl + + addl %ebp,%edx + movb %dh,%ch + + movb 0x12345678(%ebx),%al +LBPatch30: + movl C(sourcetstep),%edx + + movb %al,1(%edi) + movb 0x12345678(%ecx),%al +LBPatch31: + + movb %al,(%edi) + movl C(surfrowbytes),%ebp + + addl %edx,%esi + addl %ebp,%edi + +// if (pbasesource >= r_sourcemax) +// pbasesource -= stepback; + + cmpl C(r_sourcemax),%esi + jb LSkip_mip3 + subl C(r_stepback),%esi +LSkip_mip3: + + movl C(r_lightptr),%ebx + decl sb_v + + jnz Lv_loop_mip3 + + popl %ebx // restore register variables + popl %esi + popl %edi + popl %ebp // restore the caller's stack frame + ret + + +.globl C(R_Surf8End) +C(R_Surf8End): + +//---------------------------------------------------------------------- +// Code patching routines +//---------------------------------------------------------------------- + .data + + .align 4 +LPatchTable8: + .long LBPatch0-4 + .long LBPatch1-4 + .long LBPatch2-4 + .long LBPatch3-4 + .long LBPatch4-4 + .long LBPatch5-4 + .long LBPatch6-4 + .long LBPatch7-4 + .long LBPatch8-4 + .long LBPatch9-4 + .long LBPatch10-4 + .long LBPatch11-4 + .long LBPatch12-4 + .long LBPatch13-4 + .long LBPatch14-4 + .long LBPatch15-4 + .long LBPatch16-4 + .long LBPatch17-4 + .long LBPatch18-4 + .long LBPatch19-4 + .long LBPatch20-4 + .long LBPatch21-4 + .long LBPatch22-4 + .long LBPatch23-4 + .long LBPatch24-4 + .long LBPatch25-4 + .long LBPatch26-4 + .long LBPatch27-4 + .long LBPatch28-4 + .long LBPatch29-4 + .long LBPatch30-4 + .long LBPatch31-4 + + .text + + .align 4 +.globl C(R_Surf8Patch) +C(R_Surf8Patch): + pushl %ebx + + movl C(colormap),%eax + movl $LPatchTable8,%ebx + movl $32,%ecx +LPatchLoop8: + movl (%ebx),%edx + addl $4,%ebx + movl %eax,(%edx) + decl %ecx + jnz LPatchLoop8 + + popl %ebx + + ret + +#endif // id386 diff --git a/common/sys_dosa.s b/common/sys_dosa.s new file mode 100644 index 0000000..7b0ea61 --- /dev/null +++ b/common/sys_dosa.s @@ -0,0 +1,95 @@ +// +// sys_dosa.s +// x86 assembly-language DOS-dependent routines. + +#include "asm_i386.h" +#include "quakeasm.h" + + + .data + + .align 4 +fpenv: + .long 0, 0, 0, 0, 0, 0, 0, 0 + + .text + +.globl C(MaskExceptions) +C(MaskExceptions): + fnstenv fpenv + orl $0x3F,fpenv + fldenv fpenv + + ret + +#if 0 +.globl C(unmaskexceptions) +C(unmaskexceptions): + fnstenv fpenv + andl $0xFFFFFFE0,fpenv + fldenv fpenv + + ret +#endif + + .data + + .align 4 +.globl ceil_cw, single_cw, full_cw, cw, pushed_cw +ceil_cw: .long 0 +single_cw: .long 0 +full_cw: .long 0 +cw: .long 0 +pushed_cw: .long 0 + + .text + +.globl C(Sys_LowFPPrecision) +C(Sys_LowFPPrecision): + fldcw single_cw + + ret + +.globl C(Sys_HighFPPrecision) +C(Sys_HighFPPrecision): + fldcw full_cw + + ret + +.globl C(Sys_PushFPCW_SetHigh) +C(Sys_PushFPCW_SetHigh): + fnstcw pushed_cw + fldcw full_cw + + ret + +.globl C(Sys_PopFPCW) +C(Sys_PopFPCW): + fldcw pushed_cw + + ret + +.globl C(Sys_SetFPCW) +C(Sys_SetFPCW): + fnstcw cw + movl cw,%eax +#if id386 + andb $0xF0,%ah + orb $0x03,%ah // round mode, 64-bit precision +#endif + movl %eax,full_cw + +#if id386 + andb $0xF0,%ah + orb $0x0C,%ah // chop mode, single precision +#endif + movl %eax,single_cw + +#if id386 + andb $0xF0,%ah + orb $0x08,%ah // ceil mode, single precision +#endif + movl %eax,ceil_cw + + ret +