Tweaked the authors, missed a few .s files..

This commit is contained in:
Zephaniah E. Hull 1999-12-31 05:09:06 +00:00
parent 67b65279a3
commit b416d81046
11 changed files with 3673 additions and 0 deletions

View File

@ -20,3 +20,6 @@ Maintance of 3Dfx support:
Maintance of the keyboard stuff:
Zephaniah E. Hull <warp@whitestar.soark.net>
Pointing out more common files:
Marcus Sundberg <mackan@stacken.kth.se>

216
common/r_aclipa.s Normal file
View File

@ -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

237
common/r_aliasa.s Normal file
View File

@ -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 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
// {
movl pstverts(%esp),%ebp
movl fv(%esp),%edi
movl C(r_anumverts),%ecx
subl %edx,%edx
Lloop:
// // transform and project
// zi = 1.0 / (DotProduct(pverts->v, 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

838
common/r_drawa.s Normal file
View File

@ -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

750
common/r_edgea.s Normal file
View File

@ -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

260
common/r_light.c Normal file
View File

@ -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 ; j<MAX_LIGHTSTYLES ; j++)
{
if (!cl_lightstyle[j].length)
{
d_lightstylevalue[j] = 256;
continue;
}
k = i % cl_lightstyle[j].length;
k = cl_lightstyle[j].map[k] - 'a';
k = k*22;
d_lightstylevalue[j] = k;
}
}
/*
=============================================================================
DYNAMIC LIGHTS
=============================================================================
*/
/*
=============
R_MarkLights
=============
*/
void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents < 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 ; i<node->numsurfaces ; 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 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
R_MarkLights ( l, 1<<i, cl.worldmodel->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 ; i<node->numsurfaces ; 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;
}

280
common/r_sky.c Normal file
View File

@ -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<SKYSIZE ; y++)
{
baseofs = ((y+yshift) & SKYMASK) * 131;
// FIXME: clean this up
#if UNALIGNED_OK
for (x=0 ; x<SKYSIZE ; x += 4)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
// PORT: unaligned dword access to bottommask and bottomsky
*pnewsky = (*(pnewsky + (128 / sizeof (unsigned))) &
*(unsigned *)&bottommask[ofs]) |
*(unsigned *)&bottomsky[ofs];
pnewsky++;
}
#else
for (x=0 ; x<SKYSIZE ; x++)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
*(byte *)pnewsky = (*((byte *)pnewsky + 128) &
*(byte *)&bottommask[ofs]) |
*(byte *)&bottomsky[ofs];
pnewsky = (unsigned *)((byte *)pnewsky + 1);
}
#endif
pnewsky += 128 / sizeof (unsigned);
}
r_skymade = 1;
}
/*
=================
R_GenSkyTile
=================
*/
void R_GenSkyTile (void *pdest)
{
int x, y;
int ofs, baseofs;
int xshift, yshift;
unsigned *pnewsky;
unsigned *pd;
xshift = skytime*skyspeed;
yshift = skytime*skyspeed;
pnewsky = (unsigned *)&newsky[0];
pd = (unsigned *)pdest;
for (y=0 ; y<SKYSIZE ; y++)
{
baseofs = ((y+yshift) & SKYMASK) * 131;
// FIXME: clean this up
#if UNALIGNED_OK
for (x=0 ; x<SKYSIZE ; x += 4)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
// PORT: unaligned dword access to bottommask and bottomsky
*pd = (*(pnewsky + (128 / sizeof (unsigned))) &
*(unsigned *)&bottommask[ofs]) |
*(unsigned *)&bottomsky[ofs];
pnewsky++;
pd++;
}
#else
for (x=0 ; x<SKYSIZE ; x++)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
*(byte *)pd = (*((byte *)pnewsky + 128) &
*(byte *)&bottommask[ofs]) |
*(byte *)&bottomsky[ofs];
pnewsky = (unsigned *)((byte *)pnewsky + 1);
pd = (unsigned *)((byte *)pd + 1);
}
#endif
pnewsky += 128 / sizeof (unsigned);
}
}
/*
=================
R_GenSkyTile16
=================
*/
void R_GenSkyTile16 (void *pdest)
{
int x, y;
int ofs, baseofs;
int xshift, yshift;
byte *pnewsky;
unsigned short *pd;
xshift = skytime * skyspeed;
yshift = skytime * skyspeed;
pnewsky = (byte *)&newsky[0];
pd = (unsigned short *)pdest;
for (y=0 ; y<SKYSIZE ; y++)
{
baseofs = ((y+yshift) & SKYMASK) * 131;
// FIXME: clean this up
// FIXME: do faster unaligned version?
for (x=0 ; x<SKYSIZE ; x++)
{
ofs = baseofs + ((x+xshift) & SKYMASK);
*pd = d_8to16table[(*(pnewsky + 128) &
*(byte *)&bottommask[ofs]) |
*(byte *)&bottomsky[ofs]];
pnewsky++;
pd++;
}
pnewsky += TILE_SIZE;
}
}
/*
=============
R_SetSkyFrame
==============
*/
void R_SetSkyFrame (void)
{
int g, s1, s2;
float temp;
skyspeed = iskyspeed;
skyspeed2 = iskyspeed2;
g = GreatestCommonDivisor (iskyspeed, iskyspeed2);
s1 = iskyspeed / g;
s2 = iskyspeed2 / g;
temp = SKYSIZE * s1 * s2;
skytime = cl.time - ((int)(cl.time / temp) * temp);
r_skymade = 0;
}

39
common/r_vars.c Normal file
View File

@ -0,0 +1,39 @@
/*
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_vars.c: global refresh variables
#include "quakedef.h"
#if !id386
// all global and static refresh variables are collected in a contiguous block
// to avoid cache conflicts.
//-------------------------------------------------------
// global refresh variables
//-------------------------------------------------------
// FIXME: make into one big structure, like cl or sv
// FIXME: do separately for refresh engine and driver
int r_bmodelactive;
#endif // !id386

172
common/surf16.s Normal file
View File

@ -0,0 +1,172 @@
/*
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.
*/
//
// surf16.s
// x86 assembly-language 16 bpp surface block drawing code.
//
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#if id386
//----------------------------------------------------------------------
// Surface block drawer
//----------------------------------------------------------------------
.data
k: .long 0
loopentry: .long 0
.align 4
blockjumptable16:
.long LEnter2_16
.long LEnter4_16
.long 0, LEnter8_16
.long 0, 0, 0, LEnter16_16
.text
.align 4
.globl C(R_Surf16Start)
C(R_Surf16Start):
.align 4
.globl C(R_DrawSurfaceBlock16)
C(R_DrawSurfaceBlock16):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
movl C(blocksize),%eax
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
movl C(sourcesstep),%ebx
movl blockjumptable16-4(,%eax,2),%ecx
movl %eax,k
movl %ecx,loopentry
movl C(lightleft),%edx
movl C(lightright),%ebp
Lblockloop16:
subl %edx,%ebp
movb C(blockdivshift),%cl
sarl %cl,%ebp
jns Lp1_16
testl C(blockdivmask),%ebp
jz Lp1_16
incl %ebp
Lp1_16:
subl %eax,%eax
subl %ecx,%ecx // high words must be 0 in loop for addressing
jmp *loopentry
.align 4
#include "block16.h"
movl C(pbasesource),%esi
movl C(lightleft),%edx
movl C(lightright),%ebp
movl C(sourcetstep),%eax
movl C(lightrightstep),%ecx
movl C(prowdestbase),%edi
addl %eax,%esi
addl %ecx,%ebp
movl C(lightleftstep),%eax
movl C(surfrowbytes),%ecx
addl %eax,%edx
addl %ecx,%edi
movl %esi,C(pbasesource)
movl %ebp,C(lightright)
movl k,%eax
movl %edx,C(lightleft)
decl %eax
movl %edi,C(prowdestbase)
movl %eax,k
jnz Lblockloop16
popl %ebx // restore register variables
popl %esi
popl %edi
popl %ebp // restore the caller's stack frame
ret
.globl C(R_Surf16End)
C(R_Surf16End):
//----------------------------------------------------------------------
// Code patching routines
//----------------------------------------------------------------------
.data
.align 4
LPatchTable16:
.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
.text
.align 4
.globl C(R_Surf16Patch)
C(R_Surf16Patch):
pushl %ebx
movl C(colormap),%eax
movl $LPatchTable16,%ebx
movl $16,%ecx
LPatchLoop16:
movl (%ebx),%edx
addl $4,%ebx
movl %eax,(%edx)
decl %ecx
jnz LPatchLoop16
popl %ebx
ret
#endif // id386

783
common/surf8.s Normal file
View File

@ -0,0 +1,783 @@
/*
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.
*/
//
// surf8.s
// x86 assembly-language 8 bpp surface block drawing code.
//
#include "asm_i386.h"
#include "quakeasm.h"
#include "asm_draw.h"
#if id386
.data
sb_v: .long 0
.text
.align 4
.globl C(R_Surf8Start)
C(R_Surf8Start):
//----------------------------------------------------------------------
// Surface block drawer for mip level 0
//----------------------------------------------------------------------
.align 4
.globl C(R_DrawSurfaceBlock8_mip0)
C(R_DrawSurfaceBlock8_mip0):
pushl %ebp // preserve caller's stack frame
pushl %edi
pushl %esi // preserve register variables
pushl %ebx
// for (v=0 ; v<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip0:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> 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<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip1:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> 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<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip2:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> 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<numvblocks ; v++)
// {
movl C(r_lightptr),%ebx
movl C(r_numvblocks),%eax
movl %eax,sb_v
movl C(prowdestbase),%edi
movl C(pbasesource),%esi
Lv_loop_mip3:
// lightleft = lightptr[0];
// lightright = lightptr[1];
// lightdelta = (lightleft - lightright) & 0xFFFFF;
movl (%ebx),%eax // lightleft
movl 4(%ebx),%edx // lightright
movl %eax,%ebp
movl C(r_lightwidth),%ecx
movl %edx,C(lightright)
subl %edx,%ebp
andl $0xFFFFF,%ebp
leal (%ebx,%ecx,4),%ebx
movl %ebp,C(lightdelta)
// lightptr += lightwidth;
movl %ebx,C(r_lightptr)
// lightleftstep = (lightptr[0] - lightleft) >> 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

95
common/sys_dosa.s Normal file
View File

@ -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