Initial checkin of software rendering bits and bobs.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@20 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
3a7c75319a
commit
fffb8897b9
55 changed files with 38138 additions and 0 deletions
1074
engine/sw/adivtab.h
Normal file
1074
engine/sw/adivtab.h
Normal file
File diff suppressed because it is too large
Load diff
154
engine/sw/asm_draw.h
Normal file
154
engine/sw/asm_draw.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
//
|
||||
// asm_draw.h
|
||||
//
|
||||
// Include file for asm drawing routines.
|
||||
//
|
||||
|
||||
//
|
||||
// !!! note that this file must match the corresponding C structures at all
|
||||
// times !!!
|
||||
//
|
||||
|
||||
// !!! if this is changed, it must be changed in r_local.h too !!!
|
||||
#define NEAR_CLIP 0.01
|
||||
|
||||
// !!! if this is changed, it must be changed in r_local.h too !!!
|
||||
#define CYCLE 128
|
||||
|
||||
// espan_t structure
|
||||
// !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
#define espan_t_u 0
|
||||
#define espan_t_v 4
|
||||
#define espan_t_count 8
|
||||
#define espan_t_pnext 12
|
||||
#define espan_t_size 16
|
||||
|
||||
// sspan_t structure
|
||||
// !!! if this is changed, it must be changed in d_local.h too !!!
|
||||
#define sspan_t_u 0
|
||||
#define sspan_t_v 4
|
||||
#define sspan_t_count 8
|
||||
#define sspan_t_size 12
|
||||
|
||||
// spanpackage_t structure
|
||||
// !!! if this is changed, it must be changed in d_polyset.c too !!!
|
||||
#define spanpackage_t_pdest 0
|
||||
#define spanpackage_t_pz 4
|
||||
#define spanpackage_t_count 8
|
||||
#define spanpackage_t_ptex 12
|
||||
#define spanpackage_t_sfrac 16
|
||||
#define spanpackage_t_tfrac 20
|
||||
#define spanpackage_t_light 24
|
||||
#define spanpackage_t_zi 28
|
||||
#define spanpackage_t_size 32
|
||||
|
||||
// edge_t structure
|
||||
// !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
#define et_u 0
|
||||
#define et_u_step 4
|
||||
#define et_prev 8
|
||||
#define et_next 12
|
||||
#define et_surfs 16
|
||||
#define et_nextremove 20
|
||||
#define et_nearzi 24
|
||||
#define et_owner 28
|
||||
#define et_size 32
|
||||
|
||||
// surf_t structure
|
||||
// !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
#define SURF_T_SHIFT 6
|
||||
#define st_next 0
|
||||
#define st_prev 4
|
||||
#define st_spans 8
|
||||
#define st_key 12
|
||||
#define st_last_u 16
|
||||
#define st_spanstate 20
|
||||
#define st_flags 24
|
||||
#define st_data 28
|
||||
#define st_entity 32
|
||||
#define st_nearzi 36
|
||||
#define st_insubmodel 40
|
||||
#define st_d_ziorigin 44
|
||||
#define st_d_zistepu 48
|
||||
#define st_d_zistepv 52
|
||||
#define st_pad 56
|
||||
#define st_size 64
|
||||
|
||||
// clipplane_t structure
|
||||
// !!! if this is changed, it must be changed in r_local.h too !!!
|
||||
#define cp_normal 0
|
||||
#define cp_dist 12
|
||||
#define cp_next 16
|
||||
#define cp_leftedge 20
|
||||
#define cp_rightedge 21
|
||||
#define cp_reserved 22
|
||||
#define cp_size 24
|
||||
|
||||
// medge_t structure
|
||||
// !!! if this is changed, it must be changed in model.h too !!!
|
||||
#define me_v 0
|
||||
#define me_cachededgeoffset 4
|
||||
#define me_size 8
|
||||
|
||||
// mvertex_t structure
|
||||
// !!! if this is changed, it must be changed in model.h too !!!
|
||||
#define mv_position 0
|
||||
#define mv_size 12
|
||||
|
||||
// refdef_t structure
|
||||
// !!! if this is changed, it must be changed in render.h too !!!
|
||||
#define rd_vrect 0
|
||||
#define rd_aliasvrect 20
|
||||
#define rd_vrectright 40
|
||||
#define rd_vrectbottom 44
|
||||
#define rd_aliasvrectright 48
|
||||
#define rd_aliasvrectbottom 52
|
||||
#define rd_vrectrightedge 56
|
||||
#define rd_fvrectx 60
|
||||
#define rd_fvrecty 64
|
||||
#define rd_fvrectx_adj 68
|
||||
#define rd_fvrecty_adj 72
|
||||
#define rd_vrect_x_adj_shift20 76
|
||||
#define rd_vrectright_adj_shift20 80
|
||||
#define rd_fvrectright_adj 84
|
||||
#define rd_fvrectbottom_adj 88
|
||||
#define rd_fvrectright 92
|
||||
#define rd_fvrectbottom 96
|
||||
#define rd_horizontalFieldOfView 100
|
||||
#define rd_xOrigin 104
|
||||
#define rd_yOrigin 108
|
||||
#define rd_vieworg 112
|
||||
#define rd_viewangles 124
|
||||
#define rd_ambientlight 136
|
||||
#define rd_flags 140
|
||||
#define rd_currentplayernum 144
|
||||
#define rd_size 148
|
||||
|
||||
// mtriangle_t structure
|
||||
// !!! if this is changed, it must be changed in model.h too !!!
|
||||
#define mtri_facesfront 0
|
||||
#define mtri_vertindex 4
|
||||
#define mtri_stindex 16
|
||||
#define mtri_size 28 // !!! if this changes, array indexing in !!!
|
||||
// !!! d_polysa.s must be changed to match !!!
|
||||
#define mtri_shift 4
|
||||
|
123
engine/sw/block16.h
Normal file
123
engine/sw/block16.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
LEnter16_16:
|
||||
movb (%esi),%al
|
||||
movb (%esi,%ebx,),%cl
|
||||
movb %dh,%ah
|
||||
addl %ebp,%edx
|
||||
movb %dh,%ch
|
||||
leal (%esi,%ebx,2),%esi
|
||||
movw 0x12345678(,%eax,2),%ax
|
||||
LBPatch0:
|
||||
addl %ebp,%edx
|
||||
movw %ax,(%edi)
|
||||
movw 0x12345678(,%ecx,2),%cx
|
||||
LBPatch1:
|
||||
movw %cx,2(%edi)
|
||||
addl $0x4,%edi
|
||||
|
||||
movb (%esi),%al
|
||||
movb (%esi,%ebx,),%cl
|
||||
movb %dh,%ah
|
||||
addl %ebp,%edx
|
||||
movb %dh,%ch
|
||||
leal (%esi,%ebx,2),%esi
|
||||
movw 0x12345678(,%eax,2),%ax
|
||||
LBPatch2:
|
||||
addl %ebp,%edx
|
||||
movw %ax,(%edi)
|
||||
movw 0x12345678(,%ecx,2),%cx
|
||||
LBPatch3:
|
||||
movw %cx,2(%edi)
|
||||
addl $0x4,%edi
|
||||
|
||||
movb (%esi),%al
|
||||
movb (%esi,%ebx,),%cl
|
||||
movb %dh,%ah
|
||||
addl %ebp,%edx
|
||||
movb %dh,%ch
|
||||
leal (%esi,%ebx,2),%esi
|
||||
movw 0x12345678(,%eax,2),%ax
|
||||
LBPatch4:
|
||||
addl %ebp,%edx
|
||||
movw %ax,(%edi)
|
||||
movw 0x12345678(,%ecx,2),%cx
|
||||
LBPatch5:
|
||||
movw %cx,2(%edi)
|
||||
addl $0x4,%edi
|
||||
|
||||
movb (%esi),%al
|
||||
movb (%esi,%ebx,),%cl
|
||||
movb %dh,%ah
|
||||
addl %ebp,%edx
|
||||
movb %dh,%ch
|
||||
leal (%esi,%ebx,2),%esi
|
||||
movw 0x12345678(,%eax,2),%ax
|
||||
LBPatch6:
|
||||
addl %ebp,%edx
|
||||
movw %ax,(%edi)
|
||||
movw 0x12345678(,%ecx,2),%cx
|
||||
LBPatch7:
|
||||
movw %cx,2(%edi)
|
||||
addl $0x4,%edi
|
||||
|
||||
LEnter8_16:
|
||||
movb (%esi),%al
|
||||
movb (%esi,%ebx,),%cl
|
||||
movb %dh,%ah
|
||||
addl %ebp,%edx
|
||||
movb %dh,%ch
|
||||
leal (%esi,%ebx,2),%esi
|
||||
movw 0x12345678(,%eax,2),%ax
|
||||
LBPatch8:
|
||||
addl %ebp,%edx
|
||||
movw %ax,(%edi)
|
||||
movw 0x12345678(,%ecx,2),%cx
|
||||
LBPatch9:
|
||||
movw %cx,2(%edi)
|
||||
addl $0x4,%edi
|
||||
|
||||
movb (%esi),%al
|
||||
movb (%esi,%ebx,),%cl
|
||||
movb %dh,%ah
|
||||
addl %ebp,%edx
|
||||
movb %dh,%ch
|
||||
leal (%esi,%ebx,2),%esi
|
||||
movw 0x12345678(,%eax,2),%ax
|
||||
LBPatch10:
|
||||
addl %ebp,%edx
|
||||
movw %ax,(%edi)
|
||||
movw 0x12345678(,%ecx,2),%cx
|
||||
LBPatch11:
|
||||
movw %cx,2(%edi)
|
||||
addl $0x4,%edi
|
||||
|
||||
LEnter4_16:
|
||||
movb (%esi),%al
|
||||
movb (%esi,%ebx,),%cl
|
||||
movb %dh,%ah
|
||||
addl %ebp,%edx
|
||||
movb %dh,%ch
|
||||
leal (%esi,%ebx,2),%esi
|
||||
movw 0x12345678(,%eax,2),%ax
|
||||
LBPatch12:
|
||||
addl %ebp,%edx
|
||||
movw %ax,(%edi)
|
||||
movw 0x12345678(,%ecx,2),%cx
|
||||
LBPatch13:
|
||||
movw %cx,2(%edi)
|
||||
addl $0x4,%edi
|
||||
|
||||
LEnter2_16:
|
||||
movb (%esi),%al
|
||||
movb (%esi,%ebx,),%cl
|
||||
movb %dh,%ah
|
||||
addl %ebp,%edx
|
||||
movb %dh,%ch
|
||||
leal (%esi,%ebx,2),%esi
|
||||
movw 0x12345678(,%eax,2),%ax
|
||||
LBPatch14:
|
||||
addl %ebp,%edx
|
||||
movw %ax,(%edi)
|
||||
movw 0x12345678(,%ecx,2),%cx
|
||||
LBPatch15:
|
||||
movw %cx,2(%edi)
|
||||
addl $0x4,%edi
|
1037
engine/sw/d_draw.s
Normal file
1037
engine/sw/d_draw.s
Normal file
File diff suppressed because it is too large
Load diff
974
engine/sw/d_draw16.s
Normal file
974
engine/sw/d_draw16.s
Normal file
|
@ -0,0 +1,974 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
//
|
||||
// d_draw16.s
|
||||
// x86 assembly-language horizontal 16-bpp span-drawing code, with 16-pixel
|
||||
// subdivision.
|
||||
//
|
||||
|
||||
#include "asm_i386.h"
|
||||
#include "quakeasm.h"
|
||||
#include "asm_draw.h"
|
||||
#include "d_ifacea.h"
|
||||
|
||||
#if id386
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 8-bpp horizontal span drawing code for polygons, with no transparency and
|
||||
// 16-pixel subdivision.
|
||||
//
|
||||
// Assumes there is at least one span in pspans, and that every span
|
||||
// contains at least one pixel
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
.data
|
||||
|
||||
.text
|
||||
|
||||
// out-of-line, rarely-needed clamping code
|
||||
|
||||
LClampHigh0:
|
||||
movl C(bbextents),%esi
|
||||
jmp LClampReentry0
|
||||
LClampHighOrLow0:
|
||||
jg LClampHigh0
|
||||
xorl %esi,%esi
|
||||
jmp LClampReentry0
|
||||
|
||||
LClampHigh1:
|
||||
movl C(bbextentt),%edx
|
||||
jmp LClampReentry1
|
||||
LClampHighOrLow1:
|
||||
jg LClampHigh1
|
||||
xorl %edx,%edx
|
||||
jmp LClampReentry1
|
||||
|
||||
LClampLow2:
|
||||
movl $4096,%ebp
|
||||
jmp LClampReentry2
|
||||
LClampHigh2:
|
||||
movl C(bbextents),%ebp
|
||||
jmp LClampReentry2
|
||||
|
||||
LClampLow3:
|
||||
movl $4096,%ecx
|
||||
jmp LClampReentry3
|
||||
LClampHigh3:
|
||||
movl C(bbextentt),%ecx
|
||||
jmp LClampReentry3
|
||||
|
||||
LClampLow4:
|
||||
movl $4096,%eax
|
||||
jmp LClampReentry4
|
||||
LClampHigh4:
|
||||
movl C(bbextents),%eax
|
||||
jmp LClampReentry4
|
||||
|
||||
LClampLow5:
|
||||
movl $4096,%ebx
|
||||
jmp LClampReentry5
|
||||
LClampHigh5:
|
||||
movl C(bbextentt),%ebx
|
||||
jmp LClampReentry5
|
||||
|
||||
|
||||
#define pspans 4+16
|
||||
|
||||
.align 4
|
||||
.globl C(D_DrawSpans8SubDiv16)
|
||||
C(D_DrawSpans8SubDiv16):
|
||||
pushl %ebp // preserve caller's stack frame
|
||||
pushl %edi
|
||||
pushl %esi // preserve register variables
|
||||
pushl %ebx
|
||||
|
||||
//
|
||||
// set up scaled-by-16 steps, for 16-long segments; also set up cacheblock
|
||||
// and span list pointers
|
||||
//
|
||||
// TODO: any overlap from rearranging?
|
||||
flds C(d_sdivzstepu)
|
||||
fmuls fp_16
|
||||
movl C(cacheblock),%edx
|
||||
flds C(d_tdivzstepu)
|
||||
fmuls fp_16
|
||||
movl pspans(%esp),%ebx // point to the first span descriptor
|
||||
flds C(d_zistepu)
|
||||
fmuls fp_16
|
||||
movl %edx,pbase // pbase = cacheblock
|
||||
fstps zi16stepu
|
||||
fstps tdivz16stepu
|
||||
fstps sdivz16stepu
|
||||
|
||||
LSpanLoop:
|
||||
//
|
||||
// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
|
||||
// initial s and t values
|
||||
//
|
||||
// FIXME: pipeline FILD?
|
||||
fildl espan_t_v(%ebx)
|
||||
fildl espan_t_u(%ebx)
|
||||
|
||||
fld %st(1) // dv | du | dv
|
||||
fmuls C(d_sdivzstepv) // dv*d_sdivzstepv | du | dv
|
||||
fld %st(1) // du | dv*d_sdivzstepv | du | dv
|
||||
fmuls C(d_sdivzstepu) // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
|
||||
fld %st(2) // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
|
||||
fmuls C(d_tdivzstepu) // du*d_tdivzstepu | du*d_sdivzstepu |
|
||||
// dv*d_sdivzstepv | du | dv
|
||||
fxch %st(1) // du*d_sdivzstepu | du*d_tdivzstepu |
|
||||
// dv*d_sdivzstepv | du | dv
|
||||
faddp %st(0),%st(2) // du*d_tdivzstepu |
|
||||
// du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
|
||||
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
|
||||
// du*d_tdivzstepu | du | dv
|
||||
fld %st(3) // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
|
||||
// du*d_tdivzstepu | du | dv
|
||||
fmuls C(d_tdivzstepv) // dv*d_tdivzstepv |
|
||||
// du*d_sdivzstepu + dv*d_sdivzstepv |
|
||||
// du*d_tdivzstepu | du | dv
|
||||
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
|
||||
// dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
|
||||
fadds C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
|
||||
// du*d_sdivzstepu; stays in %st(2) at end
|
||||
fxch %st(4) // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
|
||||
// s/z
|
||||
fmuls C(d_zistepv) // dv*d_zistepv | dv*d_tdivzstepv |
|
||||
// du*d_tdivzstepu | du | s/z
|
||||
fxch %st(1) // dv*d_tdivzstepv | dv*d_zistepv |
|
||||
// du*d_tdivzstepu | du | s/z
|
||||
faddp %st(0),%st(2) // dv*d_zistepv |
|
||||
// dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
|
||||
fxch %st(2) // du | dv*d_tdivzstepv + du*d_tdivzstepu |
|
||||
// dv*d_zistepv | s/z
|
||||
fmuls C(d_zistepu) // du*d_zistepu |
|
||||
// dv*d_tdivzstepv + du*d_tdivzstepu |
|
||||
// dv*d_zistepv | s/z
|
||||
fxch %st(1) // dv*d_tdivzstepv + du*d_tdivzstepu |
|
||||
// du*d_zistepu | dv*d_zistepv | s/z
|
||||
fadds C(d_tdivzorigin) // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
|
||||
// du*d_tdivzstepu; stays in %st(1) at end
|
||||
fxch %st(2) // dv*d_zistepv | du*d_zistepu | t/z | s/z
|
||||
faddp %st(0),%st(1) // dv*d_zistepv + du*d_zistepu | t/z | s/z
|
||||
|
||||
flds fp_64k // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
|
||||
fxch %st(1) // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
|
||||
fadds C(d_ziorigin) // zi = d_ziorigin + dv*d_zistepv +
|
||||
// du*d_zistepu; stays in %st(0) at end
|
||||
// 1/z | fp_64k | t/z | s/z
|
||||
//
|
||||
// calculate and clamp s & t
|
||||
//
|
||||
fdivr %st(0),%st(1) // 1/z | z*64k | t/z | s/z
|
||||
|
||||
//
|
||||
// point %edi to the first pixel in the span
|
||||
//
|
||||
movl C(d_viewbuffer),%ecx
|
||||
movl espan_t_v(%ebx),%eax
|
||||
movl %ebx,pspantemp // preserve spans pointer
|
||||
|
||||
movl C(tadjust),%edx
|
||||
movl C(sadjust),%esi
|
||||
movl C(d_scantable)(,%eax,4),%edi // v * screenwidth
|
||||
addl %ecx,%edi
|
||||
movl espan_t_u(%ebx),%ecx
|
||||
addl %ecx,%edi // pdest = &pdestspan[scans->u];
|
||||
movl espan_t_count(%ebx),%ecx
|
||||
|
||||
//
|
||||
// now start the FDIV for the end of the span
|
||||
//
|
||||
cmpl $16,%ecx
|
||||
ja LSetupNotLast1
|
||||
|
||||
decl %ecx
|
||||
jz LCleanup1 // if only one pixel, no need to start an FDIV
|
||||
movl %ecx,spancountminus1
|
||||
|
||||
// finish up the s and t calcs
|
||||
fxch %st(1) // z*64k | 1/z | t/z | s/z
|
||||
|
||||
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
|
||||
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
|
||||
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
|
||||
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
|
||||
fxch %st(1) // s | t | 1/z | t/z | s/z
|
||||
fistpl s // 1/z | t | t/z | s/z
|
||||
fistpl t // 1/z | t/z | s/z
|
||||
|
||||
fildl spancountminus1
|
||||
|
||||
flds C(d_tdivzstepu) // C(d_tdivzstepu) | spancountminus1
|
||||
flds C(d_zistepu) // C(d_zistepu) | C(d_tdivzstepu) | spancountminus1
|
||||
fmul %st(2),%st(0) // C(d_zistepu)*scm1 | C(d_tdivzstepu) | scm1
|
||||
fxch %st(1) // C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
|
||||
fmul %st(2),%st(0) // C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
|
||||
fxch %st(2) // scm1 | C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1
|
||||
fmuls C(d_sdivzstepu) // C(d_sdivzstepu)*scm1 | C(d_zistepu)*scm1 |
|
||||
// C(d_tdivzstepu)*scm1
|
||||
fxch %st(1) // C(d_zistepu)*scm1 | C(d_sdivzstepu)*scm1 |
|
||||
// C(d_tdivzstepu)*scm1
|
||||
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
|
||||
fxch %st(1) // C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
|
||||
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1
|
||||
faddp %st(0),%st(3)
|
||||
|
||||
flds fp_64k
|
||||
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
|
||||
// overlap
|
||||
jmp LFDIVInFlight1
|
||||
|
||||
LCleanup1:
|
||||
// finish up the s and t calcs
|
||||
fxch %st(1) // z*64k | 1/z | t/z | s/z
|
||||
|
||||
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
|
||||
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
|
||||
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
|
||||
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
|
||||
fxch %st(1) // s | t | 1/z | t/z | s/z
|
||||
fistpl s // 1/z | t | t/z | s/z
|
||||
fistpl t // 1/z | t/z | s/z
|
||||
jmp LFDIVInFlight1
|
||||
|
||||
.align 4
|
||||
LSetupNotLast1:
|
||||
// finish up the s and t calcs
|
||||
fxch %st(1) // z*64k | 1/z | t/z | s/z
|
||||
|
||||
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
|
||||
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
|
||||
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
|
||||
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
|
||||
fxch %st(1) // s | t | 1/z | t/z | s/z
|
||||
fistpl s // 1/z | t | t/z | s/z
|
||||
fistpl t // 1/z | t/z | s/z
|
||||
|
||||
fadds zi16stepu
|
||||
fxch %st(2)
|
||||
fadds sdivz16stepu
|
||||
fxch %st(2)
|
||||
flds tdivz16stepu
|
||||
faddp %st(0),%st(2)
|
||||
flds fp_64k
|
||||
fdiv %st(1),%st(0) // z = 1/1/z
|
||||
// this is what we've gone to all this trouble to
|
||||
// overlap
|
||||
LFDIVInFlight1:
|
||||
|
||||
addl s,%esi
|
||||
addl t,%edx
|
||||
movl C(bbextents),%ebx
|
||||
movl C(bbextentt),%ebp
|
||||
cmpl %ebx,%esi
|
||||
ja LClampHighOrLow0
|
||||
LClampReentry0:
|
||||
movl %esi,s
|
||||
movl pbase,%ebx
|
||||
shll $16,%esi
|
||||
cmpl %ebp,%edx
|
||||
movl %esi,sfracf
|
||||
ja LClampHighOrLow1
|
||||
LClampReentry1:
|
||||
movl %edx,t
|
||||
movl s,%esi // sfrac = scans->sfrac;
|
||||
shll $16,%edx
|
||||
movl t,%eax // tfrac = scans->tfrac;
|
||||
sarl $16,%esi
|
||||
movl %edx,tfracf
|
||||
|
||||
//
|
||||
// calculate the texture starting address
|
||||
//
|
||||
sarl $16,%eax
|
||||
movl C(cachewidth),%edx
|
||||
imull %edx,%eax // (tfrac >> 16) * cachewidth
|
||||
addl %ebx,%esi
|
||||
addl %eax,%esi // psource = pbase + (sfrac >> 16) +
|
||||
// ((tfrac >> 16) * cachewidth);
|
||||
//
|
||||
// determine whether last span or not
|
||||
//
|
||||
cmpl $16,%ecx
|
||||
jna LLastSegment
|
||||
|
||||
//
|
||||
// not the last segment; do full 16-wide segment
|
||||
//
|
||||
LNotLastSegment:
|
||||
|
||||
//
|
||||
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
|
||||
// get there
|
||||
//
|
||||
|
||||
// pick up after the FDIV that was left in flight previously
|
||||
|
||||
fld %st(0) // duplicate it
|
||||
fmul %st(4),%st(0) // s = s/z * z
|
||||
fxch %st(1)
|
||||
fmul %st(3),%st(0) // t = t/z * z
|
||||
fxch %st(1)
|
||||
fistpl snext
|
||||
fistpl tnext
|
||||
movl snext,%eax
|
||||
movl tnext,%edx
|
||||
|
||||
movb (%esi),%bl // get first source texel
|
||||
subl $16,%ecx // count off this segments' pixels
|
||||
movl C(sadjust),%ebp
|
||||
movl %ecx,counttemp // remember count of remaining pixels
|
||||
|
||||
movl C(tadjust),%ecx
|
||||
movb %bl,(%edi) // store first dest pixel
|
||||
|
||||
addl %eax,%ebp
|
||||
addl %edx,%ecx
|
||||
|
||||
movl C(bbextents),%eax
|
||||
movl C(bbextentt),%edx
|
||||
|
||||
cmpl $4096,%ebp
|
||||
jl LClampLow2
|
||||
cmpl %eax,%ebp
|
||||
ja LClampHigh2
|
||||
LClampReentry2:
|
||||
|
||||
cmpl $4096,%ecx
|
||||
jl LClampLow3
|
||||
cmpl %edx,%ecx
|
||||
ja LClampHigh3
|
||||
LClampReentry3:
|
||||
|
||||
movl %ebp,snext
|
||||
movl %ecx,tnext
|
||||
|
||||
subl s,%ebp
|
||||
subl t,%ecx
|
||||
|
||||
//
|
||||
// set up advancetable
|
||||
//
|
||||
movl %ecx,%eax
|
||||
movl %ebp,%edx
|
||||
sarl $20,%eax // tstep >>= 16;
|
||||
jz LZero
|
||||
sarl $20,%edx // sstep >>= 16;
|
||||
movl C(cachewidth),%ebx
|
||||
imull %ebx,%eax
|
||||
jmp LSetUp1
|
||||
|
||||
LZero:
|
||||
sarl $20,%edx // sstep >>= 16;
|
||||
movl C(cachewidth),%ebx
|
||||
|
||||
LSetUp1:
|
||||
|
||||
addl %edx,%eax // add in sstep
|
||||
// (tstep >> 16) * cachewidth + (sstep >> 16);
|
||||
movl tfracf,%edx
|
||||
movl %eax,advancetable+4 // advance base in t
|
||||
addl %ebx,%eax // ((tstep >> 16) + 1) * cachewidth +
|
||||
// (sstep >> 16);
|
||||
shll $12,%ebp // left-justify sstep fractional part
|
||||
movl sfracf,%ebx
|
||||
shll $12,%ecx // left-justify tstep fractional part
|
||||
movl %eax,advancetable // advance extra in t
|
||||
|
||||
movl %ecx,tstep
|
||||
addl %ecx,%edx // advance tfrac fractional part by tstep frac
|
||||
|
||||
sbbl %ecx,%ecx // turn tstep carry into -1 (0 if none)
|
||||
addl %ebp,%ebx // advance sfrac fractional part by sstep frac
|
||||
adcl advancetable+4(,%ecx,4),%esi // point to next source texel
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb (%esi),%al
|
||||
addl %ebp,%ebx
|
||||
movb %al,1(%edi)
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,2(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,3(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,4(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,5(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,6(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,7(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
|
||||
//
|
||||
// start FDIV for end of next segment in flight, so it can overlap
|
||||
//
|
||||
movl counttemp,%ecx
|
||||
cmpl $16,%ecx // more than one segment after this?
|
||||
ja LSetupNotLast2 // yes
|
||||
|
||||
decl %ecx
|
||||
jz LFDIVInFlight2 // if only one pixel, no need to start an FDIV
|
||||
movl %ecx,spancountminus1
|
||||
fildl spancountminus1
|
||||
|
||||
flds C(d_zistepu) // C(d_zistepu) | spancountminus1
|
||||
fmul %st(1),%st(0) // C(d_zistepu)*scm1 | scm1
|
||||
flds C(d_tdivzstepu) // C(d_tdivzstepu) | C(d_zistepu)*scm1 | scm1
|
||||
fmul %st(2),%st(0) // C(d_tdivzstepu)*scm1 | C(d_zistepu)*scm1 | scm1
|
||||
fxch %st(1) // C(d_zistepu)*scm1 | C(d_tdivzstepu)*scm1 | scm1
|
||||
faddp %st(0),%st(3) // C(d_tdivzstepu)*scm1 | scm1
|
||||
fxch %st(1) // scm1 | C(d_tdivzstepu)*scm1
|
||||
fmuls C(d_sdivzstepu) // C(d_sdivzstepu)*scm1 | C(d_tdivzstepu)*scm1
|
||||
fxch %st(1) // C(d_tdivzstepu)*scm1 | C(d_sdivzstepu)*scm1
|
||||
faddp %st(0),%st(3) // C(d_sdivzstepu)*scm1
|
||||
flds fp_64k // 64k | C(d_sdivzstepu)*scm1
|
||||
fxch %st(1) // C(d_sdivzstepu)*scm1 | 64k
|
||||
faddp %st(0),%st(4) // 64k
|
||||
|
||||
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
|
||||
// overlap
|
||||
jmp LFDIVInFlight2
|
||||
|
||||
.align 4
|
||||
LSetupNotLast2:
|
||||
fadds zi16stepu
|
||||
fxch %st(2)
|
||||
fadds sdivz16stepu
|
||||
fxch %st(2)
|
||||
flds tdivz16stepu
|
||||
faddp %st(0),%st(2)
|
||||
flds fp_64k
|
||||
fdiv %st(1),%st(0) // z = 1/1/z
|
||||
// this is what we've gone to all this trouble to
|
||||
// overlap
|
||||
LFDIVInFlight2:
|
||||
movl %ecx,counttemp
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,8(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,9(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,10(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,11(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,12(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,13(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,14(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl $16,%edi
|
||||
movl %edx,tfracf
|
||||
movl snext,%edx
|
||||
movl %ebx,sfracf
|
||||
movl tnext,%ebx
|
||||
movl %edx,s
|
||||
movl %ebx,t
|
||||
|
||||
movl counttemp,%ecx // retrieve count
|
||||
|
||||
//
|
||||
// determine whether last span or not
|
||||
//
|
||||
cmpl $16,%ecx // are there multiple segments remaining?
|
||||
movb %al,-1(%edi)
|
||||
ja LNotLastSegment // yes
|
||||
|
||||
//
|
||||
// last segment of scan
|
||||
//
|
||||
LLastSegment:
|
||||
|
||||
//
|
||||
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
|
||||
// get there. The number of pixels left is variable, and we want to land on the
|
||||
// last pixel, not step one past it, so we can't run into arithmetic problems
|
||||
//
|
||||
testl %ecx,%ecx
|
||||
jz LNoSteps // just draw the last pixel and we're done
|
||||
|
||||
// pick up after the FDIV that was left in flight previously
|
||||
|
||||
|
||||
fld %st(0) // duplicate it
|
||||
fmul %st(4),%st(0) // s = s/z * z
|
||||
fxch %st(1)
|
||||
fmul %st(3),%st(0) // t = t/z * z
|
||||
fxch %st(1)
|
||||
fistpl snext
|
||||
fistpl tnext
|
||||
|
||||
movb (%esi),%al // load first texel in segment
|
||||
movl C(tadjust),%ebx
|
||||
movb %al,(%edi) // store first pixel in segment
|
||||
movl C(sadjust),%eax
|
||||
|
||||
addl snext,%eax
|
||||
addl tnext,%ebx
|
||||
|
||||
movl C(bbextents),%ebp
|
||||
movl C(bbextentt),%edx
|
||||
|
||||
cmpl $4096,%eax
|
||||
jl LClampLow4
|
||||
cmpl %ebp,%eax
|
||||
ja LClampHigh4
|
||||
LClampReentry4:
|
||||
movl %eax,snext
|
||||
|
||||
cmpl $4096,%ebx
|
||||
jl LClampLow5
|
||||
cmpl %edx,%ebx
|
||||
ja LClampHigh5
|
||||
LClampReentry5:
|
||||
|
||||
cmpl $1,%ecx // don't bother
|
||||
je LOnlyOneStep // if two pixels in segment, there's only one step,
|
||||
// of the segment length
|
||||
subl s,%eax
|
||||
subl t,%ebx
|
||||
|
||||
addl %eax,%eax // convert to 15.17 format so multiply by 1.31
|
||||
addl %ebx,%ebx // reciprocal yields 16.48
|
||||
|
||||
imull reciprocal_table_16-8(,%ecx,4) // sstep = (snext - s) /
|
||||
// (spancount-1)
|
||||
movl %edx,%ebp
|
||||
|
||||
movl %ebx,%eax
|
||||
imull reciprocal_table_16-8(,%ecx,4) // tstep = (tnext - t) /
|
||||
// (spancount-1)
|
||||
LSetEntryvec:
|
||||
//
|
||||
// set up advancetable
|
||||
//
|
||||
movl entryvec_table_16(,%ecx,4),%ebx
|
||||
movl %edx,%eax
|
||||
movl %ebx,jumptemp // entry point into code for RET later
|
||||
movl %ebp,%ecx
|
||||
sarl $16,%edx // tstep >>= 16;
|
||||
movl C(cachewidth),%ebx
|
||||
sarl $16,%ecx // sstep >>= 16;
|
||||
imull %ebx,%edx
|
||||
|
||||
addl %ecx,%edx // add in sstep
|
||||
// (tstep >> 16) * cachewidth + (sstep >> 16);
|
||||
movl tfracf,%ecx
|
||||
movl %edx,advancetable+4 // advance base in t
|
||||
addl %ebx,%edx // ((tstep >> 16) + 1) * cachewidth +
|
||||
// (sstep >> 16);
|
||||
shll $16,%ebp // left-justify sstep fractional part
|
||||
movl sfracf,%ebx
|
||||
shll $16,%eax // left-justify tstep fractional part
|
||||
movl %edx,advancetable // advance extra in t
|
||||
|
||||
movl %eax,tstep
|
||||
movl %ecx,%edx
|
||||
addl %eax,%edx
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
jmp *jumptemp // jump to the number-of-pixels handler
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
LNoSteps:
|
||||
movb (%esi),%al // load first texel in segment
|
||||
subl $15,%edi // adjust for hardwired offset
|
||||
jmp LEndSpan
|
||||
|
||||
|
||||
LOnlyOneStep:
|
||||
subl s,%eax
|
||||
subl t,%ebx
|
||||
movl %eax,%ebp
|
||||
movl %ebx,%edx
|
||||
jmp LSetEntryvec
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
.globl Entry2_16, Entry3_16, Entry4_16, Entry5_16
|
||||
.globl Entry6_16, Entry7_16, Entry8_16, Entry9_16
|
||||
.globl Entry10_16, Entry11_16, Entry12_16, Entry13_16
|
||||
.globl Entry14_16, Entry15_16, Entry16_16
|
||||
|
||||
Entry2_16:
|
||||
subl $14,%edi // adjust for hardwired offsets
|
||||
movb (%esi),%al
|
||||
jmp LEntry2_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry3_16:
|
||||
subl $13,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
jmp LEntry3_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry4_16:
|
||||
subl $12,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry4_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry5_16:
|
||||
subl $11,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry5_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry6_16:
|
||||
subl $10,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry6_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry7_16:
|
||||
subl $9,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry7_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry8_16:
|
||||
subl $8,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry8_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry9_16:
|
||||
subl $7,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry9_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry10_16:
|
||||
subl $6,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry10_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry11_16:
|
||||
subl $5,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry11_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry12_16:
|
||||
subl $4,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry12_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry13_16:
|
||||
subl $3,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry13_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry14_16:
|
||||
subl $2,%edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry14_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry15_16:
|
||||
decl %edi // adjust for hardwired offsets
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
jmp LEntry15_16
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
Entry16_16:
|
||||
addl %eax,%edx
|
||||
movb (%esi),%al
|
||||
sbbl %ecx,%ecx
|
||||
addl %ebp,%ebx
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
|
||||
addl tstep,%edx
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,1(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry15_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,2(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry14_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,3(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry13_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,4(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry12_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,5(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry11_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,6(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry10_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,7(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry9_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,8(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry8_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,9(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry7_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,10(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry6_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,11(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry5_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,12(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
addl tstep,%edx
|
||||
LEntry4_16:
|
||||
sbbl %ecx,%ecx
|
||||
movb %al,13(%edi)
|
||||
addl %ebp,%ebx
|
||||
movb (%esi),%al
|
||||
adcl advancetable+4(,%ecx,4),%esi
|
||||
LEntry3_16:
|
||||
movb %al,14(%edi)
|
||||
movb (%esi),%al
|
||||
LEntry2_16:
|
||||
|
||||
LEndSpan:
|
||||
|
||||
//
|
||||
// clear s/z, t/z, 1/z from FP stack
|
||||
//
|
||||
fstp %st(0)
|
||||
fstp %st(0)
|
||||
fstp %st(0)
|
||||
|
||||
movl pspantemp,%ebx // restore spans pointer
|
||||
movl espan_t_pnext(%ebx),%ebx // point to next span
|
||||
testl %ebx,%ebx // any more spans?
|
||||
movb %al,15(%edi)
|
||||
jnz LSpanLoop // more spans
|
||||
|
||||
popl %ebx // restore register variables
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp // restore the caller's stack frame
|
||||
ret
|
||||
|
||||
#endif // id386
|
435
engine/sw/d_edge.c
Normal file
435
engine/sw/d_edge.c
Normal file
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_edge.c
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "d_local.h"
|
||||
|
||||
static int miplevel;
|
||||
|
||||
float scale_for_mip;
|
||||
int screenwidth;
|
||||
int ubasestep, errorterm, erroradjustup, erroradjustdown;
|
||||
int vstartscan;
|
||||
|
||||
// FIXME: should go away
|
||||
extern void R_RotateBmodel (void);
|
||||
extern void R_TransformFrustum (void);
|
||||
|
||||
vec3_t transformed_modelorg;
|
||||
|
||||
/*
|
||||
==============
|
||||
D_DrawPoly
|
||||
|
||||
==============
|
||||
*/
|
||||
void D_DrawPoly (void)
|
||||
{
|
||||
// this driver takes spans, not polygons
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
D_MipLevelForScale
|
||||
=============
|
||||
*/
|
||||
int D_MipLevelForScale (float scale)
|
||||
{
|
||||
int lmiplevel;
|
||||
|
||||
if (scale >= d_scalemip[0] )
|
||||
lmiplevel = 0;
|
||||
else if (scale >= d_scalemip[1] )
|
||||
lmiplevel = 1;
|
||||
else if (scale >= d_scalemip[2] )
|
||||
lmiplevel = 2;
|
||||
else
|
||||
lmiplevel = 3;
|
||||
|
||||
if (lmiplevel < d_minmip)
|
||||
lmiplevel = d_minmip;
|
||||
|
||||
return lmiplevel;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
D_DrawSolidSurface
|
||||
==============
|
||||
*/
|
||||
|
||||
// FIXME: clean this up
|
||||
|
||||
void D_DrawSolidSurface (surf_t *surf, int color)
|
||||
{
|
||||
espan_t *span;
|
||||
qbyte *pdest;
|
||||
int u, u2, pix;
|
||||
|
||||
if (r_pixbytes == 4)
|
||||
{
|
||||
unsigned int *p32dest;
|
||||
pix = d_8to32table[color];
|
||||
for (span=surf->spans ; span ; span=span->pnext)
|
||||
{
|
||||
p32dest = (unsigned int *)d_viewbuffer + screenwidth*span->v;
|
||||
u = span->u;
|
||||
u2 = span->u + span->count - 1;
|
||||
p32dest[u] = pix;
|
||||
|
||||
for ( ; u <= u2 ; u++)
|
||||
p32dest[u] = pix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pix = (color<<24) | (color<<16) | (color<<8) | color;
|
||||
for (span=surf->spans ; span ; span=span->pnext)
|
||||
{
|
||||
pdest = (qbyte *)d_viewbuffer + screenwidth*span->v;
|
||||
u = span->u;
|
||||
u2 = span->u + span->count - 1;
|
||||
((qbyte *)pdest)[u] = pix;
|
||||
|
||||
if (u2 - u < 8)
|
||||
{
|
||||
for (u++ ; u <= u2 ; u++)
|
||||
((qbyte *)pdest)[u] = pix;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u++ ; u & 3 ; u++)
|
||||
((qbyte *)pdest)[u] = pix;
|
||||
|
||||
u2 -= 3;
|
||||
for ( ; u <= u2 ; u+=4)
|
||||
*(int *)((qbyte *)pdest + u) = pix;
|
||||
u2 += 3;
|
||||
for ( ; u <= u2 ; u++)
|
||||
((qbyte *)pdest)[u] = pix;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
D_CalcGradients
|
||||
==============
|
||||
*/
|
||||
void D_CalcGradients (msurface_t *pface)
|
||||
{
|
||||
mplane_t *pplane;
|
||||
float mipscale;
|
||||
vec3_t p_temp1;
|
||||
vec3_t p_saxis, p_taxis;
|
||||
float t;
|
||||
|
||||
pplane = pface->plane;
|
||||
|
||||
mipscale = 1.0 / (float)(1 << miplevel);
|
||||
|
||||
TransformVector (pface->texinfo->vecs[0], p_saxis);
|
||||
TransformVector (pface->texinfo->vecs[1], p_taxis);
|
||||
|
||||
t = xscaleinv * mipscale;
|
||||
d_sdivzstepu = p_saxis[0] * t;
|
||||
d_tdivzstepu = p_taxis[0] * t;
|
||||
|
||||
t = yscaleinv * mipscale;
|
||||
d_sdivzstepv = -p_saxis[1] * t;
|
||||
d_tdivzstepv = -p_taxis[1] * t;
|
||||
|
||||
d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
|
||||
ycenter * d_sdivzstepv;
|
||||
d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
|
||||
ycenter * d_tdivzstepv;
|
||||
|
||||
VectorScale (transformed_modelorg, mipscale, p_temp1);
|
||||
|
||||
t = 0x10000*mipscale;
|
||||
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
|
||||
((pface->texturemins[0] << 16) >> miplevel)
|
||||
+ pface->texinfo->vecs[0][3]*t;
|
||||
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
|
||||
((pface->texturemins[1] << 16) >> miplevel)
|
||||
+ pface->texinfo->vecs[1][3]*t;
|
||||
|
||||
//
|
||||
// -1 (-epsilon) so we never wander off the edge of the texture
|
||||
//
|
||||
bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
|
||||
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
D_DrawSurfaces
|
||||
==============
|
||||
*/
|
||||
void D_DrawSurfaces (void)
|
||||
{
|
||||
void D_DrawSpans32 (espan_t *pspan);
|
||||
surf_t *s;
|
||||
msurface_t *pface;
|
||||
surfcache_t *pcurrentcache;
|
||||
vec3_t world_transformed_modelorg;
|
||||
vec3_t local_modelorg;
|
||||
extern int r_dosirds;
|
||||
|
||||
currententity = &r_worldentity;
|
||||
TransformVector (modelorg, transformed_modelorg);
|
||||
VectorCopy (transformed_modelorg, world_transformed_modelorg);
|
||||
|
||||
if (r_dosirds) //depth only
|
||||
{
|
||||
for (s = &surfaces[1] ; s<surface_p ; s++)
|
||||
{
|
||||
if (!s->spans)
|
||||
continue;
|
||||
|
||||
d_zistepu = s->d_zistepu;
|
||||
d_zistepv = s->d_zistepv;
|
||||
d_ziorigin = s->d_ziorigin;
|
||||
D_DrawZSpans (s->spans);
|
||||
}
|
||||
}
|
||||
// TODO: could preset a lot of this at mode set time
|
||||
else if (r_drawflat.value)
|
||||
{
|
||||
for (s = &surfaces[1] ; s<surface_p ; s++)
|
||||
{
|
||||
if (!s->spans)
|
||||
continue;
|
||||
|
||||
d_zistepu = s->d_zistepu;
|
||||
d_zistepv = s->d_zistepv;
|
||||
d_ziorigin = s->d_ziorigin;
|
||||
|
||||
#ifdef __alpha__
|
||||
D_DrawSolidSurface (s, (int)((long)s->data & 0xFF));
|
||||
#else
|
||||
D_DrawSolidSurface (s, (int)s->data & 0xFF);
|
||||
#endif
|
||||
D_DrawZSpans (s->spans);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (s = &surfaces[1] ; s<surface_p ; s++)
|
||||
{
|
||||
if (!s->spans)
|
||||
continue;
|
||||
|
||||
r_drawnpolycount++;
|
||||
|
||||
d_zistepu = s->d_zistepu;
|
||||
d_zistepv = s->d_zistepv;
|
||||
d_ziorigin = s->d_ziorigin;
|
||||
|
||||
if (s->flags & SURF_DRAWSKY)
|
||||
{
|
||||
if (r_worldentity.model->fromgame == fg_halflife)
|
||||
continue;
|
||||
if (!r_skymade)
|
||||
{
|
||||
R_MakeSky ();
|
||||
}
|
||||
|
||||
if (r_pixbytes == 4)
|
||||
D_DrawSkyScans32 (s->spans);
|
||||
else if (r_pixbytes == 2)
|
||||
D_DrawSkyScans16 (s->spans);
|
||||
else
|
||||
D_DrawSkyScans8 (s->spans);
|
||||
D_DrawZSpans (s->spans);
|
||||
}
|
||||
else if (s->flags & SURF_DRAWSKYBOX)
|
||||
{
|
||||
pface = s->data;
|
||||
miplevel = 0;
|
||||
if (!pface->texinfo->texture)
|
||||
{
|
||||
d_zistepu = 0;
|
||||
d_zistepv = 0;
|
||||
d_ziorigin = -0.9;
|
||||
|
||||
D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
|
||||
D_DrawZSpans (s->spans);
|
||||
continue;
|
||||
}
|
||||
cacheblock = (qbyte *)pface->texinfo->texture + pface->texinfo->texture->offsets[0];
|
||||
cachewidth = 256;
|
||||
|
||||
d_zistepu = s->d_zistepu;
|
||||
d_zistepv = s->d_zistepv;
|
||||
d_ziorigin = s->d_ziorigin;
|
||||
|
||||
D_CalcGradients (pface);
|
||||
|
||||
if (r_pixbytes == 2)
|
||||
D_DrawSpans16From8(s->spans);
|
||||
else
|
||||
(*d_drawspans) (s->spans);
|
||||
// D_DrawSolidSurface (s, (int)15);
|
||||
|
||||
// set up a gradient for the background surface that places it
|
||||
// effectively at infinity distance from the viewpoint
|
||||
d_zistepu = 0;
|
||||
d_zistepv = 0;
|
||||
d_ziorigin = -0.9;
|
||||
|
||||
D_DrawZSpans (s->spans);
|
||||
}
|
||||
else if (s->flags & SURF_DRAWBACKGROUND)
|
||||
{
|
||||
// set up a gradient for the background surface that places it
|
||||
// effectively at infinity distance from the viewpoint
|
||||
d_zistepu = 0;
|
||||
d_zistepv = 0;
|
||||
d_ziorigin = -0.9;
|
||||
|
||||
D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
|
||||
D_DrawZSpans (s->spans);
|
||||
}
|
||||
else if (s->flags & SURF_DRAWTURB)
|
||||
{
|
||||
pface = s->data;
|
||||
miplevel = 0;
|
||||
cacheblock = (pixel_t *)
|
||||
((qbyte *)pface->texinfo->texture +
|
||||
pface->texinfo->texture->offsets[0]);
|
||||
cachewidth = 64;
|
||||
cacheheight = 64;
|
||||
|
||||
if (s->insubmodel)
|
||||
{
|
||||
// FIXME: we don't want to do all this for every polygon!
|
||||
// TODO: store once at start of frame
|
||||
currententity = s->entity; //FIXME: make this passed in to
|
||||
// R_RotateBmodel ()
|
||||
VectorSubtract (r_origin, currententity->origin,
|
||||
local_modelorg);
|
||||
TransformVector (local_modelorg, transformed_modelorg);
|
||||
|
||||
R_RotateBmodel (); // FIXME: don't mess with the frustum,
|
||||
// make entity passed in
|
||||
}
|
||||
|
||||
D_CalcGradients (pface);
|
||||
|
||||
if (r_pixbytes == 4)
|
||||
Turbulent32 (s->spans);
|
||||
else if (r_pixbytes == 2)
|
||||
Turbulent16 (s->spans);
|
||||
else
|
||||
Turbulent8 (s->spans);
|
||||
D_DrawZSpans (s->spans);
|
||||
|
||||
if (s->insubmodel)
|
||||
{
|
||||
//
|
||||
// restore the old drawing state
|
||||
// FIXME: we don't want to do this every time!
|
||||
// TODO: speed up
|
||||
//
|
||||
currententity = &r_worldentity;
|
||||
VectorCopy (world_transformed_modelorg,
|
||||
transformed_modelorg);
|
||||
VectorCopy (base_vpn, vpn);
|
||||
VectorCopy (base_vup, vup);
|
||||
VectorCopy (base_vright, vright);
|
||||
VectorCopy (base_modelorg, modelorg);
|
||||
R_TransformFrustum ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->insubmodel)
|
||||
{
|
||||
// FIXME: we don't want to do all this for every polygon!
|
||||
// TODO: store once at start of frame
|
||||
currententity = s->entity; //FIXME: make this passed in to
|
||||
// R_RotateBmodel ()
|
||||
VectorSubtract (r_origin, currententity->origin, local_modelorg);
|
||||
TransformVector (local_modelorg, transformed_modelorg);
|
||||
|
||||
R_RotateBmodel (); // FIXME: don't mess with the frustum,
|
||||
// make entity passed in
|
||||
}
|
||||
|
||||
pface = s->data;
|
||||
|
||||
if (pface->flags & SURF_BULLETEN)
|
||||
{
|
||||
miplevel = 0;
|
||||
if (pface->cachespots[miplevel])
|
||||
pface->cachespots[miplevel]->texture = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
|
||||
* pface->texinfo->mipadjust);
|
||||
}
|
||||
|
||||
// FIXME: make this passed in to D_CacheSurface
|
||||
pcurrentcache = D_CacheSurface (pface, miplevel);
|
||||
|
||||
cacheblock = (pixel_t *)pcurrentcache->data;
|
||||
cachewidth = pcurrentcache->width;
|
||||
|
||||
cacheheight = pcurrentcache->height;
|
||||
|
||||
|
||||
// if (s->entity == &r_worldentity) //temporary
|
||||
// {
|
||||
D_CalcGradients (pface);
|
||||
(*d_drawspans) (s->spans);
|
||||
|
||||
if (d_drawspans != D_DrawSpans32)
|
||||
D_DrawZSpans (s->spans);
|
||||
// }
|
||||
|
||||
if (s->insubmodel)
|
||||
{
|
||||
//
|
||||
// restore the old drawing state
|
||||
// FIXME: we don't want to do this every time!
|
||||
// TODO: speed up
|
||||
//
|
||||
VectorCopy (world_transformed_modelorg,
|
||||
transformed_modelorg);
|
||||
VectorCopy (base_vpn, vpn);
|
||||
VectorCopy (base_vup, vup);
|
||||
VectorCopy (base_vright, vright);
|
||||
VectorCopy (base_modelorg, modelorg);
|
||||
R_TransformFrustum ();
|
||||
currententity = &r_worldentity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
88
engine/sw/d_fill.c
Normal file
88
engine/sw/d_fill.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_clear: clears a specified rectangle to the specified color
|
||||
|
||||
#include "quakedef.h"
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
D_FillRect
|
||||
================
|
||||
*/
|
||||
void D_FillRect (vrect_t *rect, int color)
|
||||
{
|
||||
int rx, ry, rwidth, rheight;
|
||||
unsigned char *dest;
|
||||
unsigned *ldest;
|
||||
|
||||
rx = rect->x;
|
||||
ry = rect->y;
|
||||
rwidth = rect->width;
|
||||
rheight = rect->height;
|
||||
|
||||
if (rx < 0)
|
||||
{
|
||||
rwidth += rx;
|
||||
rx = 0;
|
||||
}
|
||||
if (ry < 0)
|
||||
{
|
||||
rheight += ry;
|
||||
ry = 0;
|
||||
}
|
||||
if (rx+rwidth > vid.width)
|
||||
rwidth = vid.width - rx;
|
||||
if (ry+rheight > vid.height)
|
||||
rheight = vid.height - rx;
|
||||
|
||||
if (rwidth < 1 || rheight < 1)
|
||||
return;
|
||||
|
||||
dest = ((qbyte *)vid.buffer + ry*vid.rowbytes + rx);
|
||||
|
||||
if (((rwidth & 0x03) == 0) && (((long)dest & 0x03) == 0))
|
||||
{
|
||||
// faster aligned dword clear
|
||||
ldest = (unsigned *)dest;
|
||||
color += color << 16;
|
||||
|
||||
rwidth >>= 2;
|
||||
color += color << 8;
|
||||
|
||||
for (ry=0 ; ry<rheight ; ry++)
|
||||
{
|
||||
for (rx=0 ; rx<rwidth ; rx++)
|
||||
ldest[rx] = color;
|
||||
ldest = (unsigned *)((qbyte*)ldest + vid.rowbytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// slower byte-by-byte clear for unaligned cases
|
||||
for (ry=0 ; ry<rheight ; ry++)
|
||||
{
|
||||
for (rx=0 ; rx<rwidth ; rx++)
|
||||
dest[rx] = color;
|
||||
dest += vid.rowbytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
226
engine/sw/d_iface.h
Normal file
226
engine/sw/d_iface.h
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_iface.h: interface header file for rasterization driver modules
|
||||
|
||||
#define WARP_WIDTH 320
|
||||
#define WARP_HEIGHT 200
|
||||
|
||||
#define MAX_LBM_HEIGHT 480
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float u, v;
|
||||
float s, t;
|
||||
float zi;
|
||||
} emitpoint_t;
|
||||
|
||||
#include "particles.h"
|
||||
|
||||
typedef struct polyvert_s {
|
||||
float u, v, zi, s, t;
|
||||
} polyvert_t;
|
||||
|
||||
typedef struct polydesc_s {
|
||||
int numverts;
|
||||
float nearzi;
|
||||
msurface_t *pcurrentface;
|
||||
polyvert_t *pverts;
|
||||
} polydesc_t;
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
typedef struct finalvert_s {
|
||||
int v[6]; // u, v, s, t, l, 1/z
|
||||
int flags;
|
||||
float reserved;
|
||||
} finalvert_t;
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
typedef struct
|
||||
{
|
||||
void *pskin;
|
||||
maliasskindesc_t *pskindesc;
|
||||
int skinwidth;
|
||||
int skinheight;
|
||||
mtriangle_t *ptriangles;
|
||||
finalvert_t *pfinalverts;
|
||||
int numtriangles;
|
||||
int drawtype;
|
||||
mstvert_t *pstverts;
|
||||
//int seamfixupX16;
|
||||
} affinetridesc_t;
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
typedef struct {
|
||||
float u, v, zi, color;
|
||||
} screenpart_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int nump;
|
||||
emitpoint_t *pverts; // there's room for an extra element at [nump],
|
||||
// if the driver wants to duplicate element [0] at
|
||||
// element [nump] to avoid dealing with wrapping
|
||||
mspriteframe_t *pspriteframe;
|
||||
vec3_t vup, vright, vpn; // in worldspace
|
||||
float nearzi;
|
||||
} spritedesc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int u, v;
|
||||
float zi;
|
||||
int color;
|
||||
} zpointdesc_t;
|
||||
|
||||
extern cvar_t r_drawflat;
|
||||
extern int d_spanpixcount;
|
||||
extern int r_framecount; // sequence # of current frame since Quake
|
||||
// started
|
||||
extern qboolean r_drawpolys; // 1 if driver wants clipped polygons
|
||||
// rather than a span list
|
||||
extern qboolean r_drawculledpolys; // 1 if driver wants clipped polygons that
|
||||
// have been culled by the edge list
|
||||
extern qboolean r_worldpolysbacktofront; // 1 if driver wants polygons
|
||||
// delivered back to front rather
|
||||
// than front to back
|
||||
extern qboolean r_recursiveaffinetriangles; // true if a driver wants to use
|
||||
// recursive triangular subdivison
|
||||
// and vertex drawing via
|
||||
// D_PolysetDrawFinalVerts() past
|
||||
// a certain distance (normally
|
||||
// only used by the software
|
||||
// driver)
|
||||
extern float r_aliasuvscale; // scale-up factor for screen u and v
|
||||
// on Alias vertices passed to driver
|
||||
|
||||
//16 bit rendering.
|
||||
extern int redbits, redshift;
|
||||
extern int greenbits, greenshift;
|
||||
extern int bluebits, blueshift;
|
||||
|
||||
|
||||
extern int r_pixbytes;
|
||||
extern qboolean r_dowarp;
|
||||
|
||||
extern affinetridesc_t r_affinetridesc;
|
||||
extern spritedesc_t r_spritedesc;
|
||||
extern zpointdesc_t r_zpointdesc;
|
||||
extern polydesc_t r_polydesc;
|
||||
|
||||
extern int d_con_indirect; // if 0, Quake will draw console directly
|
||||
// to vid.buffer; if 1, Quake will
|
||||
// draw console via D_DrawRect. Must be
|
||||
// defined by driver
|
||||
|
||||
extern vec3_t r_pright, r_pup, r_ppn;
|
||||
|
||||
|
||||
void D_Aff8Patch (void *pcolormap);
|
||||
void GLD_BeginDirectRect (int x, int y, qbyte *pbitmap, int width, int height);
|
||||
void SWD_BeginDirectRect (int x, int y, qbyte *pbitmap, int width, int height);
|
||||
void D_DisableBackBufferAccess (void);
|
||||
void GLD_EndDirectRect (int x, int y, int width, int height);
|
||||
void SWD_EndDirectRect (int x, int y, int width, int height);
|
||||
void D_PolysetDraw (void);
|
||||
void D_PolysetDraw16 (void);
|
||||
void D_PolysetDraw32 (void);
|
||||
void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts);
|
||||
void D_PolysetDrawFinalVerts32Trans (finalvert_t *fv, int numverts);
|
||||
void D_DrawParticle (particle_t *pparticle);
|
||||
void D_DrawPoly (void);
|
||||
void D_DrawSprite (void);
|
||||
void D_DrawSurfaces (void);
|
||||
void D_DrawZPoint (void);
|
||||
void D_ClearDepth(void);
|
||||
void D_EnableBackBufferAccess (void);
|
||||
void D_EndParticles (void);
|
||||
void D_Init (void);
|
||||
void D_ViewChanged (void);
|
||||
void D_SetupFrame (void);
|
||||
void D_StartParticles (void);
|
||||
void D_TurnZOn (void);
|
||||
void D_WarpScreen (void);
|
||||
|
||||
void D_FillRect (vrect_t *vrect, int color);
|
||||
void D_DrawRect (void);
|
||||
void D_UpdateRects (vrect_t *prect);
|
||||
|
||||
// currently for internal use only, and should be a do-nothing function in
|
||||
// hardware drivers
|
||||
// FIXME: this should go away
|
||||
void D_PolysetUpdateTables (void);
|
||||
|
||||
// these are currently for internal use only, and should not be used by drivers
|
||||
extern int r_skydirect;
|
||||
extern qbyte *r_skysource;
|
||||
|
||||
// transparency types for D_DrawRect ()
|
||||
#define DR_SOLID 0
|
||||
#define DR_TRANSPARENT 1
|
||||
|
||||
// !!! must be kept the same as in quakeasm.h !!!
|
||||
#define TRANSPARENT_COLOR 0xFF
|
||||
|
||||
extern void *acolormap; // FIXME: should go away
|
||||
|
||||
//=======================================================================//
|
||||
|
||||
// callbacks to Quake
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pixel_t *surfdat; // destination for generated surface
|
||||
int rowbytes; // destination logical width in bytes
|
||||
msurface_t *surf; // description for surface to generate
|
||||
fixed8_t lightadj[MAXLIGHTMAPS];
|
||||
// adjust for lightmap levels for dynamic lighting
|
||||
texture_t *texture; // corrected for animating textures
|
||||
int surfmip; // mipmapped ratio of surface texels / world pixels
|
||||
int surfwidth; // in mipmapped texels
|
||||
int surfheight; // in mipmapped texels
|
||||
} drawsurf_t;
|
||||
|
||||
extern drawsurf_t r_drawsurf;
|
||||
|
||||
void R_DrawSurface (void);
|
||||
void R_DrawSurface32 (void);
|
||||
void R_GenTile (msurface_t *psurf, void *pdest);
|
||||
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
#define TURB_TEX_SIZE 64 // base turbulent texture size
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
#define CYCLE 128 // turbulent cycle size
|
||||
|
||||
#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf
|
||||
|
||||
#define SKYSHIFT 7
|
||||
#define SKYSIZE (1 << SKYSHIFT)
|
||||
#define SKYMASK (SKYSIZE - 1)
|
||||
|
||||
extern float skyspeed, skyspeed2;
|
||||
extern float skytime;
|
||||
|
||||
extern int c_surf;
|
||||
extern vrect_t scr_vrect;
|
||||
|
||||
extern qbyte *r_warpbuffer;
|
||||
|
97
engine/sw/d_ifacea.h
Normal file
97
engine/sw/d_ifacea.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
//
|
||||
// d_ifacea.h
|
||||
//
|
||||
// Include file for asm driver interface.
|
||||
//
|
||||
|
||||
//
|
||||
// !!! note that this file must match the corresponding C structures in
|
||||
// d_iface.h at all times !!!
|
||||
//
|
||||
|
||||
// !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
//#define ALIAS_ONSEAM 0x0020
|
||||
|
||||
// !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
#define TURB_TEX_SIZE 64 // base turbulent texture size
|
||||
|
||||
// !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
#define CYCLE 128
|
||||
|
||||
// !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
#define MAXHEIGHT 1024
|
||||
|
||||
// !!! if this is changed, it must be changed in quakedef.h too !!!
|
||||
#define CACHE_SIZE 32 // used to align key data structures
|
||||
|
||||
// particle_t structure
|
||||
// !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
// driver-usable fields
|
||||
#define pt_org 0
|
||||
#define pt_color 12
|
||||
// drivers never touch the following fields
|
||||
#define pt_next 16
|
||||
#define pt_vel 20
|
||||
#define pt_ramp 32
|
||||
#define pt_die 36
|
||||
#define pt_type 40
|
||||
#define pt_size 44
|
||||
|
||||
#define PARTICLE_Z_CLIP 8.0
|
||||
|
||||
// finalvert_t structure
|
||||
// !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
#define fv_v 0 // !!! if this is moved, cases where the !!!
|
||||
// !!! address of this field is pushed in !!!
|
||||
// !!! d_polysa.s must be changed !!!
|
||||
#define fv_flags 24
|
||||
#define fv_reserved 28
|
||||
#define fv_size 32
|
||||
#define fv_shift 5
|
||||
|
||||
|
||||
// stvert_t structure
|
||||
// !!! if this is changed, it must be changed in modelgen.h too !!!
|
||||
#define stv_s 4
|
||||
#define stv_t 8
|
||||
#define stv_size 12
|
||||
|
||||
|
||||
// trivertx_t structure
|
||||
// !!! if this is changed, it must be changed in modelgen.h too !!!
|
||||
#define tv_v 0
|
||||
#define tv_lightnormalindex 3
|
||||
#define tv_size 4
|
||||
|
||||
// affinetridesc_t structure
|
||||
// !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
#define atd_pskin 0
|
||||
#define atd_pskindesc 4
|
||||
#define atd_skinwidth 8
|
||||
#define atd_skinheight 12
|
||||
#define atd_ptriangles 16
|
||||
#define atd_pfinalverts 20
|
||||
#define atd_numtriangles 24
|
||||
#define atd_drawtype 28
|
||||
#define atd_seamfixupX16 32
|
||||
#define atd_size 36
|
||||
|
198
engine/sw/d_init.c
Normal file
198
engine/sw/d_init.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_init.c: rasterization driver initialization
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "d_local.h"
|
||||
|
||||
#define NUM_MIPS 4
|
||||
|
||||
cvar_t d_subdiv16 = {"d_subdiv16", "1"};
|
||||
cvar_t d_mipcap = {"d_mipcap", "0"};
|
||||
cvar_t d_mipscale = {"d_mipscale", "0.5"};
|
||||
extern cvar_t d_smooth;
|
||||
|
||||
surfcache_t *d_initial_rover;
|
||||
qboolean d_roverwrapped;
|
||||
int d_minmip;
|
||||
float d_scalemip[NUM_MIPS-1];
|
||||
|
||||
static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
|
||||
|
||||
extern int d_aflatcolor;
|
||||
|
||||
void (*d_drawspans) (espan_t *pspan);
|
||||
|
||||
void D_DrawSpans32 (espan_t *pspan);
|
||||
void D_DrawSpans32From8 (espan_t *pspan);
|
||||
void D_DrawSpans32_Smooth (espan_t *pspan);
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
D_Init
|
||||
===============
|
||||
*/
|
||||
void D_Init (void)
|
||||
{
|
||||
|
||||
r_skydirect = 1;
|
||||
|
||||
r_drawpolys = false;
|
||||
r_worldpolysbacktofront = false;
|
||||
r_recursiveaffinetriangles = true;
|
||||
|
||||
if (!r_pixbytes)
|
||||
r_pixbytes = 1;
|
||||
r_aliasuvscale = 1.0;
|
||||
|
||||
#ifdef PEXT_TRANS
|
||||
D_InitTrans();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
D_CopyRects
|
||||
===============
|
||||
*/
|
||||
void D_CopyRects (vrect_t *prects, int transparent)
|
||||
{
|
||||
|
||||
// this function is only required if the CPU doesn't have direct access to the
|
||||
// back buffer, and there's some driver interface function that the driver
|
||||
// doesn't support and requires Quake to do in software (such as drawing the
|
||||
// console); Quake will then draw into wherever the driver points vid.buffer
|
||||
// and will call this function before swapping buffers
|
||||
|
||||
UNUSED(prects);
|
||||
UNUSED(transparent);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
D_EnableBackBufferAccess
|
||||
===============
|
||||
*/
|
||||
void D_EnableBackBufferAccess (void)
|
||||
{
|
||||
|
||||
VID_LockBuffer ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
D_TurnZOn
|
||||
===============
|
||||
*/
|
||||
void D_TurnZOn (void)
|
||||
{
|
||||
// not needed for software version
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
D_DisableBackBufferAccess
|
||||
===============
|
||||
*/
|
||||
void D_DisableBackBufferAccess (void)
|
||||
{
|
||||
VID_UnlockBuffer ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
D_SetupFrame
|
||||
===============
|
||||
*/
|
||||
void D_SetupFrame (void)
|
||||
{
|
||||
extern qboolean r_usinglits;
|
||||
int i;
|
||||
|
||||
if (r_dowarp)
|
||||
d_viewbuffer = r_warpbuffer;
|
||||
else
|
||||
d_viewbuffer = (void *)(qbyte *)vid.buffer;
|
||||
|
||||
if (r_dowarp)
|
||||
screenwidth = WARP_WIDTH;
|
||||
else
|
||||
screenwidth = vid.rowbytes;
|
||||
|
||||
d_roverwrapped = false;
|
||||
d_initial_rover = sc_rover;
|
||||
|
||||
d_minmip = d_mipcap.value;
|
||||
if (d_minmip > 3)
|
||||
d_minmip = 3;
|
||||
else if (d_minmip < 0)
|
||||
d_minmip = 0;
|
||||
|
||||
for (i=0 ; i<(NUM_MIPS-1) ; i++)
|
||||
d_scalemip[i] = basemip[i] * d_mipscale.value;
|
||||
|
||||
#if id386
|
||||
if (r_pixbytes == 4)
|
||||
d_drawspans = d_smooth.value?D_DrawSpans32_Smooth:D_DrawSpans32;
|
||||
else if (r_pixbytes == 2)
|
||||
d_drawspans = D_DrawSpans16;
|
||||
else if (d_smooth.value)//override's subdiv16 (bigger impact)
|
||||
d_drawspans = D_DrawSpans8_Smooth;
|
||||
else if (d_subdiv16.value)
|
||||
d_drawspans = D_DrawSpans8SubDiv16;
|
||||
else
|
||||
d_drawspans = D_DrawSpans8;
|
||||
#else
|
||||
if (r_pixbytes == 4)
|
||||
{
|
||||
if (r_usinglits)
|
||||
d_drawspans = d_smooth.value?D_DrawSpans32_Smooth:D_DrawSpans32;
|
||||
else
|
||||
d_drawspans = D_DrawSpans32From8;
|
||||
}
|
||||
else if (r_pixbytes == 2)
|
||||
d_drawspans = D_DrawSpans16;
|
||||
else
|
||||
d_drawspans = d_smooth.value?D_DrawSpans8_Smooth:D_DrawSpans8;
|
||||
#endif
|
||||
|
||||
d_aflatcolor = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
D_UpdateRects
|
||||
===============
|
||||
*/
|
||||
void D_UpdateRects (vrect_t *prect)
|
||||
{
|
||||
|
||||
// the software driver draws these directly to the vid buffer
|
||||
|
||||
UNUSED(prect);
|
||||
}
|
||||
|
136
engine/sw/d_local.h
Normal file
136
engine/sw/d_local.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_local.h: private rasterization driver defs
|
||||
|
||||
#include "r_shared.h"
|
||||
|
||||
//
|
||||
// TODO: fine-tune this; it's based on providing some overage even if there
|
||||
// is a 2k-wide scan, with subdivision every 8, for 256 spans of 12 bytes each
|
||||
//
|
||||
#define SCANBUFFERPAD 0x1000
|
||||
|
||||
#define R_SKY_SMASK 0x007F0000
|
||||
#define R_SKY_TMASK 0x007F0000
|
||||
|
||||
#define DS_SPAN_LIST_END -128
|
||||
|
||||
#define SURFCACHE_SIZE_AT_320X200 600*1024
|
||||
|
||||
typedef struct surfcache_s
|
||||
{
|
||||
struct surfcache_s *next;
|
||||
struct surfcache_s **owner; // NULL is an empty chunk of memory
|
||||
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
|
||||
int dlight;
|
||||
int size; // including header
|
||||
unsigned width;
|
||||
unsigned height; // DEBUG only needed for debug
|
||||
float mipscale;
|
||||
struct texture_s *texture; // checked for animating textures
|
||||
int bytesperpix;
|
||||
int fcache;
|
||||
qbyte data[4]; // width*height elements
|
||||
} surfcache_t;
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct sspan_s
|
||||
{
|
||||
int u, v, count;
|
||||
} sspan_t;
|
||||
|
||||
extern cvar_t d_subdiv16;
|
||||
|
||||
extern float scale_for_mip;
|
||||
|
||||
extern qboolean d_roverwrapped;
|
||||
extern surfcache_t *sc_rover;
|
||||
extern surfcache_t *d_initial_rover;
|
||||
|
||||
extern float d_sdivzstepu, d_tdivzstepu, d_zistepu;
|
||||
extern float d_sdivzstepv, d_tdivzstepv, d_zistepv;
|
||||
extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
|
||||
|
||||
fixed16_t sadjust, tadjust;
|
||||
fixed16_t bbextents, bbextentt;
|
||||
|
||||
|
||||
void D_DrawSpans8_Smooth (espan_t *pspan);
|
||||
void D_DrawSpans8 (espan_t *pspans);
|
||||
void D_DrawSpans16 (espan_t *pspans);
|
||||
void D_DrawSpans8SubDiv16 (espan_t *pspans);
|
||||
void D_DrawSpans16From8 (espan_t *pspan); //skybox in 16 bit renderer (fixme - load tgas with more colourdepth).
|
||||
void D_DrawZSpans (espan_t *pspans);
|
||||
void Turbulent8 (espan_t *pspan);
|
||||
void Turbulent16 (espan_t *pspan);
|
||||
void Turbulent32 (espan_t *pspan);
|
||||
void D_SpriteDrawSpans (sspan_t *pspan);
|
||||
|
||||
void D_DrawSkyScans8 (espan_t *pspan);
|
||||
void D_DrawSkyScans16 (espan_t *pspan);
|
||||
void D_DrawSkyScans32 (espan_t *pspan);
|
||||
|
||||
void R_ShowSubDiv (void);
|
||||
void (*prealspandrawer)(void);
|
||||
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
|
||||
|
||||
extern int D_MipLevelForScale (float scale);
|
||||
|
||||
#if id386
|
||||
extern void D_PolysetAff8Start (void);
|
||||
extern void D_PolysetAff8End (void);
|
||||
#endif
|
||||
|
||||
extern short *d_pzbuffer;
|
||||
extern unsigned int d_zrowbytes, d_zwidth;
|
||||
|
||||
extern int *d_pscantable;
|
||||
extern int d_scantable[MAXHEIGHT];
|
||||
|
||||
extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
|
||||
|
||||
extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
|
||||
|
||||
extern pixel_t *d_viewbuffer;
|
||||
|
||||
extern short *zspantable[MAXHEIGHT];
|
||||
|
||||
extern int d_minmip;
|
||||
extern float d_scalemip[3];
|
||||
|
||||
extern void (*d_drawspans) (espan_t *pspan);
|
||||
|
||||
|
||||
|
||||
#ifdef PEXT_TRANS
|
||||
typedef qbyte tlookup[256][256];
|
||||
typedef qbyte tlookupp[256];
|
||||
extern tlookup *t_lookup;
|
||||
extern tlookupp *t_curlookupp;
|
||||
extern int t_curtable;
|
||||
extern int t_numtables;
|
||||
extern int t_numtablesinv;//65546/numtables
|
||||
|
||||
void D_InitTrans(void);
|
||||
#define Trans(p, p2) (t_curlookupp[p][p2])
|
||||
void Set_TransLevelI(int level);
|
||||
void Set_TransLevelF(float level);
|
||||
#endif
|
||||
|
115
engine/sw/d_modech.c
Normal file
115
engine/sw/d_modech.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_modech.c: called when mode has just changed
|
||||
|
||||
//the id made assembler cannot cope with the changes made to the triangle data type.
|
||||
#ifndef NOASM
|
||||
#define NOASM
|
||||
#endif
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "d_local.h"
|
||||
|
||||
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
|
||||
|
||||
int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift;
|
||||
|
||||
int d_scantable[MAXHEIGHT];
|
||||
short *zspantable[MAXHEIGHT];
|
||||
|
||||
/*
|
||||
================
|
||||
D_Patch
|
||||
================
|
||||
*/
|
||||
void D_Patch (void)
|
||||
{
|
||||
#if id386
|
||||
|
||||
static qboolean protectset8 = false;
|
||||
|
||||
if (!protectset8)
|
||||
{
|
||||
Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
|
||||
(int)D_PolysetAff8End - (int)D_PolysetAff8Start);
|
||||
protectset8 = true;
|
||||
}
|
||||
|
||||
#endif // id386
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
D_ViewChanged
|
||||
================
|
||||
*/
|
||||
void D_ViewChanged (void)
|
||||
{
|
||||
int rowbytes;
|
||||
|
||||
if (r_dowarp)
|
||||
rowbytes = WARP_WIDTH;
|
||||
else
|
||||
rowbytes = vid.rowbytes;
|
||||
|
||||
scale_for_mip = xscale;
|
||||
if (yscale > xscale)
|
||||
scale_for_mip = yscale;
|
||||
|
||||
d_zrowbytes = vid.width * 2;
|
||||
d_zwidth = vid.width;
|
||||
|
||||
d_pix_min = r_refdef.vrect.width / 320;
|
||||
if (d_pix_min < 1)
|
||||
d_pix_min = 1;
|
||||
|
||||
d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
|
||||
d_pix_max*=2;
|
||||
d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
|
||||
if (d_pix_max < 1)
|
||||
d_pix_max = 1;
|
||||
|
||||
if (pixelAspect > 1.4)
|
||||
d_y_aspect_shift = 1;
|
||||
else
|
||||
d_y_aspect_shift = 0;
|
||||
|
||||
d_vrectx = r_refdef.vrect.x;
|
||||
d_vrecty = r_refdef.vrect.y;
|
||||
d_vrectright_particle = r_refdef.vrectright - d_pix_max;
|
||||
d_vrectbottom_particle =
|
||||
r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift);
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<vid.height; i++)
|
||||
{
|
||||
d_scantable[i] = i*rowbytes;
|
||||
zspantable[i] = d_pzbuffer + i*d_zwidth;
|
||||
}
|
||||
}
|
||||
|
||||
D_Patch ();
|
||||
|
||||
D_FlushCaches();
|
||||
}
|
||||
|
868
engine/sw/d_part.c
Normal file
868
engine/sw/d_part.c
Normal file
|
@ -0,0 +1,868 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_part.c: software driver module for drawing particles
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "d_local.h"
|
||||
|
||||
//Spike: Particles are depth sorted. So why depth write? They are the last to be drawn anyway.
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
D_EndParticles
|
||||
==============
|
||||
*/
|
||||
void D_EndParticles (void)
|
||||
{
|
||||
// not used by software driver
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
D_StartParticles
|
||||
==============
|
||||
*/
|
||||
void D_StartParticles (void)
|
||||
{
|
||||
// not used by software driver
|
||||
}
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
==============
|
||||
D_DrawParticle
|
||||
==============
|
||||
*/
|
||||
void D_DrawParticle (particle_t *pparticle)
|
||||
{
|
||||
vec3_t local, transformed;
|
||||
float zi;
|
||||
qbyte *pdest;
|
||||
short *pz;
|
||||
int i, izi, pix, count, u, v;
|
||||
|
||||
// transform point
|
||||
VectorSubtract (pparticle->org, r_origin, local);
|
||||
|
||||
transformed[0] = DotProduct(local, r_pright);
|
||||
transformed[1] = DotProduct(local, r_pup);
|
||||
transformed[2] = DotProduct(local, r_ppn);
|
||||
|
||||
if (transformed[2] < PARTICLE_Z_CLIP)
|
||||
return;
|
||||
|
||||
// project the point
|
||||
// FIXME: preadjust xcenter and ycenter
|
||||
zi = 1.0 / transformed[2];
|
||||
u = (int)(xcenter + zi * transformed[0] + 0.5);
|
||||
v = (int)(ycenter - zi * transformed[1] + 0.5);
|
||||
|
||||
if ((v > d_vrectbottom_particle) ||
|
||||
(u > d_vrectright_particle) ||
|
||||
(v < d_vrecty) ||
|
||||
(u < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pz = d_pzbuffer + (d_zwidth * v) + u;
|
||||
pdest = d_viewbuffer + d_scantable[v] + u;
|
||||
izi = (int)(zi * 0x8000);
|
||||
|
||||
pix = izi >> d_pix_shift;
|
||||
pix *= pparticle->scale;
|
||||
|
||||
if (pix < d_pix_min)
|
||||
pix = d_pix_min;
|
||||
else if (pix > d_pix_max)
|
||||
pix = d_pix_max;
|
||||
|
||||
switch (pix)
|
||||
{
|
||||
case 1:
|
||||
count = 1 << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
if (pz[0] <= izi)
|
||||
{
|
||||
// pz[0] = izi;
|
||||
pdest[0] = pparticle->color;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
count = 2 << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
if (pz[0] <= izi)
|
||||
{
|
||||
// pz[0] = izi;
|
||||
pdest[0] = pparticle->color;
|
||||
}
|
||||
|
||||
if (pz[1] <= izi)
|
||||
{
|
||||
// pz[1] = izi;
|
||||
pdest[1] = pparticle->color;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
count = 3 << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
if (pz[0] <= izi)
|
||||
{
|
||||
// pz[0] = izi;
|
||||
pdest[0] = pparticle->color;
|
||||
}
|
||||
|
||||
if (pz[1] <= izi)
|
||||
{
|
||||
// pz[1] = izi;
|
||||
pdest[1] = pparticle->color;
|
||||
}
|
||||
|
||||
if (pz[2] <= izi)
|
||||
{
|
||||
// pz[2] = izi;
|
||||
pdest[2] = pparticle->color;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
count = 4 << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
if (pz[0] <= izi)
|
||||
{
|
||||
// pz[0] = izi;
|
||||
pdest[0] = pparticle->color;
|
||||
}
|
||||
|
||||
if (pz[1] <= izi)
|
||||
{
|
||||
// pz[1] = izi;
|
||||
pdest[1] = pparticle->color;
|
||||
}
|
||||
|
||||
if (pz[2] <= izi)
|
||||
{
|
||||
// pz[2] = izi;
|
||||
pdest[2] = pparticle->color;
|
||||
}
|
||||
|
||||
if (pz[3] <= izi)
|
||||
{
|
||||
// pz[3] = izi;
|
||||
pdest[3] = pparticle->color;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
count = pix << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
for (i=0 ; i<pix ; i++)
|
||||
{
|
||||
if (pz[i] <= izi)
|
||||
{
|
||||
// pz[i] = izi;
|
||||
pdest[i] = pparticle->color;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
void D_DrawParticle16 (particle_t *pparticle)
|
||||
{
|
||||
vec3_t local, transformed;
|
||||
float zi;
|
||||
unsigned short *pdest;
|
||||
int a;
|
||||
short *pz;
|
||||
int i, izi, pix, count, u, v;
|
||||
|
||||
if (pparticle->alpha <= 0.2)
|
||||
return;
|
||||
|
||||
// transform point
|
||||
VectorSubtract (pparticle->org, r_origin, local);
|
||||
|
||||
transformed[0] = DotProduct(local, r_pright);
|
||||
transformed[1] = DotProduct(local, r_pup);
|
||||
transformed[2] = DotProduct(local, r_ppn);
|
||||
|
||||
if (transformed[2] < PARTICLE_Z_CLIP)
|
||||
return;
|
||||
|
||||
// project the point
|
||||
// FIXME: preadjust xcenter and ycenter
|
||||
zi = 1.0 / transformed[2];
|
||||
u = (int)(xcenter + zi * transformed[0] + 0.5);
|
||||
v = (int)(ycenter - zi * transformed[1] + 0.5);
|
||||
|
||||
if ((v > d_vrectbottom_particle) ||
|
||||
(u > d_vrectright_particle) ||
|
||||
(v < d_vrecty) ||
|
||||
(u < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pz = d_pzbuffer + (d_zwidth * v) + u;
|
||||
izi = (int)(zi * 0x8000);
|
||||
|
||||
pix = ((int)(izi*pparticle->scale)) >> d_pix_shift;
|
||||
|
||||
if (pix < d_pix_min)
|
||||
pix = d_pix_min;
|
||||
else if (pix > d_pix_max)
|
||||
pix = d_pix_max;
|
||||
|
||||
u -= pix/2;
|
||||
v -= pix/2;
|
||||
if (u < 0) u = 0;
|
||||
if (v < 0) v = 0;
|
||||
pdest = (unsigned short *)d_viewbuffer + ((d_scantable[v] + u));
|
||||
|
||||
a = 255*pparticle->alpha;
|
||||
|
||||
switch (pix)
|
||||
{
|
||||
default:
|
||||
count = pix << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
for (i=0 ; i<pix ; i++)
|
||||
{
|
||||
if (pz[i] <= izi)
|
||||
{
|
||||
// pz[i] = izi;
|
||||
pdest[i] = d_8to16table[(int)pparticle->color];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void D_DrawParticle32 (particle_t *pparticle)
|
||||
{
|
||||
vec3_t local, transformed;
|
||||
float zi;
|
||||
qbyte *pdest;
|
||||
qbyte *pal;
|
||||
int a;
|
||||
short *pz;
|
||||
int i, izi, pix, count, u, v;
|
||||
|
||||
if (pparticle->alpha <= 0.0)
|
||||
return;
|
||||
|
||||
// transform point
|
||||
VectorSubtract (pparticle->org, r_origin, local);
|
||||
|
||||
transformed[0] = DotProduct(local, r_pright);
|
||||
transformed[1] = DotProduct(local, r_pup);
|
||||
transformed[2] = DotProduct(local, r_ppn);
|
||||
|
||||
if (transformed[2] < PARTICLE_Z_CLIP)
|
||||
return;
|
||||
|
||||
// project the point
|
||||
// FIXME: preadjust xcenter and ycenter
|
||||
zi = 1.0 / transformed[2];
|
||||
u = (int)(xcenter + zi * transformed[0] + 0.5);
|
||||
v = (int)(ycenter - zi * transformed[1] + 0.5);
|
||||
|
||||
if ((v > d_vrectbottom_particle) ||
|
||||
(u > d_vrectright_particle) ||
|
||||
(v < d_vrecty) ||
|
||||
(u < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pz = d_pzbuffer + (d_zwidth * v) + u;
|
||||
izi = (int)(zi * 0x8000);
|
||||
|
||||
pix = ((int)(izi*pparticle->scale)) >> d_pix_shift;
|
||||
|
||||
if (pix < d_pix_min)
|
||||
pix = d_pix_min;
|
||||
else if (pix > d_pix_max)
|
||||
pix = d_pix_max;
|
||||
|
||||
u -= pix/2;
|
||||
v -= pix/2;
|
||||
if (u < 0) u = 0;
|
||||
if (v < 0) v = 0;
|
||||
pdest = d_viewbuffer + ((d_scantable[v] + u)<<2);
|
||||
pal = (qbyte *)&d_8to32table[(int)pparticle->color];
|
||||
|
||||
a = 255*pparticle->alpha;
|
||||
|
||||
switch (pix)
|
||||
{
|
||||
default:
|
||||
count = pix << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth<<2)
|
||||
{
|
||||
for (i=0 ; i<pix ; i++)
|
||||
{
|
||||
if (pz[i] <= izi)
|
||||
{
|
||||
// pz[i] = izi;
|
||||
pdest[(i<<2)+0] = (pdest[(i<<2)+0]*(255-a) + pal[0]*a) / 255;
|
||||
pdest[(i<<2)+1] = (pdest[(i<<2)+1]*(255-a) + pal[1]*a) / 255;
|
||||
pdest[(i<<2)+2] = (pdest[(i<<2)+2]*(255-a) + pal[2]*a) / 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define draw(x, y) x=Trans(x,(int)y)
|
||||
void D_DrawParticleTrans (particle_t *pparticle)
|
||||
{
|
||||
vec3_t local, transformed;
|
||||
float zi;
|
||||
qbyte *pdest;
|
||||
short *pz;
|
||||
int i, izi, pix, count, u, v;
|
||||
|
||||
if (r_pixbytes == 4)
|
||||
{
|
||||
D_DrawParticle32(pparticle);
|
||||
return;
|
||||
}
|
||||
if (r_pixbytes == 2)
|
||||
{
|
||||
D_DrawParticle16(pparticle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pparticle->alpha <= 0.0)
|
||||
return;
|
||||
|
||||
|
||||
if (pparticle->alpha >= 0.9)
|
||||
{
|
||||
D_DrawParticle(pparticle);
|
||||
return;
|
||||
}
|
||||
|
||||
Set_TransLevelF(pparticle->alpha);
|
||||
|
||||
// transform point
|
||||
VectorSubtract (pparticle->org, r_origin, local);
|
||||
|
||||
transformed[0] = DotProduct(local, r_pright);
|
||||
transformed[1] = DotProduct(local, r_pup);
|
||||
transformed[2] = DotProduct(local, r_ppn);
|
||||
|
||||
if (transformed[2] < PARTICLE_Z_CLIP)
|
||||
return;
|
||||
|
||||
// project the point
|
||||
// FIXME: preadjust xcenter and ycenter
|
||||
zi = 1.0 / transformed[2];
|
||||
u = (int)(xcenter + zi * transformed[0] + 0.5);
|
||||
v = (int)(ycenter - zi * transformed[1] + 0.5);
|
||||
|
||||
if ((v > d_vrectbottom_particle) ||
|
||||
(u > d_vrectright_particle) ||
|
||||
(v < d_vrecty) ||
|
||||
(u < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pz = d_pzbuffer + (d_zwidth * v) + u;
|
||||
izi = (int)(zi * 0x8000);
|
||||
|
||||
pix = ((int)(izi*pparticle->scale)) >> d_pix_shift;
|
||||
|
||||
if (pix < d_pix_min)
|
||||
pix = d_pix_min;
|
||||
else if (pix > d_pix_max)
|
||||
pix = d_pix_max;
|
||||
|
||||
u -= pix/2;
|
||||
v -= pix/2;
|
||||
if (u < 0) u = 0;
|
||||
if (v < 0) v = 0;
|
||||
pdest = d_viewbuffer + d_scantable[v] + u;
|
||||
|
||||
switch (pix)
|
||||
{
|
||||
case 1:
|
||||
count = 1 << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
if (pz[0] <= izi)
|
||||
{
|
||||
// pz[0] = izi;
|
||||
draw(pdest[0], pparticle->color);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
count = 2 << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
if (pz[0] <= izi)
|
||||
{
|
||||
// pz[0] = izi;
|
||||
draw(pdest[0], pparticle->color);
|
||||
}
|
||||
|
||||
if (pz[1] <= izi)
|
||||
{
|
||||
// pz[1] = izi;
|
||||
draw(pdest[1], pparticle->color);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
count = 3 << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
if (pz[0] <= izi)
|
||||
{
|
||||
// pz[0] = izi;
|
||||
draw(pdest[0], pparticle->color);
|
||||
}
|
||||
|
||||
if (pz[1] <= izi)
|
||||
{
|
||||
// pz[1] = izi;
|
||||
draw(pdest[1], pparticle->color);
|
||||
}
|
||||
|
||||
if (pz[2] <= izi)
|
||||
{
|
||||
// pz[2] = izi;
|
||||
draw(pdest[2], pparticle->color);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
count = 4 << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
if (pz[0] <= izi)
|
||||
{
|
||||
// pz[0] = izi;
|
||||
draw(pdest[0], pparticle->color);
|
||||
}
|
||||
|
||||
if (pz[1] <= izi)
|
||||
{
|
||||
// pz[1] = izi;
|
||||
draw(pdest[1], pparticle->color);
|
||||
}
|
||||
|
||||
if (pz[2] <= izi)
|
||||
{
|
||||
// pz[2] = izi;
|
||||
draw(pdest[2], pparticle->color);
|
||||
}
|
||||
|
||||
if (pz[3] <= izi)
|
||||
{
|
||||
// pz[3] = izi;
|
||||
draw(pdest[3], pparticle->color);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
count = pix << d_y_aspect_shift;
|
||||
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
{
|
||||
for (i=0 ; i<pix ; i++)
|
||||
{
|
||||
if (pz[i] <= izi)
|
||||
{
|
||||
// pz[i] = izi;
|
||||
draw(pdest[i], pparticle->color);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void D_2dPos(vec3_t pos, int *u, int *v, int *z)
|
||||
{
|
||||
float zi;
|
||||
vec3_t local, transformed;
|
||||
|
||||
// transform point
|
||||
VectorSubtract (pos, r_origin, local);
|
||||
|
||||
transformed[2] = DotProduct(local, r_ppn);
|
||||
|
||||
if (transformed[2] < PARTICLE_Z_CLIP) //near clip
|
||||
{
|
||||
*u = -1; //send it off the side intentionally.
|
||||
return;
|
||||
}
|
||||
|
||||
transformed[0] = DotProduct(local, r_pright);
|
||||
transformed[1] = DotProduct(local, r_pup);
|
||||
|
||||
// project the point
|
||||
zi = 1.0 / transformed[2];
|
||||
*u = (int)(xcenter + zi * transformed[0] + 0.5);
|
||||
*v = (int)(ycenter - zi * transformed[1] + 0.5);
|
||||
|
||||
*z = (int)(zi * 0x8000);
|
||||
}
|
||||
vec_t VI2Length(int x, int y)
|
||||
{
|
||||
float length;
|
||||
length = (float)x*x + (float)y*y;
|
||||
length = sqrt (length);
|
||||
return length;
|
||||
}
|
||||
void D_DrawSparkTrans32 (particle_t *pparticle) //draw a line in 3d space
|
||||
{
|
||||
/*
|
||||
Finds 2d coords for the points, then draws a line between them with an appropriate alpha
|
||||
*/
|
||||
vec3_t delta;
|
||||
unsigned char *pdest;
|
||||
unsigned char *pal;
|
||||
short *pz;
|
||||
int count, u1, v1, z1, a1, a, ia;
|
||||
int u2, v2, z2;
|
||||
float speed;
|
||||
|
||||
int du, dv, dz, da;
|
||||
|
||||
if (pparticle->alpha <= 0.0)
|
||||
return;
|
||||
|
||||
speed = Length(pparticle->vel);
|
||||
if ((speed) < 1)
|
||||
{
|
||||
D_2dPos(pparticle->org, &u1, &v1, &z1);
|
||||
D_2dPos(pparticle->org, &u2, &v2, &z2);
|
||||
}
|
||||
else
|
||||
{ //causes flickers with lower vels (due to bouncing in physics)
|
||||
if (speed < 50)
|
||||
speed *= 50/speed;
|
||||
VectorMA(pparticle->org, 5/(speed), pparticle->vel, delta);
|
||||
D_2dPos(delta, &u1, &v1, &z1);
|
||||
VectorMA(pparticle->org, -5/(speed), pparticle->vel, delta);
|
||||
D_2dPos(delta, &u2, &v2, &z2);
|
||||
}
|
||||
|
||||
if ((v1 > d_vrectbottom_particle) ||
|
||||
(u1 > d_vrectright_particle) ||
|
||||
(v1 < d_vrecty) ||
|
||||
(u1 < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((v2 > d_vrectbottom_particle) ||
|
||||
(u2 > d_vrectright_particle) ||
|
||||
(v2 < d_vrecty) ||
|
||||
(u2 < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
pal = (qbyte *)(d_8to32table + (int)pparticle->color);
|
||||
a1 = 255 * pparticle->alpha;
|
||||
|
||||
du = u2 - u1;
|
||||
dv = v2 - v1;
|
||||
dz = z2 - z1;
|
||||
da = 0 - a1;
|
||||
|
||||
if (!du && !dv)
|
||||
count = 1;
|
||||
else
|
||||
{
|
||||
count = VI2Length(du, dv);
|
||||
if (!count)
|
||||
count = 1;
|
||||
}
|
||||
|
||||
du *= 256*256;
|
||||
dv *= 256*256;
|
||||
dz *= 256*256;
|
||||
da *= 256*256;
|
||||
u1 = u1<<16;
|
||||
v1 = v1<<16;
|
||||
z1 = z1<<16;
|
||||
a1 = a1<<16;
|
||||
{
|
||||
du /= count;
|
||||
dv /= count;
|
||||
dz /= count;
|
||||
da /= count;
|
||||
}
|
||||
do
|
||||
{
|
||||
pz = d_pzbuffer + (d_zwidth * (v1>>16)) + (u1>>16);
|
||||
|
||||
if (*pz <= z1>>16)
|
||||
{
|
||||
// *pz = z1>>16;
|
||||
|
||||
a = a1>>16;
|
||||
ia = 255-a;
|
||||
pdest = (qbyte *)((unsigned int *)d_viewbuffer + ((d_scantable[v1>>16] + (u1>>16))));
|
||||
pdest[0] = (pdest[0]*((ia)) + pal[0]*(a))/255;
|
||||
pdest[1] = (pdest[1]*((ia)) + pal[1]*(a))/255;
|
||||
pdest[2] = (pdest[2]*((ia)) + pal[2]*(a))/255;
|
||||
}
|
||||
|
||||
u1 += du;
|
||||
v1 += dv;
|
||||
z1 += dz;
|
||||
a1 += da;
|
||||
} while (count--);
|
||||
}
|
||||
|
||||
void D_DrawSparkTrans16 (particle_t *pparticle) //draw a line in 3d space, 8bpp
|
||||
{
|
||||
vec3_t delta;
|
||||
unsigned short *pdest;
|
||||
short *pz;
|
||||
int count, u1, v1, z1;
|
||||
int u2, v2, z2;
|
||||
float speed;
|
||||
|
||||
int du, dv, dz;
|
||||
|
||||
if (pparticle->alpha <= 0.0)
|
||||
return;
|
||||
|
||||
speed = Length(pparticle->vel);
|
||||
if ((speed) < 1)
|
||||
{
|
||||
D_2dPos(pparticle->org, &u1, &v1, &z1);
|
||||
D_2dPos(pparticle->org, &u2, &v2, &z2);
|
||||
}
|
||||
else
|
||||
{ //causes flickers with lower vels (due to bouncing in physics)
|
||||
if (speed < 50)
|
||||
speed *= 50/speed;
|
||||
VectorMA(pparticle->org, 2.5/(speed), pparticle->vel, delta);
|
||||
D_2dPos(delta, &u1, &v1, &z1);
|
||||
VectorMA(pparticle->org, -2.5/(speed), pparticle->vel, delta);
|
||||
D_2dPos(delta, &u2, &v2, &z2);
|
||||
}
|
||||
|
||||
if ((v1 > d_vrectbottom_particle) ||
|
||||
(u1 > d_vrectright_particle) ||
|
||||
(v1 < d_vrecty) ||
|
||||
(u1 < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((v2 > d_vrectbottom_particle) ||
|
||||
(u2 > d_vrectright_particle) ||
|
||||
(v2 < d_vrecty) ||
|
||||
(u2 < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
du = u2 - u1;
|
||||
dv = v2 - v1;
|
||||
dz = z2 - z1;
|
||||
|
||||
if (!du && !dv)
|
||||
count = 1;
|
||||
else
|
||||
{
|
||||
count = VI2Length(du, dv);
|
||||
if (!count)
|
||||
count = 1;
|
||||
}
|
||||
|
||||
du *= 256*256;
|
||||
dv *= 256*256;
|
||||
dz *= 256*256;
|
||||
u1 = u1<<16;
|
||||
v1 = v1<<16;
|
||||
z1 = z1<<16;
|
||||
{
|
||||
du /= count;
|
||||
dv /= count;
|
||||
dz /= count;
|
||||
}
|
||||
do
|
||||
{
|
||||
pz = d_pzbuffer + (d_zwidth * (v1>>16)) + (u1>>16);
|
||||
|
||||
if (*pz <= z1>>16)
|
||||
{
|
||||
// *pz = z1>>16;
|
||||
|
||||
pdest = (unsigned short*)d_viewbuffer + d_scantable[v1>>16] + (u1>>16);
|
||||
*pdest = d_8to16table[(int)pparticle->color];
|
||||
}
|
||||
|
||||
u1 += du;
|
||||
v1 += dv;
|
||||
z1 += dz;
|
||||
} while (count--);
|
||||
}
|
||||
|
||||
void D_DrawSparkTrans (particle_t *pparticle) //draw a line in 3d space, 8bpp
|
||||
{
|
||||
vec3_t delta;
|
||||
qbyte *pdest;
|
||||
short *pz;
|
||||
int count, u1, v1, z1;
|
||||
int u2, v2, z2;
|
||||
float speed;
|
||||
|
||||
int du, dv, dz;
|
||||
/*
|
||||
D_DrawParticleTrans(pparticle);
|
||||
return;
|
||||
*/
|
||||
if (r_pixbytes == 4)
|
||||
{
|
||||
D_DrawSparkTrans32(pparticle);
|
||||
return;
|
||||
}
|
||||
if (r_pixbytes == 2)
|
||||
{
|
||||
D_DrawSparkTrans16(pparticle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pparticle->alpha <= 0.0)
|
||||
return;
|
||||
|
||||
Set_TransLevelF(pparticle->alpha);
|
||||
|
||||
speed = Length(pparticle->vel);
|
||||
if ((speed) < 1)
|
||||
{
|
||||
D_2dPos(pparticle->org, &u1, &v1, &z1);
|
||||
D_2dPos(pparticle->org, &u2, &v2, &z2);
|
||||
}
|
||||
else
|
||||
{ //causes flickers with lower vels (due to bouncing in physics)
|
||||
if (speed < 50)
|
||||
speed *= 50/speed;
|
||||
VectorMA(pparticle->org, 2.5/(speed), pparticle->vel, delta);
|
||||
D_2dPos(delta, &u1, &v1, &z1);
|
||||
VectorMA(pparticle->org, -2.5/(speed), pparticle->vel, delta);
|
||||
D_2dPos(delta, &u2, &v2, &z2);
|
||||
}
|
||||
|
||||
if ((v1 > d_vrectbottom_particle) ||
|
||||
(u1 > d_vrectright_particle) ||
|
||||
(v1 < d_vrecty) ||
|
||||
(u1 < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((v2 > d_vrectbottom_particle) ||
|
||||
(u2 > d_vrectright_particle) ||
|
||||
(v2 < d_vrecty) ||
|
||||
(u2 < d_vrectx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
du = u2 - u1;
|
||||
dv = v2 - v1;
|
||||
dz = z2 - z1;
|
||||
|
||||
if (!du && !dv)
|
||||
count = 1;
|
||||
else
|
||||
{
|
||||
count = VI2Length(du, dv);
|
||||
if (!count)
|
||||
count = 1;
|
||||
}
|
||||
|
||||
du *= 256*256;
|
||||
dv *= 256*256;
|
||||
dz *= 256*256;
|
||||
u1 = u1<<16;
|
||||
v1 = v1<<16;
|
||||
z1 = z1<<16;
|
||||
{
|
||||
du /= count;
|
||||
dv /= count;
|
||||
dz /= count;
|
||||
}
|
||||
do
|
||||
{
|
||||
pz = d_pzbuffer + (d_zwidth * (v1>>16)) + (u1>>16);
|
||||
|
||||
if (*pz <= z1>>16)
|
||||
{
|
||||
// *pz = z1>>16;
|
||||
|
||||
pdest = d_viewbuffer + d_scantable[v1>>16] + (u1>>16);
|
||||
draw(*pdest, pparticle->color);
|
||||
}
|
||||
|
||||
u1 += du;
|
||||
v1 += dv;
|
||||
z1 += dz;
|
||||
} while (count--);
|
||||
}
|
477
engine/sw/d_parta.s
Normal file
477
engine/sw/d_parta.s
Normal file
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
//
|
||||
// d_parta.s
|
||||
// x86 assembly-language 8-bpp particle-drawing code.
|
||||
//
|
||||
|
||||
#include "asm_i386.h"
|
||||
#include "quakeasm.h"
|
||||
#include "d_ifacea.h"
|
||||
#include "asm_draw.h"
|
||||
|
||||
#if id386
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 8-bpp particle drawing code.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//FIXME: comments, full optimization
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 8-bpp particle queueing code.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
.text
|
||||
|
||||
#define P 12+4
|
||||
|
||||
.align 4
|
||||
.globl C(D_DrawParticle)
|
||||
C(D_DrawParticle):
|
||||
pushl %ebp // preserve caller's stack frame
|
||||
pushl %edi // preserve register variables
|
||||
pushl %ebx
|
||||
|
||||
movl P(%esp),%edi
|
||||
|
||||
// FIXME: better FP overlap in general here
|
||||
|
||||
// transform point
|
||||
// VectorSubtract (p->org, r_origin, local);
|
||||
flds C(r_origin)
|
||||
fsubrs pt_org(%edi)
|
||||
flds pt_org+4(%edi)
|
||||
fsubs C(r_origin)+4
|
||||
flds pt_org+8(%edi)
|
||||
fsubs C(r_origin)+8
|
||||
fxch %st(2) // local[0] | local[1] | local[2]
|
||||
|
||||
// transformed[2] = DotProduct(local, r_ppn);
|
||||
flds C(r_ppn) // r_ppn[0] | local[0] | local[1] | local[2]
|
||||
fmul %st(1),%st(0) // dot0 | local[0] | local[1] | local[2]
|
||||
flds C(r_ppn)+4 // r_ppn[1] | dot0 | local[0] | local[1] | local[2]
|
||||
fmul %st(3),%st(0) // dot1 | dot0 | local[0] | local[1] | local[2]
|
||||
flds C(r_ppn)+8 // r_ppn[2] | dot1 | dot0 | local[0] |
|
||||
// local[1] | local[2]
|
||||
fmul %st(5),%st(0) // dot2 | dot1 | dot0 | local[0] | local[1] | local[2]
|
||||
fxch %st(2) // dot0 | dot1 | dot2 | local[0] | local[1] | local[2]
|
||||
faddp %st(0),%st(1) // dot0 + dot1 | dot2 | local[0] | local[1] |
|
||||
// local[2]
|
||||
faddp %st(0),%st(1) // z | local[0] | local[1] | local[2]
|
||||
fld %st(0) // z | z | local[0] | local[1] |
|
||||
// local[2]
|
||||
fdivrs float_1 // 1/z | z | local[0] | local[1] | local[2]
|
||||
fxch %st(1) // z | 1/z | local[0] | local[1] | local[2]
|
||||
|
||||
// if (transformed[2] < PARTICLE_Z_CLIP)
|
||||
// return;
|
||||
fcomps float_particle_z_clip // 1/z | local[0] | local[1] | local[2]
|
||||
fxch %st(3) // local[2] | local[0] | local[1] | 1/z
|
||||
|
||||
flds C(r_pup) // r_pup[0] | local[2] | local[0] | local[1] | 1/z
|
||||
fmul %st(2),%st(0) // dot0 | local[2] | local[0] | local[1] | 1/z
|
||||
flds C(r_pup)+4 // r_pup[1] | dot0 | local[2] | local[0] |
|
||||
// local[1] | 1/z
|
||||
|
||||
fnstsw %ax
|
||||
testb $1,%ah
|
||||
jnz LPop6AndDone
|
||||
|
||||
// transformed[1] = DotProduct(local, r_pup);
|
||||
fmul %st(4),%st(0) // dot1 | dot0 | local[2] | local[0] | local[1] | 1/z
|
||||
flds C(r_pup)+8 // r_pup[2] | dot1 | dot0 | local[2] |
|
||||
// local[0] | local[1] | 1/z
|
||||
fmul %st(3),%st(0) // dot2 | dot1 | dot0 | local[2] | local[0] |
|
||||
// local[1] | 1/z
|
||||
fxch %st(2) // dot0 | dot1 | dot2 | local[2] | local[0] |
|
||||
// local[1] | 1/z
|
||||
faddp %st(0),%st(1) // dot0 + dot1 | dot2 | local[2] | local[0] |
|
||||
// local[1] | 1/z
|
||||
faddp %st(0),%st(1) // y | local[2] | local[0] | local[1] | 1/z
|
||||
fxch %st(3) // local[1] | local[2] | local[0] | y | 1/z
|
||||
|
||||
// transformed[0] = DotProduct(local, r_pright);
|
||||
fmuls C(r_pright)+4 // dot1 | local[2] | local[0] | y | 1/z
|
||||
fxch %st(2) // local[0] | local[2] | dot1 | y | 1/z
|
||||
fmuls C(r_pright) // dot0 | local[2] | dot1 | y | 1/z
|
||||
fxch %st(1) // local[2] | dot0 | dot1 | y | 1/z
|
||||
fmuls C(r_pright)+8 // dot2 | dot0 | dot1 | y | 1/z
|
||||
fxch %st(2) // dot1 | dot0 | dot2 | y | 1/z
|
||||
faddp %st(0),%st(1) // dot1 + dot0 | dot2 | y | 1/z
|
||||
|
||||
faddp %st(0),%st(1) // x | y | 1/z
|
||||
fxch %st(1) // y | x | 1/z
|
||||
|
||||
// project the point
|
||||
fmul %st(2),%st(0) // y/z | x | 1/z
|
||||
fxch %st(1) // x | y/z | 1/z
|
||||
fmul %st(2),%st(0) // x/z | y/z | 1/z
|
||||
fxch %st(1) // y/z | x/z | 1/z
|
||||
fsubrs C(ycenter) // v | x/z | 1/z
|
||||
fxch %st(1) // x/z | v | 1/z
|
||||
fadds C(xcenter) // u | v | 1/z
|
||||
// FIXME: preadjust xcenter and ycenter
|
||||
fxch %st(1) // v | u | 1/z
|
||||
fadds float_point5 // v | u | 1/z
|
||||
fxch %st(1) // u | v | 1/z
|
||||
fadds float_point5 // u | v | 1/z
|
||||
fxch %st(2) // 1/z | v | u
|
||||
fmuls DP_32768 // 1/z * 0x8000 | v | u
|
||||
fxch %st(2) // u | v | 1/z * 0x8000
|
||||
|
||||
// FIXME: use Terje's fp->int trick here?
|
||||
// FIXME: check we're getting proper rounding here
|
||||
fistpl DP_u // v | 1/z * 0x8000
|
||||
fistpl DP_v // 1/z * 0x8000
|
||||
|
||||
movl DP_u,%eax
|
||||
movl DP_v,%edx
|
||||
|
||||
// if ((v > d_vrectbottom_particle) ||
|
||||
// (u > d_vrectright_particle) ||
|
||||
// (v < d_vrecty) ||
|
||||
// (u < d_vrectx))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
movl C(d_vrectbottom_particle),%ebx
|
||||
movl C(d_vrectright_particle),%ecx
|
||||
cmpl %ebx,%edx
|
||||
jg LPop1AndDone
|
||||
cmpl %ecx,%eax
|
||||
jg LPop1AndDone
|
||||
movl C(d_vrecty),%ebx
|
||||
movl C(d_vrectx),%ecx
|
||||
cmpl %ebx,%edx
|
||||
jl LPop1AndDone
|
||||
|
||||
cmpl %ecx,%eax
|
||||
jl LPop1AndDone
|
||||
|
||||
flds pt_color(%edi) // color | 1/z * 0x8000
|
||||
// FIXME: use Terje's fast fp->int trick?
|
||||
fistpl DP_Color // 1/z * 0x8000
|
||||
|
||||
movl C(d_viewbuffer),%ebx
|
||||
|
||||
addl %eax,%ebx
|
||||
movl C(d_scantable)(,%edx,4),%edi // point to the pixel
|
||||
|
||||
imull C(d_zrowbytes),%edx // point to the z pixel
|
||||
|
||||
leal (%edx,%eax,2),%edx
|
||||
movl C(d_pzbuffer),%eax
|
||||
|
||||
fistpl izi
|
||||
|
||||
addl %ebx,%edi
|
||||
addl %eax,%edx
|
||||
|
||||
// pix = izi >> d_pix_shift;
|
||||
|
||||
movl izi,%eax
|
||||
movl C(d_pix_shift),%ecx
|
||||
shrl %cl,%eax
|
||||
movl izi,%ebp
|
||||
|
||||
// if (pix < d_pix_min)
|
||||
// pix = d_pix_min;
|
||||
// else if (pix > d_pix_max)
|
||||
// pix = d_pix_max;
|
||||
|
||||
movl C(d_pix_min),%ebx
|
||||
movl C(d_pix_max),%ecx
|
||||
cmpl %ebx,%eax
|
||||
jnl LTestPixMax
|
||||
movl %ebx,%eax
|
||||
jmp LTestDone
|
||||
|
||||
LTestPixMax:
|
||||
cmpl %ecx,%eax
|
||||
jng LTestDone
|
||||
movl %ecx,%eax
|
||||
LTestDone:
|
||||
|
||||
movb DP_Color,%ch
|
||||
|
||||
movl C(d_y_aspect_shift),%ebx
|
||||
testl %ebx,%ebx
|
||||
jnz LDefault
|
||||
|
||||
cmpl $4,%eax
|
||||
ja LDefault
|
||||
|
||||
jmp DP_EntryTable-4(,%eax,4)
|
||||
|
||||
// 1x1
|
||||
.globl DP_1x1
|
||||
DP_1x1:
|
||||
cmpw %bp,(%edx) // just one pixel to do
|
||||
jg LDone
|
||||
movw %bp,(%edx)
|
||||
movb %ch,(%edi)
|
||||
jmp LDone
|
||||
|
||||
// 2x2
|
||||
.globl DP_2x2
|
||||
DP_2x2:
|
||||
pushl %esi
|
||||
movl C(screenwidth),%ebx
|
||||
movl C(d_zrowbytes),%esi
|
||||
|
||||
cmpw %bp,(%edx)
|
||||
jg L2x2_1
|
||||
movw %bp,(%edx)
|
||||
movb %ch,(%edi)
|
||||
L2x2_1:
|
||||
cmpw %bp,2(%edx)
|
||||
jg L2x2_2
|
||||
movw %bp,2(%edx)
|
||||
movb %ch,1(%edi)
|
||||
L2x2_2:
|
||||
cmpw %bp,(%edx,%esi,1)
|
||||
jg L2x2_3
|
||||
movw %bp,(%edx,%esi,1)
|
||||
movb %ch,(%edi,%ebx,1)
|
||||
L2x2_3:
|
||||
cmpw %bp,2(%edx,%esi,1)
|
||||
jg L2x2_4
|
||||
movw %bp,2(%edx,%esi,1)
|
||||
movb %ch,1(%edi,%ebx,1)
|
||||
L2x2_4:
|
||||
|
||||
popl %esi
|
||||
jmp LDone
|
||||
|
||||
// 3x3
|
||||
.globl DP_3x3
|
||||
DP_3x3:
|
||||
pushl %esi
|
||||
movl C(screenwidth),%ebx
|
||||
movl C(d_zrowbytes),%esi
|
||||
|
||||
cmpw %bp,(%edx)
|
||||
jg L3x3_1
|
||||
movw %bp,(%edx)
|
||||
movb %ch,(%edi)
|
||||
L3x3_1:
|
||||
cmpw %bp,2(%edx)
|
||||
jg L3x3_2
|
||||
movw %bp,2(%edx)
|
||||
movb %ch,1(%edi)
|
||||
L3x3_2:
|
||||
cmpw %bp,4(%edx)
|
||||
jg L3x3_3
|
||||
movw %bp,4(%edx)
|
||||
movb %ch,2(%edi)
|
||||
L3x3_3:
|
||||
|
||||
cmpw %bp,(%edx,%esi,1)
|
||||
jg L3x3_4
|
||||
movw %bp,(%edx,%esi,1)
|
||||
movb %ch,(%edi,%ebx,1)
|
||||
L3x3_4:
|
||||
cmpw %bp,2(%edx,%esi,1)
|
||||
jg L3x3_5
|
||||
movw %bp,2(%edx,%esi,1)
|
||||
movb %ch,1(%edi,%ebx,1)
|
||||
L3x3_5:
|
||||
cmpw %bp,4(%edx,%esi,1)
|
||||
jg L3x3_6
|
||||
movw %bp,4(%edx,%esi,1)
|
||||
movb %ch,2(%edi,%ebx,1)
|
||||
L3x3_6:
|
||||
|
||||
cmpw %bp,(%edx,%esi,2)
|
||||
jg L3x3_7
|
||||
movw %bp,(%edx,%esi,2)
|
||||
movb %ch,(%edi,%ebx,2)
|
||||
L3x3_7:
|
||||
cmpw %bp,2(%edx,%esi,2)
|
||||
jg L3x3_8
|
||||
movw %bp,2(%edx,%esi,2)
|
||||
movb %ch,1(%edi,%ebx,2)
|
||||
L3x3_8:
|
||||
cmpw %bp,4(%edx,%esi,2)
|
||||
jg L3x3_9
|
||||
movw %bp,4(%edx,%esi,2)
|
||||
movb %ch,2(%edi,%ebx,2)
|
||||
L3x3_9:
|
||||
|
||||
popl %esi
|
||||
jmp LDone
|
||||
|
||||
|
||||
// 4x4
|
||||
.globl DP_4x4
|
||||
DP_4x4:
|
||||
pushl %esi
|
||||
movl C(screenwidth),%ebx
|
||||
movl C(d_zrowbytes),%esi
|
||||
|
||||
cmpw %bp,(%edx)
|
||||
jg L4x4_1
|
||||
movw %bp,(%edx)
|
||||
movb %ch,(%edi)
|
||||
L4x4_1:
|
||||
cmpw %bp,2(%edx)
|
||||
jg L4x4_2
|
||||
movw %bp,2(%edx)
|
||||
movb %ch,1(%edi)
|
||||
L4x4_2:
|
||||
cmpw %bp,4(%edx)
|
||||
jg L4x4_3
|
||||
movw %bp,4(%edx)
|
||||
movb %ch,2(%edi)
|
||||
L4x4_3:
|
||||
cmpw %bp,6(%edx)
|
||||
jg L4x4_4
|
||||
movw %bp,6(%edx)
|
||||
movb %ch,3(%edi)
|
||||
L4x4_4:
|
||||
|
||||
cmpw %bp,(%edx,%esi,1)
|
||||
jg L4x4_5
|
||||
movw %bp,(%edx,%esi,1)
|
||||
movb %ch,(%edi,%ebx,1)
|
||||
L4x4_5:
|
||||
cmpw %bp,2(%edx,%esi,1)
|
||||
jg L4x4_6
|
||||
movw %bp,2(%edx,%esi,1)
|
||||
movb %ch,1(%edi,%ebx,1)
|
||||
L4x4_6:
|
||||
cmpw %bp,4(%edx,%esi,1)
|
||||
jg L4x4_7
|
||||
movw %bp,4(%edx,%esi,1)
|
||||
movb %ch,2(%edi,%ebx,1)
|
||||
L4x4_7:
|
||||
cmpw %bp,6(%edx,%esi,1)
|
||||
jg L4x4_8
|
||||
movw %bp,6(%edx,%esi,1)
|
||||
movb %ch,3(%edi,%ebx,1)
|
||||
L4x4_8:
|
||||
|
||||
leal (%edx,%esi,2),%edx
|
||||
leal (%edi,%ebx,2),%edi
|
||||
|
||||
cmpw %bp,(%edx)
|
||||
jg L4x4_9
|
||||
movw %bp,(%edx)
|
||||
movb %ch,(%edi)
|
||||
L4x4_9:
|
||||
cmpw %bp,2(%edx)
|
||||
jg L4x4_10
|
||||
movw %bp,2(%edx)
|
||||
movb %ch,1(%edi)
|
||||
L4x4_10:
|
||||
cmpw %bp,4(%edx)
|
||||
jg L4x4_11
|
||||
movw %bp,4(%edx)
|
||||
movb %ch,2(%edi)
|
||||
L4x4_11:
|
||||
cmpw %bp,6(%edx)
|
||||
jg L4x4_12
|
||||
movw %bp,6(%edx)
|
||||
movb %ch,3(%edi)
|
||||
L4x4_12:
|
||||
|
||||
cmpw %bp,(%edx,%esi,1)
|
||||
jg L4x4_13
|
||||
movw %bp,(%edx,%esi,1)
|
||||
movb %ch,(%edi,%ebx,1)
|
||||
L4x4_13:
|
||||
cmpw %bp,2(%edx,%esi,1)
|
||||
jg L4x4_14
|
||||
movw %bp,2(%edx,%esi,1)
|
||||
movb %ch,1(%edi,%ebx,1)
|
||||
L4x4_14:
|
||||
cmpw %bp,4(%edx,%esi,1)
|
||||
jg L4x4_15
|
||||
movw %bp,4(%edx,%esi,1)
|
||||
movb %ch,2(%edi,%ebx,1)
|
||||
L4x4_15:
|
||||
cmpw %bp,6(%edx,%esi,1)
|
||||
jg L4x4_16
|
||||
movw %bp,6(%edx,%esi,1)
|
||||
movb %ch,3(%edi,%ebx,1)
|
||||
L4x4_16:
|
||||
|
||||
popl %esi
|
||||
jmp LDone
|
||||
|
||||
// default case, handling any size particle
|
||||
LDefault:
|
||||
|
||||
// count = pix << d_y_aspect_shift;
|
||||
|
||||
movl %eax,%ebx
|
||||
movl %eax,DP_Pix
|
||||
movb C(d_y_aspect_shift),%cl
|
||||
shll %cl,%ebx
|
||||
|
||||
// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
// {
|
||||
// for (i=0 ; i<pix ; i++)
|
||||
// {
|
||||
// if (pz[i] <= izi)
|
||||
// {
|
||||
// pz[i] = izi;
|
||||
// pdest[i] = color;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
LGenRowLoop:
|
||||
movl DP_Pix,%eax
|
||||
|
||||
LGenColLoop:
|
||||
cmpw %bp,-2(%edx,%eax,2)
|
||||
jg LGSkip
|
||||
movw %bp,-2(%edx,%eax,2)
|
||||
movb %ch,-1(%edi,%eax,1)
|
||||
LGSkip:
|
||||
decl %eax // --pix
|
||||
jnz LGenColLoop
|
||||
|
||||
addl C(d_zrowbytes),%edx
|
||||
addl C(screenwidth),%edi
|
||||
|
||||
decl %ebx // --count
|
||||
jnz LGenRowLoop
|
||||
|
||||
LDone:
|
||||
popl %ebx // restore register variables
|
||||
popl %edi
|
||||
popl %ebp // restore the caller's stack frame
|
||||
ret
|
||||
|
||||
LPop6AndDone:
|
||||
fstp %st(0)
|
||||
fstp %st(0)
|
||||
fstp %st(0)
|
||||
fstp %st(0)
|
||||
fstp %st(0)
|
||||
LPop1AndDone:
|
||||
fstp %st(0)
|
||||
jmp LDone
|
||||
|
||||
#endif // id386
|
1759
engine/sw/d_polysa.s
Normal file
1759
engine/sw/d_polysa.s
Normal file
File diff suppressed because it is too large
Load diff
2446
engine/sw/d_polyse.c
Normal file
2446
engine/sw/d_polyse.c
Normal file
File diff suppressed because it is too large
Load diff
1728
engine/sw/d_scan.c
Normal file
1728
engine/sw/d_scan.c
Normal file
File diff suppressed because it is too large
Load diff
89
engine/sw/d_scana.s
Normal file
89
engine/sw/d_scana.s
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
//
|
||||
// d_scana.s
|
||||
// x86 assembly-language turbulent texture mapping code
|
||||
//
|
||||
|
||||
#include "asm_i386.h"
|
||||
#include "quakeasm.h"
|
||||
#include "asm_draw.h"
|
||||
#include "d_ifacea.h"
|
||||
|
||||
#if id386
|
||||
|
||||
.data
|
||||
|
||||
.text
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// turbulent texture mapping code
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
.globl C(D_DrawTurbulent8Span)
|
||||
C(D_DrawTurbulent8Span):
|
||||
pushl %ebp // preserve caller's stack frame pointer
|
||||
pushl %esi // preserve register variables
|
||||
pushl %edi
|
||||
pushl %ebx
|
||||
|
||||
movl C(r_turb_s),%esi
|
||||
movl C(r_turb_t),%ecx
|
||||
movl C(r_turb_pdest),%edi
|
||||
movl C(r_turb_spancount),%ebx
|
||||
|
||||
Llp:
|
||||
movl %ecx,%eax
|
||||
movl %esi,%edx
|
||||
sarl $16,%eax
|
||||
movl C(r_turb_turb),%ebp
|
||||
sarl $16,%edx
|
||||
andl $(CYCLE-1),%eax
|
||||
andl $(CYCLE-1),%edx
|
||||
movl (%ebp,%eax,4),%eax
|
||||
movl (%ebp,%edx,4),%edx
|
||||
addl %esi,%eax
|
||||
sarl $16,%eax
|
||||
addl %ecx,%edx
|
||||
sarl $16,%edx
|
||||
andl $(TURB_TEX_SIZE-1),%eax
|
||||
andl $(TURB_TEX_SIZE-1),%edx
|
||||
shll $6,%edx
|
||||
movl C(r_turb_pbase),%ebp
|
||||
addl %eax,%edx
|
||||
incl %edi
|
||||
addl C(r_turb_sstep),%esi
|
||||
addl C(r_turb_tstep),%ecx
|
||||
movb (%ebp,%edx,1),%dl
|
||||
decl %ebx
|
||||
movb %dl,-1(%edi)
|
||||
jnz Llp
|
||||
|
||||
movl %edi,C(r_turb_pdest)
|
||||
|
||||
popl %ebx // restore register variables
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebp // restore caller's stack frame pointer
|
||||
ret
|
||||
|
||||
#endif // id386
|
||||
|
301
engine/sw/d_sky.c
Normal file
301
engine/sw/d_sky.c
Normal file
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_sky.c
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "r_local.h"
|
||||
#include "d_local.h"
|
||||
|
||||
#define SKY_SPAN_SHIFT 5
|
||||
#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT)
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
D_Sky_uv_To_st
|
||||
=================
|
||||
*/
|
||||
void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t)
|
||||
{
|
||||
float wu, wv, temp;
|
||||
vec3_t end;
|
||||
|
||||
if (r_refdef.vrect.width >= r_refdef.vrect.height)
|
||||
temp = (float)r_refdef.vrect.width;
|
||||
else
|
||||
temp = (float)r_refdef.vrect.height;
|
||||
|
||||
wu = 8192.0 * (float)(u-((int)vid.width>>1)) / temp;
|
||||
wv = 8192.0 * (float)(((int)vid.height>>1)-v) / temp;
|
||||
|
||||
end[0] = 4096*vpn[0] + wu*vright[0] + wv*vup[0];
|
||||
end[1] = 4096*vpn[1] + wu*vright[1] + wv*vup[1];
|
||||
end[2] = 4096*vpn[2] + wu*vright[2] + wv*vup[2];
|
||||
end[2] *= 3;
|
||||
VectorNormalize (end);
|
||||
|
||||
temp = skytime*skyspeed; // TODO: add D_SetupFrame & set this there
|
||||
*s = (int)((temp + 6*(SKYSIZE/2-1)*end[0]) * 0x10000);
|
||||
*t = (int)((temp + 6*(SKYSIZE/2-1)*end[1]) * 0x10000);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
D_DrawSkyScans8
|
||||
=================
|
||||
*/
|
||||
void D_DrawSkyScans8 (espan_t *pspan)
|
||||
{
|
||||
int count, spancount, u, v;
|
||||
unsigned char *pdest;
|
||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
||||
int spancountminus1;
|
||||
|
||||
sstep = 0; // keep compiler happy
|
||||
tstep = 0; // ditto
|
||||
|
||||
do
|
||||
{
|
||||
pdest = (unsigned char *)((qbyte *)d_viewbuffer +
|
||||
(screenwidth * pspan->v) + pspan->u);
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
// calculate the initial s & t
|
||||
u = pspan->u;
|
||||
v = pspan->v;
|
||||
D_Sky_uv_To_st (u, v, &s, &t);
|
||||
|
||||
do
|
||||
{
|
||||
if (count >= SKY_SPAN_MAX)
|
||||
spancount = SKY_SPAN_MAX;
|
||||
else
|
||||
spancount = count;
|
||||
|
||||
count -= spancount;
|
||||
|
||||
if (count)
|
||||
{
|
||||
u += spancount;
|
||||
|
||||
// calculate s and t at far end of span,
|
||||
// calculate s and t steps across span by shifting
|
||||
D_Sky_uv_To_st (u, v, &snext, &tnext);
|
||||
|
||||
sstep = (snext - s) >> SKY_SPAN_SHIFT;
|
||||
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate s and t at last pixel in span,
|
||||
// calculate s and t steps across span by division
|
||||
spancountminus1 = (float)(spancount - 1);
|
||||
|
||||
if (spancountminus1 > 0)
|
||||
{
|
||||
u += spancountminus1;
|
||||
D_Sky_uv_To_st (u, v, &snext, &tnext);
|
||||
|
||||
sstep = (snext - s) / spancountminus1;
|
||||
tstep = (tnext - t) / spancountminus1;
|
||||
}
|
||||
else
|
||||
{
|
||||
snext = 0;
|
||||
tnext = 0;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
*pdest++ = r_skysource[((t & R_SKY_TMASK) >> 8) +
|
||||
((s & R_SKY_SMASK) >> 16)];
|
||||
s += sstep;
|
||||
t += tstep;
|
||||
} while (--spancount > 0);
|
||||
|
||||
s = snext;
|
||||
t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
} while ((pspan = pspan->pnext) != NULL);
|
||||
}
|
||||
|
||||
void D_DrawSkyScans16 (espan_t *pspan)
|
||||
{
|
||||
int count, spancount, u, v;
|
||||
unsigned short *pdest;
|
||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
||||
int spancountminus1;
|
||||
|
||||
sstep = 0; // keep compiler happy
|
||||
tstep = 0; // ditto
|
||||
|
||||
do
|
||||
{
|
||||
pdest = ((unsigned short *)d_viewbuffer +
|
||||
(screenwidth * pspan->v) + pspan->u);
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
// calculate the initial s & t
|
||||
u = pspan->u;
|
||||
v = pspan->v;
|
||||
D_Sky_uv_To_st (u, v, &s, &t);
|
||||
|
||||
do
|
||||
{
|
||||
if (count >= SKY_SPAN_MAX)
|
||||
spancount = SKY_SPAN_MAX;
|
||||
else
|
||||
spancount = count;
|
||||
|
||||
count -= spancount;
|
||||
|
||||
if (count)
|
||||
{
|
||||
u += spancount;
|
||||
|
||||
// calculate s and t at far end of span,
|
||||
// calculate s and t steps across span by shifting
|
||||
D_Sky_uv_To_st (u, v, &snext, &tnext);
|
||||
|
||||
sstep = (snext - s) >> SKY_SPAN_SHIFT;
|
||||
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate s and t at last pixel in span,
|
||||
// calculate s and t steps across span by division
|
||||
spancountminus1 = (float)(spancount - 1);
|
||||
|
||||
if (spancountminus1 > 0)
|
||||
{
|
||||
u += spancountminus1;
|
||||
D_Sky_uv_To_st (u, v, &snext, &tnext);
|
||||
|
||||
sstep = (snext - s) / spancountminus1;
|
||||
tstep = (tnext - t) / spancountminus1;
|
||||
}
|
||||
else
|
||||
{
|
||||
snext=0;
|
||||
tnext=0;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
*pdest++ = d_8to16table[r_skysource[((t & R_SKY_TMASK) >> 8) +
|
||||
((s & R_SKY_SMASK) >> 16)]];
|
||||
s += sstep;
|
||||
t += tstep;
|
||||
} while (--spancount > 0);
|
||||
|
||||
s = snext;
|
||||
t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
} while ((pspan = pspan->pnext) != NULL);
|
||||
}
|
||||
|
||||
void D_DrawSkyScans32 (espan_t *pspan)
|
||||
{
|
||||
int count, spancount, u, v;
|
||||
unsigned int *pdest;
|
||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
||||
int spancountminus1;
|
||||
|
||||
sstep = 0; // keep compiler happy
|
||||
tstep = 0; // ditto
|
||||
|
||||
do
|
||||
{
|
||||
pdest = ((unsigned int *)d_viewbuffer +
|
||||
(screenwidth * pspan->v) + pspan->u);
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
// calculate the initial s & t
|
||||
u = pspan->u;
|
||||
v = pspan->v;
|
||||
D_Sky_uv_To_st (u, v, &s, &t);
|
||||
|
||||
do
|
||||
{
|
||||
if (count >= SKY_SPAN_MAX)
|
||||
spancount = SKY_SPAN_MAX;
|
||||
else
|
||||
spancount = count;
|
||||
|
||||
count -= spancount;
|
||||
|
||||
if (count)
|
||||
{
|
||||
u += spancount;
|
||||
|
||||
// calculate s and t at far end of span,
|
||||
// calculate s and t steps across span by shifting
|
||||
D_Sky_uv_To_st (u, v, &snext, &tnext);
|
||||
|
||||
sstep = (snext - s) >> SKY_SPAN_SHIFT;
|
||||
tstep = (tnext - t) >> SKY_SPAN_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate s and t at last pixel in span,
|
||||
// calculate s and t steps across span by division
|
||||
spancountminus1 = (float)(spancount - 1);
|
||||
|
||||
if (spancountminus1 > 0)
|
||||
{
|
||||
u += spancountminus1;
|
||||
D_Sky_uv_To_st (u, v, &snext, &tnext);
|
||||
|
||||
sstep = (snext - s) / spancountminus1;
|
||||
tstep = (tnext - t) / spancountminus1;
|
||||
}
|
||||
else
|
||||
{
|
||||
snext=0;
|
||||
tnext=0;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
*pdest++ = d_8to32table[r_skysource[((t & R_SKY_TMASK) >> 8) +
|
||||
((s & R_SKY_SMASK) >> 16)]];
|
||||
s += sstep;
|
||||
t += tstep;
|
||||
} while (--spancount > 0);
|
||||
|
||||
s = snext;
|
||||
t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
} while ((pspan = pspan->pnext) != NULL);
|
||||
}
|
||||
|
899
engine/sw/d_spr8.s
Normal file
899
engine/sw/d_spr8.s
Normal file
|
@ -0,0 +1,899 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
//
|
||||
// d_spr8.s
|
||||
// x86 assembly-language horizontal 8-bpp transparent span-drawing code.
|
||||
//
|
||||
#include "asm_i386.h"
|
||||
#include "quakeasm.h"
|
||||
#include "asm_draw.h"
|
||||
|
||||
#if id386
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 8-bpp horizontal span drawing code for polygons, with transparency.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
.text
|
||||
|
||||
// out-of-line, rarely-needed clamping code
|
||||
|
||||
LClampHigh0:
|
||||
movl C(bbextents),%esi
|
||||
jmp LClampReentry0
|
||||
LClampHighOrLow0:
|
||||
jg LClampHigh0
|
||||
xorl %esi,%esi
|
||||
jmp LClampReentry0
|
||||
|
||||
LClampHigh1:
|
||||
movl C(bbextentt),%edx
|
||||
jmp LClampReentry1
|
||||
LClampHighOrLow1:
|
||||
jg LClampHigh1
|
||||
xorl %edx,%edx
|
||||
jmp LClampReentry1
|
||||
|
||||
LClampLow2:
|
||||
movl $2048,%ebp
|
||||
jmp LClampReentry2
|
||||
LClampHigh2:
|
||||
movl C(bbextents),%ebp
|
||||
jmp LClampReentry2
|
||||
|
||||
LClampLow3:
|
||||
movl $2048,%ecx
|
||||
jmp LClampReentry3
|
||||
LClampHigh3:
|
||||
movl C(bbextentt),%ecx
|
||||
jmp LClampReentry3
|
||||
|
||||
LClampLow4:
|
||||
movl $2048,%eax
|
||||
jmp LClampReentry4
|
||||
LClampHigh4:
|
||||
movl C(bbextents),%eax
|
||||
jmp LClampReentry4
|
||||
|
||||
LClampLow5:
|
||||
movl $2048,%ebx
|
||||
jmp LClampReentry5
|
||||
LClampHigh5:
|
||||
movl C(bbextentt),%ebx
|
||||
jmp LClampReentry5
|
||||
|
||||
|
||||
#define pspans 4+16
|
||||
|
||||
.align 4
|
||||
.globl C(D_SpriteDrawSpans)
|
||||
C(D_SpriteDrawSpans):
|
||||
pushl %ebp // preserve caller's stack frame
|
||||
pushl %edi
|
||||
pushl %esi // preserve register variables
|
||||
pushl %ebx
|
||||
|
||||
//
|
||||
// set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
|
||||
// and span list pointers, and 1/z step in 0.32 fixed-point
|
||||
//
|
||||
// FIXME: any overlap from rearranging?
|
||||
flds C(d_sdivzstepu)
|
||||
fmuls fp_8
|
||||
movl C(cacheblock),%edx
|
||||
flds C(d_tdivzstepu)
|
||||
fmuls fp_8
|
||||
movl pspans(%esp),%ebx // point to the first span descriptor
|
||||
flds C(d_zistepu)
|
||||
fmuls fp_8
|
||||
movl %edx,pbase // pbase = cacheblock
|
||||
flds C(d_zistepu)
|
||||
fmuls fp_64kx64k
|
||||
fxch %st(3)
|
||||
fstps sdivz8stepu
|
||||
fstps zi8stepu
|
||||
fstps tdivz8stepu
|
||||
fistpl izistep
|
||||
movl izistep,%eax
|
||||
rorl $16,%eax // put upper 16 bits in low word
|
||||
movl sspan_t_count(%ebx),%ecx
|
||||
movl %eax,izistep
|
||||
|
||||
cmpl $0,%ecx
|
||||
jle LNextSpan
|
||||
|
||||
LSpanLoop:
|
||||
|
||||
//
|
||||
// set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
|
||||
// initial s and t values
|
||||
//
|
||||
// FIXME: pipeline FILD?
|
||||
fildl sspan_t_v(%ebx)
|
||||
fildl sspan_t_u(%ebx)
|
||||
|
||||
fld %st(1) // dv | du | dv
|
||||
fmuls C(d_sdivzstepv) // dv*d_sdivzstepv | du | dv
|
||||
fld %st(1) // du | dv*d_sdivzstepv | du | dv
|
||||
fmuls C(d_sdivzstepu) // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
|
||||
fld %st(2) // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
|
||||
fmuls C(d_tdivzstepu) // du*d_tdivzstepu | du*d_sdivzstepu |
|
||||
// dv*d_sdivzstepv | du | dv
|
||||
fxch %st(1) // du*d_sdivzstepu | du*d_tdivzstepu |
|
||||
// dv*d_sdivzstepv | du | dv
|
||||
faddp %st(0),%st(2) // du*d_tdivzstepu |
|
||||
// du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
|
||||
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
|
||||
// du*d_tdivzstepu | du | dv
|
||||
fld %st(3) // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
|
||||
// du*d_tdivzstepu | du | dv
|
||||
fmuls C(d_tdivzstepv) // dv*d_tdivzstepv |
|
||||
// du*d_sdivzstepu + dv*d_sdivzstepv |
|
||||
// du*d_tdivzstepu | du | dv
|
||||
fxch %st(1) // du*d_sdivzstepu + dv*d_sdivzstepv |
|
||||
// dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
|
||||
fadds C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
|
||||
// du*d_sdivzstepu; stays in %st(2) at end
|
||||
fxch %st(4) // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
|
||||
// s/z
|
||||
fmuls C(d_zistepv) // dv*d_zistepv | dv*d_tdivzstepv |
|
||||
// du*d_tdivzstepu | du | s/z
|
||||
fxch %st(1) // dv*d_tdivzstepv | dv*d_zistepv |
|
||||
// du*d_tdivzstepu | du | s/z
|
||||
faddp %st(0),%st(2) // dv*d_zistepv |
|
||||
// dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
|
||||
fxch %st(2) // du | dv*d_tdivzstepv + du*d_tdivzstepu |
|
||||
// dv*d_zistepv | s/z
|
||||
fmuls C(d_zistepu) // du*d_zistepu |
|
||||
// dv*d_tdivzstepv + du*d_tdivzstepu |
|
||||
// dv*d_zistepv | s/z
|
||||
fxch %st(1) // dv*d_tdivzstepv + du*d_tdivzstepu |
|
||||
// du*d_zistepu | dv*d_zistepv | s/z
|
||||
fadds C(d_tdivzorigin) // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
|
||||
// du*d_tdivzstepu; stays in %st(1) at end
|
||||
fxch %st(2) // dv*d_zistepv | du*d_zistepu | t/z | s/z
|
||||
faddp %st(0),%st(1) // dv*d_zistepv + du*d_zistepu | t/z | s/z
|
||||
|
||||
flds fp_64k // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
|
||||
fxch %st(1) // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
|
||||
fadds C(d_ziorigin) // zi = d_ziorigin + dv*d_zistepv +
|
||||
// du*d_zistepu; stays in %st(0) at end
|
||||
// 1/z | fp_64k | t/z | s/z
|
||||
|
||||
fld %st(0) // FIXME: get rid of stall on FMUL?
|
||||
fmuls fp_64kx64k
|
||||
fxch %st(1)
|
||||
|
||||
//
|
||||
// calculate and clamp s & t
|
||||
//
|
||||
fdivr %st(0),%st(2) // 1/z | z*64k | t/z | s/z
|
||||
fxch %st(1)
|
||||
|
||||
fistpl izi // 0.32 fixed-point 1/z
|
||||
movl izi,%ebp
|
||||
|
||||
//
|
||||
// set pz to point to the first z-buffer pixel in the span
|
||||
//
|
||||
rorl $16,%ebp // put upper 16 bits in low word
|
||||
movl sspan_t_v(%ebx),%eax
|
||||
movl %ebp,izi
|
||||
movl sspan_t_u(%ebx),%ebp
|
||||
imull C(d_zrowbytes)
|
||||
shll $1,%ebp // a word per pixel
|
||||
addl C(d_pzbuffer),%eax
|
||||
addl %ebp,%eax
|
||||
movl %eax,pz
|
||||
|
||||
//
|
||||
// point %edi to the first pixel in the span
|
||||
//
|
||||
movl C(d_viewbuffer),%ebp
|
||||
movl sspan_t_v(%ebx),%eax
|
||||
pushl %ebx // preserve spans pointer
|
||||
movl C(tadjust),%edx
|
||||
movl C(sadjust),%esi
|
||||
movl C(d_scantable)(,%eax,4),%edi // v * screenwidth
|
||||
addl %ebp,%edi
|
||||
movl sspan_t_u(%ebx),%ebp
|
||||
addl %ebp,%edi // pdest = &pdestspan[scans->u];
|
||||
|
||||
//
|
||||
// now start the FDIV for the end of the span
|
||||
//
|
||||
cmpl $8,%ecx
|
||||
ja LSetupNotLast1
|
||||
|
||||
decl %ecx
|
||||
jz LCleanup1 // if only one pixel, no need to start an FDIV
|
||||
movl %ecx,spancountminus1
|
||||
|
||||
// finish up the s and t calcs
|
||||
fxch %st(1) // z*64k | 1/z | t/z | s/z
|
||||
|
||||
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
|
||||
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
|
||||
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
|
||||
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
|
||||
fxch %st(1) // s | t | 1/z | t/z | s/z
|
||||
fistpl s // 1/z | t | t/z | s/z
|
||||
fistpl t // 1/z | t/z | s/z
|
||||
|
||||
fildl spancountminus1
|
||||
|
||||
flds C(d_tdivzstepu) // _d_tdivzstepu | spancountminus1
|
||||
flds C(d_zistepu) // _d_zistepu | _d_tdivzstepu | spancountminus1
|
||||
fmul %st(2),%st(0) // _d_zistepu*scm1 | _d_tdivzstepu | scm1
|
||||
fxch %st(1) // _d_tdivzstepu | _d_zistepu*scm1 | scm1
|
||||
fmul %st(2),%st(0) // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
|
||||
fxch %st(2) // scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1
|
||||
fmuls C(d_sdivzstepu) // _d_sdivzstepu*scm1 | _d_zistepu*scm1 |
|
||||
// _d_tdivzstepu*scm1
|
||||
fxch %st(1) // _d_zistepu*scm1 | _d_sdivzstepu*scm1 |
|
||||
// _d_tdivzstepu*scm1
|
||||
faddp %st(0),%st(3) // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
|
||||
fxch %st(1) // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
|
||||
faddp %st(0),%st(3) // _d_sdivzstepu*scm1
|
||||
faddp %st(0),%st(3)
|
||||
|
||||
flds fp_64k
|
||||
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
|
||||
// overlap
|
||||
jmp LFDIVInFlight1
|
||||
|
||||
LCleanup1:
|
||||
// finish up the s and t calcs
|
||||
fxch %st(1) // z*64k | 1/z | t/z | s/z
|
||||
|
||||
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
|
||||
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
|
||||
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
|
||||
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
|
||||
fxch %st(1) // s | t | 1/z | t/z | s/z
|
||||
fistpl s // 1/z | t | t/z | s/z
|
||||
fistpl t // 1/z | t/z | s/z
|
||||
jmp LFDIVInFlight1
|
||||
|
||||
.align 4
|
||||
LSetupNotLast1:
|
||||
// finish up the s and t calcs
|
||||
fxch %st(1) // z*64k | 1/z | t/z | s/z
|
||||
|
||||
fld %st(0) // z*64k | z*64k | 1/z | t/z | s/z
|
||||
fmul %st(4),%st(0) // s | z*64k | 1/z | t/z | s/z
|
||||
fxch %st(1) // z*64k | s | 1/z | t/z | s/z
|
||||
fmul %st(3),%st(0) // t | s | 1/z | t/z | s/z
|
||||
fxch %st(1) // s | t | 1/z | t/z | s/z
|
||||
fistpl s // 1/z | t | t/z | s/z
|
||||
fistpl t // 1/z | t/z | s/z
|
||||
|
||||
fadds zi8stepu
|
||||
fxch %st(2)
|
||||
fadds sdivz8stepu
|
||||
fxch %st(2)
|
||||
flds tdivz8stepu
|
||||
faddp %st(0),%st(2)
|
||||
flds fp_64k
|
||||
fdiv %st(1),%st(0) // z = 1/1/z
|
||||
// this is what we've gone to all this trouble to
|
||||
// overlap
|
||||
LFDIVInFlight1:
|
||||
|
||||
addl s,%esi
|
||||
addl t,%edx
|
||||
movl C(bbextents),%ebx
|
||||
movl C(bbextentt),%ebp
|
||||
cmpl %ebx,%esi
|
||||
ja LClampHighOrLow0
|
||||
LClampReentry0:
|
||||
movl %esi,s
|
||||
movl pbase,%ebx
|
||||
shll $16,%esi
|
||||
cmpl %ebp,%edx
|
||||
movl %esi,sfracf
|
||||
ja LClampHighOrLow1
|
||||
LClampReentry1:
|
||||
movl %edx,t
|
||||
movl s,%esi // sfrac = scans->sfrac;
|
||||
shll $16,%edx
|
||||
movl t,%eax // tfrac = scans->tfrac;
|
||||
sarl $16,%esi
|
||||
movl %edx,tfracf
|
||||
|
||||
//
|
||||
// calculate the texture starting address
|
||||
//
|
||||
sarl $16,%eax
|
||||
addl %ebx,%esi
|
||||
imull C(cachewidth),%eax // (tfrac >> 16) * cachewidth
|
||||
addl %eax,%esi // psource = pbase + (sfrac >> 16) +
|
||||
// ((tfrac >> 16) * cachewidth);
|
||||
|
||||
//
|
||||
// determine whether last span or not
|
||||
//
|
||||
cmpl $8,%ecx
|
||||
jna LLastSegment
|
||||
|
||||
//
|
||||
// not the last segment; do full 8-wide segment
|
||||
//
|
||||
LNotLastSegment:
|
||||
|
||||
//
|
||||
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
|
||||
// get there
|
||||
//
|
||||
|
||||
// pick up after the FDIV that was left in flight previously
|
||||
|
||||
fld %st(0) // duplicate it
|
||||
fmul %st(4),%st(0) // s = s/z * z
|
||||
fxch %st(1)
|
||||
fmul %st(3),%st(0) // t = t/z * z
|
||||
fxch %st(1)
|
||||
fistpl snext
|
||||
fistpl tnext
|
||||
movl snext,%eax
|
||||
movl tnext,%edx
|
||||
|
||||
subl $8,%ecx // count off this segments' pixels
|
||||
movl C(sadjust),%ebp
|
||||
pushl %ecx // remember count of remaining pixels
|
||||
movl C(tadjust),%ecx
|
||||
|
||||
addl %eax,%ebp
|
||||
addl %edx,%ecx
|
||||
|
||||
movl C(bbextents),%eax
|
||||
movl C(bbextentt),%edx
|
||||
|
||||
cmpl $2048,%ebp
|
||||
jl LClampLow2
|
||||
cmpl %eax,%ebp
|
||||
ja LClampHigh2
|
||||
LClampReentry2:
|
||||
|
||||
cmpl $2048,%ecx
|
||||
jl LClampLow3
|
||||
cmpl %edx,%ecx
|
||||
ja LClampHigh3
|
||||
LClampReentry3:
|
||||
|
||||
movl %ebp,snext
|
||||
movl %ecx,tnext
|
||||
|
||||
subl s,%ebp
|
||||
subl t,%ecx
|
||||
|
||||
//
|
||||
// set up advancetable
|
||||
//
|
||||
movl %ecx,%eax
|
||||
movl %ebp,%edx
|
||||
sarl $19,%edx // sstep >>= 16;
|
||||
movl C(cachewidth),%ebx
|
||||
sarl $19,%eax // tstep >>= 16;
|
||||
jz LIsZero
|
||||
imull %ebx,%eax // (tstep >> 16) * cachewidth;
|
||||
LIsZero:
|
||||
addl %edx,%eax // add in sstep
|
||||
// (tstep >> 16) * cachewidth + (sstep >> 16);
|
||||
movl tfracf,%edx
|
||||
movl %eax,advancetable+4 // advance base in t
|
||||
addl %ebx,%eax // ((tstep >> 16) + 1) * cachewidth +
|
||||
// (sstep >> 16);
|
||||
shll $13,%ebp // left-justify sstep fractional part
|
||||
movl %ebp,sstep
|
||||
movl sfracf,%ebx
|
||||
shll $13,%ecx // left-justify tstep fractional part
|
||||
movl %eax,advancetable // advance extra in t
|
||||
movl %ecx,tstep
|
||||
|
||||
movl pz,%ecx
|
||||
movl izi,%ebp
|
||||
|
||||
cmpw (%ecx),%bp
|
||||
jl Lp1
|
||||
movb (%esi),%al // get first source texel
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp1
|
||||
movw %bp,(%ecx)
|
||||
movb %al,(%edi) // store first dest pixel
|
||||
Lp1:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx // advance tfrac fractional part by tstep frac
|
||||
|
||||
sbbl %eax,%eax // turn tstep carry into -1 (0 if none)
|
||||
addl sstep,%ebx // advance sfrac fractional part by sstep frac
|
||||
adcl advancetable+4(,%eax,4),%esi // point to next source texel
|
||||
|
||||
cmpw 2(%ecx),%bp
|
||||
jl Lp2
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp2
|
||||
movw %bp,2(%ecx)
|
||||
movb %al,1(%edi)
|
||||
Lp2:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
|
||||
cmpw 4(%ecx),%bp
|
||||
jl Lp3
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp3
|
||||
movw %bp,4(%ecx)
|
||||
movb %al,2(%edi)
|
||||
Lp3:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
|
||||
cmpw 6(%ecx),%bp
|
||||
jl Lp4
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp4
|
||||
movw %bp,6(%ecx)
|
||||
movb %al,3(%edi)
|
||||
Lp4:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
|
||||
cmpw 8(%ecx),%bp
|
||||
jl Lp5
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp5
|
||||
movw %bp,8(%ecx)
|
||||
movb %al,4(%edi)
|
||||
Lp5:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
|
||||
//
|
||||
// start FDIV for end of next segment in flight, so it can overlap
|
||||
//
|
||||
popl %eax
|
||||
cmpl $8,%eax // more than one segment after this?
|
||||
ja LSetupNotLast2 // yes
|
||||
|
||||
decl %eax
|
||||
jz LFDIVInFlight2 // if only one pixel, no need to start an FDIV
|
||||
movl %eax,spancountminus1
|
||||
fildl spancountminus1
|
||||
|
||||
flds C(d_zistepu) // _d_zistepu | spancountminus1
|
||||
fmul %st(1),%st(0) // _d_zistepu*scm1 | scm1
|
||||
flds C(d_tdivzstepu) // _d_tdivzstepu | _d_zistepu*scm1 | scm1
|
||||
fmul %st(2),%st(0) // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
|
||||
fxch %st(1) // _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1
|
||||
faddp %st(0),%st(3) // _d_tdivzstepu*scm1 | scm1
|
||||
fxch %st(1) // scm1 | _d_tdivzstepu*scm1
|
||||
fmuls C(d_sdivzstepu) // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
|
||||
fxch %st(1) // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
|
||||
faddp %st(0),%st(3) // _d_sdivzstepu*scm1
|
||||
flds fp_64k // 64k | _d_sdivzstepu*scm1
|
||||
fxch %st(1) // _d_sdivzstepu*scm1 | 64k
|
||||
faddp %st(0),%st(4) // 64k
|
||||
|
||||
fdiv %st(1),%st(0) // this is what we've gone to all this trouble to
|
||||
// overlap
|
||||
jmp LFDIVInFlight2
|
||||
|
||||
.align 4
|
||||
LSetupNotLast2:
|
||||
fadds zi8stepu
|
||||
fxch %st(2)
|
||||
fadds sdivz8stepu
|
||||
fxch %st(2)
|
||||
flds tdivz8stepu
|
||||
faddp %st(0),%st(2)
|
||||
flds fp_64k
|
||||
fdiv %st(1),%st(0) // z = 1/1/z
|
||||
// this is what we've gone to all this trouble to
|
||||
// overlap
|
||||
LFDIVInFlight2:
|
||||
pushl %eax
|
||||
|
||||
cmpw 10(%ecx),%bp
|
||||
jl Lp6
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp6
|
||||
movw %bp,10(%ecx)
|
||||
movb %al,5(%edi)
|
||||
Lp6:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
|
||||
cmpw 12(%ecx),%bp
|
||||
jl Lp7
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp7
|
||||
movw %bp,12(%ecx)
|
||||
movb %al,6(%edi)
|
||||
Lp7:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
|
||||
cmpw 14(%ecx),%bp
|
||||
jl Lp8
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp8
|
||||
movw %bp,14(%ecx)
|
||||
movb %al,7(%edi)
|
||||
Lp8:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
|
||||
addl $8,%edi
|
||||
addl $16,%ecx
|
||||
movl %edx,tfracf
|
||||
movl snext,%edx
|
||||
movl %ebx,sfracf
|
||||
movl tnext,%ebx
|
||||
movl %edx,s
|
||||
movl %ebx,t
|
||||
|
||||
movl %ecx,pz
|
||||
movl %ebp,izi
|
||||
|
||||
popl %ecx // retrieve count
|
||||
|
||||
//
|
||||
// determine whether last span or not
|
||||
//
|
||||
cmpl $8,%ecx // are there multiple segments remaining?
|
||||
ja LNotLastSegment // yes
|
||||
|
||||
//
|
||||
// last segment of scan
|
||||
//
|
||||
LLastSegment:
|
||||
|
||||
//
|
||||
// advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
|
||||
// get there. The number of pixels left is variable, and we want to land on the
|
||||
// last pixel, not step one past it, so we can't run into arithmetic problems
|
||||
//
|
||||
testl %ecx,%ecx
|
||||
jz LNoSteps // just draw the last pixel and we're done
|
||||
|
||||
// pick up after the FDIV that was left in flight previously
|
||||
|
||||
|
||||
fld %st(0) // duplicate it
|
||||
fmul %st(4),%st(0) // s = s/z * z
|
||||
fxch %st(1)
|
||||
fmul %st(3),%st(0) // t = t/z * z
|
||||
fxch %st(1)
|
||||
fistpl snext
|
||||
fistpl tnext
|
||||
|
||||
movl C(tadjust),%ebx
|
||||
movl C(sadjust),%eax
|
||||
|
||||
addl snext,%eax
|
||||
addl tnext,%ebx
|
||||
|
||||
movl C(bbextents),%ebp
|
||||
movl C(bbextentt),%edx
|
||||
|
||||
cmpl $2048,%eax
|
||||
jl LClampLow4
|
||||
cmpl %ebp,%eax
|
||||
ja LClampHigh4
|
||||
LClampReentry4:
|
||||
movl %eax,snext
|
||||
|
||||
cmpl $2048,%ebx
|
||||
jl LClampLow5
|
||||
cmpl %edx,%ebx
|
||||
ja LClampHigh5
|
||||
LClampReentry5:
|
||||
|
||||
cmpl $1,%ecx // don't bother
|
||||
je LOnlyOneStep // if two pixels in segment, there's only one step,
|
||||
// of the segment length
|
||||
subl s,%eax
|
||||
subl t,%ebx
|
||||
|
||||
addl %eax,%eax // convert to 15.17 format so multiply by 1.31
|
||||
addl %ebx,%ebx // reciprocal yields 16.48
|
||||
imull reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
|
||||
movl %edx,%ebp
|
||||
|
||||
movl %ebx,%eax
|
||||
imull reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
|
||||
|
||||
LSetEntryvec:
|
||||
//
|
||||
// set up advancetable
|
||||
//
|
||||
movl spr8entryvec_table(,%ecx,4),%ebx
|
||||
movl %edx,%eax
|
||||
pushl %ebx // entry point into code for RET later
|
||||
movl %ebp,%ecx
|
||||
sarl $16,%ecx // sstep >>= 16;
|
||||
movl C(cachewidth),%ebx
|
||||
sarl $16,%edx // tstep >>= 16;
|
||||
jz LIsZeroLast
|
||||
imull %ebx,%edx // (tstep >> 16) * cachewidth;
|
||||
LIsZeroLast:
|
||||
addl %ecx,%edx // add in sstep
|
||||
// (tstep >> 16) * cachewidth + (sstep >> 16);
|
||||
movl tfracf,%ecx
|
||||
movl %edx,advancetable+4 // advance base in t
|
||||
addl %ebx,%edx // ((tstep >> 16) + 1) * cachewidth +
|
||||
// (sstep >> 16);
|
||||
shll $16,%ebp // left-justify sstep fractional part
|
||||
movl sfracf,%ebx
|
||||
shll $16,%eax // left-justify tstep fractional part
|
||||
movl %edx,advancetable // advance extra in t
|
||||
|
||||
movl %eax,tstep
|
||||
movl %ebp,sstep
|
||||
movl %ecx,%edx
|
||||
|
||||
movl pz,%ecx
|
||||
movl izi,%ebp
|
||||
|
||||
ret // jump to the number-of-pixels handler
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
LNoSteps:
|
||||
movl pz,%ecx
|
||||
subl $7,%edi // adjust for hardwired offset
|
||||
subl $14,%ecx
|
||||
jmp LEndSpan
|
||||
|
||||
|
||||
LOnlyOneStep:
|
||||
subl s,%eax
|
||||
subl t,%ebx
|
||||
movl %eax,%ebp
|
||||
movl %ebx,%edx
|
||||
jmp LSetEntryvec
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
.globl Spr8Entry2_8
|
||||
Spr8Entry2_8:
|
||||
subl $6,%edi // adjust for hardwired offsets
|
||||
subl $12,%ecx
|
||||
movb (%esi),%al
|
||||
jmp LLEntry2_8
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
.globl Spr8Entry3_8
|
||||
Spr8Entry3_8:
|
||||
subl $5,%edi // adjust for hardwired offsets
|
||||
subl $10,%ecx
|
||||
jmp LLEntry3_8
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
.globl Spr8Entry4_8
|
||||
Spr8Entry4_8:
|
||||
subl $4,%edi // adjust for hardwired offsets
|
||||
subl $8,%ecx
|
||||
jmp LLEntry4_8
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
.globl Spr8Entry5_8
|
||||
Spr8Entry5_8:
|
||||
subl $3,%edi // adjust for hardwired offsets
|
||||
subl $6,%ecx
|
||||
jmp LLEntry5_8
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
.globl Spr8Entry6_8
|
||||
Spr8Entry6_8:
|
||||
subl $2,%edi // adjust for hardwired offsets
|
||||
subl $4,%ecx
|
||||
jmp LLEntry6_8
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
.globl Spr8Entry7_8
|
||||
Spr8Entry7_8:
|
||||
decl %edi // adjust for hardwired offsets
|
||||
subl $2,%ecx
|
||||
jmp LLEntry7_8
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
.globl Spr8Entry8_8
|
||||
Spr8Entry8_8:
|
||||
cmpw (%ecx),%bp
|
||||
jl Lp9
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp9
|
||||
movw %bp,(%ecx)
|
||||
movb %al,(%edi)
|
||||
Lp9:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
LLEntry7_8:
|
||||
cmpw 2(%ecx),%bp
|
||||
jl Lp10
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp10
|
||||
movw %bp,2(%ecx)
|
||||
movb %al,1(%edi)
|
||||
Lp10:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
LLEntry6_8:
|
||||
cmpw 4(%ecx),%bp
|
||||
jl Lp11
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp11
|
||||
movw %bp,4(%ecx)
|
||||
movb %al,2(%edi)
|
||||
Lp11:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
LLEntry5_8:
|
||||
cmpw 6(%ecx),%bp
|
||||
jl Lp12
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp12
|
||||
movw %bp,6(%ecx)
|
||||
movb %al,3(%edi)
|
||||
Lp12:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
LLEntry4_8:
|
||||
cmpw 8(%ecx),%bp
|
||||
jl Lp13
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp13
|
||||
movw %bp,8(%ecx)
|
||||
movb %al,4(%edi)
|
||||
Lp13:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
LLEntry3_8:
|
||||
cmpw 10(%ecx),%bp
|
||||
jl Lp14
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp14
|
||||
movw %bp,10(%ecx)
|
||||
movb %al,5(%edi)
|
||||
Lp14:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
LLEntry2_8:
|
||||
cmpw 12(%ecx),%bp
|
||||
jl Lp15
|
||||
movb (%esi),%al
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp15
|
||||
movw %bp,12(%ecx)
|
||||
movb %al,6(%edi)
|
||||
Lp15:
|
||||
addl izistep,%ebp
|
||||
adcl $0,%ebp
|
||||
addl tstep,%edx
|
||||
sbbl %eax,%eax
|
||||
addl sstep,%ebx
|
||||
adcl advancetable+4(,%eax,4),%esi
|
||||
|
||||
LEndSpan:
|
||||
cmpw 14(%ecx),%bp
|
||||
jl Lp16
|
||||
movb (%esi),%al // load first texel in segment
|
||||
cmpb $(TRANSPARENT_COLOR),%al
|
||||
jz Lp16
|
||||
movw %bp,14(%ecx)
|
||||
movb %al,7(%edi)
|
||||
Lp16:
|
||||
|
||||
//
|
||||
// clear s/z, t/z, 1/z from FP stack
|
||||
//
|
||||
fstp %st(0)
|
||||
fstp %st(0)
|
||||
fstp %st(0)
|
||||
|
||||
popl %ebx // restore spans pointer
|
||||
LNextSpan:
|
||||
addl $(sspan_t_size),%ebx // point to next span
|
||||
movl sspan_t_count(%ebx),%ecx
|
||||
cmpl $0,%ecx // any more spans?
|
||||
jg LSpanLoop // yes
|
||||
jz LNextSpan // yes, but this one's empty
|
||||
|
||||
popl %ebx // restore register variables
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp // restore the caller's stack frame
|
||||
ret
|
||||
|
||||
#endif // id386
|
926
engine/sw/d_sprite.c
Normal file
926
engine/sw/d_sprite.c
Normal file
|
@ -0,0 +1,926 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_sprite.c: software top-level rasterization driver module for drawing
|
||||
// sprites
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "d_local.h"
|
||||
|
||||
static int sprite_height;
|
||||
static int minindex, maxindex;
|
||||
static sspan_t *sprite_spans;
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
=====================
|
||||
D_SpriteDrawSpans
|
||||
=====================
|
||||
*/
|
||||
void D_SpriteDrawSpans (sspan_t *pspan)
|
||||
{
|
||||
int count, spancount, izistep;
|
||||
int izi;
|
||||
qbyte *pbase, *pdest;
|
||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
||||
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
||||
qbyte btemp;
|
||||
short *pz;
|
||||
|
||||
sstep = 0; // keep compiler happy
|
||||
tstep = 0; // ditto
|
||||
|
||||
pbase = cacheblock;
|
||||
|
||||
sdivz8stepu = d_sdivzstepu * 8;
|
||||
tdivz8stepu = d_tdivzstepu * 8;
|
||||
zi8stepu = d_zistepu * 8;
|
||||
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
|
||||
|
||||
do
|
||||
{
|
||||
pdest = (qbyte *)d_viewbuffer + r_pixbytes*((screenwidth * pspan->v) + pspan->u);
|
||||
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
if (count <= 0)
|
||||
goto NextSpan;
|
||||
|
||||
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
|
||||
du = (float)pspan->u;
|
||||
dv = (float)pspan->v;
|
||||
|
||||
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
|
||||
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
|
||||
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izi = (int)(zi * 0x8000 * 0x10000);
|
||||
|
||||
s = (int)(sdivz * z) + sadjust;
|
||||
if (s > bbextents)
|
||||
s = bbextents;
|
||||
else if (s < 0)
|
||||
s = 0;
|
||||
|
||||
t = (int)(tdivz * z) + tadjust;
|
||||
if (t > bbextentt)
|
||||
t = bbextentt;
|
||||
else if (t < 0)
|
||||
t = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// calculate s and t at the far end of the span
|
||||
if (count >= 8)
|
||||
spancount = 8;
|
||||
else
|
||||
spancount = count;
|
||||
|
||||
count -= spancount;
|
||||
|
||||
if (count)
|
||||
{
|
||||
// calculate s/z, t/z, zi->fixed s and t at far end of span,
|
||||
// calculate s and t steps across span by shifting
|
||||
sdivz += sdivz8stepu;
|
||||
tdivz += tdivz8stepu;
|
||||
zi += zi8stepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 8)
|
||||
snext = 8; // prevent round-off error on <0 steps from
|
||||
// from causing overstepping & running off the
|
||||
// edge of the texture
|
||||
|
||||
tnext = (int)(tdivz * z) + tadjust;
|
||||
if (tnext > bbextentt)
|
||||
tnext = bbextentt;
|
||||
else if (tnext < 8)
|
||||
tnext = 8; // guard against round-off error on <0 steps
|
||||
|
||||
sstep = (snext - s) >> 3;
|
||||
tstep = (tnext - t) >> 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
|
||||
// can't step off polygon), clamp, calculate s and t steps across
|
||||
// span by division, biasing steps low so we don't run off the
|
||||
// texture
|
||||
spancountminus1 = (float)(spancount - 1);
|
||||
sdivz += d_sdivzstepu * spancountminus1;
|
||||
tdivz += d_tdivzstepu * spancountminus1;
|
||||
zi += d_zistepu * spancountminus1;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 8)
|
||||
snext = 8; // prevent round-off error on <0 steps from
|
||||
// from causing overstepping & running off the
|
||||
// edge of the texture
|
||||
|
||||
tnext = (int)(tdivz * z) + tadjust;
|
||||
if (tnext > bbextentt)
|
||||
tnext = bbextentt;
|
||||
else if (tnext < 8)
|
||||
tnext = 8; // guard against round-off error on <0 steps
|
||||
|
||||
if (spancount > 1)
|
||||
{
|
||||
sstep = (snext - s) / (spancount - 1);
|
||||
tstep = (tnext - t) / (spancount - 1);
|
||||
}
|
||||
}
|
||||
do
|
||||
{
|
||||
btemp = *(pbase + ((s >> 16) + (t >> 16) * cachewidth));
|
||||
if (btemp != 255)
|
||||
{
|
||||
if (*pz <= (izi >> 16))
|
||||
{
|
||||
*pz = izi >> 16;
|
||||
*pdest = btemp;
|
||||
}
|
||||
}
|
||||
|
||||
izi += izistep;
|
||||
pdest++;
|
||||
pz++;
|
||||
s += sstep;
|
||||
t += tstep;
|
||||
} while (--spancount > 0);
|
||||
|
||||
s = snext;
|
||||
t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
NextSpan:
|
||||
pspan++;
|
||||
|
||||
} while (pspan->count != DS_SPAN_LIST_END);
|
||||
}
|
||||
#endif
|
||||
|
||||
void D_SpriteDrawSpans16 (sspan_t *pspan)
|
||||
{
|
||||
int count, spancount, izistep;
|
||||
int izi;
|
||||
unsigned short *pbase, *pdest;
|
||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
||||
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
||||
unsigned short btemp;
|
||||
short *pz;
|
||||
|
||||
sstep = 0; // keep compiler happy
|
||||
tstep = 0; // ditto
|
||||
|
||||
pbase = (unsigned short *)cacheblock;
|
||||
|
||||
sdivz8stepu = d_sdivzstepu * 8;
|
||||
tdivz8stepu = d_tdivzstepu * 8;
|
||||
zi8stepu = d_zistepu * 8;
|
||||
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
|
||||
|
||||
do
|
||||
{
|
||||
pdest = (unsigned short *)d_viewbuffer + ((screenwidth * pspan->v) + pspan->u);
|
||||
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
if (count <= 0)
|
||||
goto NextSpan;
|
||||
|
||||
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
|
||||
du = (float)pspan->u;
|
||||
dv = (float)pspan->v;
|
||||
|
||||
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
|
||||
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
|
||||
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izi = (int)(zi * 0x8000 * 0x10000);
|
||||
|
||||
s = (int)(sdivz * z) + sadjust;
|
||||
if (s > bbextents)
|
||||
s = bbextents;
|
||||
else if (s < 0)
|
||||
s = 0;
|
||||
|
||||
t = (int)(tdivz * z) + tadjust;
|
||||
if (t > bbextentt)
|
||||
t = bbextentt;
|
||||
else if (t < 0)
|
||||
t = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// calculate s and t at the far end of the span
|
||||
if (count >= 8)
|
||||
spancount = 8;
|
||||
else
|
||||
spancount = count;
|
||||
|
||||
count -= spancount;
|
||||
|
||||
if (count)
|
||||
{
|
||||
// calculate s/z, t/z, zi->fixed s and t at far end of span,
|
||||
// calculate s and t steps across span by shifting
|
||||
sdivz += sdivz8stepu;
|
||||
tdivz += tdivz8stepu;
|
||||
zi += zi8stepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 8)
|
||||
snext = 8; // prevent round-off error on <0 steps from
|
||||
// from causing overstepping & running off the
|
||||
// edge of the texture
|
||||
|
||||
tnext = (int)(tdivz * z) + tadjust;
|
||||
if (tnext > bbextentt)
|
||||
tnext = bbextentt;
|
||||
else if (tnext < 8)
|
||||
tnext = 8; // guard against round-off error on <0 steps
|
||||
|
||||
sstep = (snext - s) >> 3;
|
||||
tstep = (tnext - t) >> 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
|
||||
// can't step off polygon), clamp, calculate s and t steps across
|
||||
// span by division, biasing steps low so we don't run off the
|
||||
// texture
|
||||
spancountminus1 = (float)(spancount - 1);
|
||||
sdivz += d_sdivzstepu * spancountminus1;
|
||||
tdivz += d_tdivzstepu * spancountminus1;
|
||||
zi += d_zistepu * spancountminus1;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 8)
|
||||
snext = 8; // prevent round-off error on <0 steps from
|
||||
// from causing overstepping & running off the
|
||||
// edge of the texture
|
||||
|
||||
tnext = (int)(tdivz * z) + tadjust;
|
||||
if (tnext > bbextentt)
|
||||
tnext = bbextentt;
|
||||
else if (tnext < 8)
|
||||
tnext = 8; // guard against round-off error on <0 steps
|
||||
|
||||
if (spancount > 1)
|
||||
{
|
||||
sstep = (snext - s) / (spancount - 1);
|
||||
tstep = (tnext - t) / (spancount - 1);
|
||||
}
|
||||
}
|
||||
do
|
||||
{
|
||||
btemp = *(pbase + ((s >> 16) + (t >> 16) * cachewidth));
|
||||
if (btemp != 0xffff)
|
||||
{
|
||||
if (*pz <= (izi >> 16))
|
||||
{
|
||||
*pz = izi >> 16;
|
||||
*pdest = btemp;
|
||||
}
|
||||
}
|
||||
|
||||
izi += izistep;
|
||||
pdest++;
|
||||
pz++;
|
||||
s += sstep;
|
||||
t += tstep;
|
||||
} while (--spancount > 0);
|
||||
|
||||
s = snext;
|
||||
t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
NextSpan:
|
||||
pspan++;
|
||||
|
||||
} while (pspan->count != DS_SPAN_LIST_END);
|
||||
}
|
||||
|
||||
|
||||
void D_SpriteDrawSpans32 (sspan_t *pspan)
|
||||
{
|
||||
int count, spancount, izistep;
|
||||
int izi;
|
||||
unsigned int *pbase, *pdest;
|
||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
||||
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
||||
unsigned int itemp;
|
||||
qbyte *pbtemp, *pbdest, alpha;
|
||||
short *pz;
|
||||
|
||||
sstep = 0; // keep compiler happy
|
||||
tstep = 0; // ditto
|
||||
|
||||
pbase = (unsigned int*)cacheblock;
|
||||
|
||||
sdivz8stepu = d_sdivzstepu * 8;
|
||||
tdivz8stepu = d_tdivzstepu * 8;
|
||||
zi8stepu = d_zistepu * 8;
|
||||
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
|
||||
|
||||
do
|
||||
{
|
||||
pdest = (unsigned int *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
|
||||
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
if (count <= 0)
|
||||
goto NextSpan;
|
||||
|
||||
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
|
||||
du = (float)pspan->u;
|
||||
dv = (float)pspan->v;
|
||||
|
||||
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
|
||||
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
|
||||
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izi = (int)(zi * 0x8000 * 0x10000);
|
||||
|
||||
s = (int)(sdivz * z) + sadjust;
|
||||
if (s > bbextents)
|
||||
s = bbextents;
|
||||
else if (s < 0)
|
||||
s = 0;
|
||||
|
||||
t = (int)(tdivz * z) + tadjust;
|
||||
if (t > bbextentt)
|
||||
t = bbextentt;
|
||||
else if (t < 0)
|
||||
t = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// calculate s and t at the far end of the span
|
||||
if (count >= 8)
|
||||
spancount = 8;
|
||||
else
|
||||
spancount = count;
|
||||
|
||||
count -= spancount;
|
||||
|
||||
if (count)
|
||||
{
|
||||
// calculate s/z, t/z, zi->fixed s and t at far end of span,
|
||||
// calculate s and t steps across span by shifting
|
||||
sdivz += sdivz8stepu;
|
||||
tdivz += tdivz8stepu;
|
||||
zi += zi8stepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 8)
|
||||
snext = 8; // prevent round-off error on <0 steps from
|
||||
// from causing overstepping & running off the
|
||||
// edge of the texture
|
||||
|
||||
tnext = (int)(tdivz * z) + tadjust;
|
||||
if (tnext > bbextentt)
|
||||
tnext = bbextentt;
|
||||
else if (tnext < 8)
|
||||
tnext = 8; // guard against round-off error on <0 steps
|
||||
|
||||
sstep = (snext - s) >> 3;
|
||||
tstep = (tnext - t) >> 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
|
||||
// can't step off polygon), clamp, calculate s and t steps across
|
||||
// span by division, biasing steps low so we don't run off the
|
||||
// texture
|
||||
spancountminus1 = (float)(spancount - 1);
|
||||
sdivz += d_sdivzstepu * spancountminus1;
|
||||
tdivz += d_tdivzstepu * spancountminus1;
|
||||
zi += d_zistepu * spancountminus1;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 8)
|
||||
snext = 8; // prevent round-off error on <0 steps from
|
||||
// from causing overstepping & running off the
|
||||
// edge of the texture
|
||||
|
||||
tnext = (int)(tdivz * z) + tadjust;
|
||||
if (tnext > bbextentt)
|
||||
tnext = bbextentt;
|
||||
else if (tnext < 8)
|
||||
tnext = 8; // guard against round-off error on <0 steps
|
||||
|
||||
if (spancount > 1)
|
||||
{
|
||||
sstep = (snext - s) / (spancount - 1);
|
||||
tstep = (tnext - t) / (spancount - 1);
|
||||
}
|
||||
}
|
||||
do
|
||||
{
|
||||
itemp = *(pbase + ((s >> 16) + (t >> 16) * cachewidth));
|
||||
if ((alpha = itemp>>24))
|
||||
{
|
||||
alpha = 128;
|
||||
if (*pz <= (izi >> 16))
|
||||
{
|
||||
*pz = izi >> 16;
|
||||
|
||||
pbtemp = (qbyte *)&itemp;
|
||||
pbdest = (qbyte *)pdest;
|
||||
pbdest[0] = (pbdest[0]*(255-alpha) + pbtemp[0]*alpha)/255;
|
||||
pbdest[1] = (pbdest[1]*(255-alpha) + pbtemp[1]*alpha)/255;
|
||||
pbdest[2] = (pbdest[2]*(255-alpha) + pbtemp[2]*alpha)/255;
|
||||
}
|
||||
}
|
||||
|
||||
izi += izistep;
|
||||
pdest++;
|
||||
pz++;
|
||||
s += sstep;
|
||||
t += tstep;
|
||||
} while (--spancount > 0);
|
||||
|
||||
s = snext;
|
||||
t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
NextSpan:
|
||||
pspan++;
|
||||
|
||||
} while (pspan->count != DS_SPAN_LIST_END);
|
||||
}
|
||||
|
||||
#ifdef PEXT_TRANS
|
||||
void D_SpriteDrawSpansTrans (sspan_t *pspan)
|
||||
{
|
||||
int count, spancount, izistep;
|
||||
int izi;
|
||||
qbyte *pbase, *pdest;
|
||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
||||
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
||||
qbyte btemp;
|
||||
short *pz;
|
||||
|
||||
sstep = 0; // keep compiler happy
|
||||
tstep = 0; // ditto
|
||||
|
||||
pbase = cacheblock;
|
||||
|
||||
sdivz8stepu = d_sdivzstepu * 8;
|
||||
tdivz8stepu = d_tdivzstepu * 8;
|
||||
zi8stepu = d_zistepu * 8;
|
||||
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
|
||||
|
||||
do
|
||||
{
|
||||
pdest = (qbyte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
|
||||
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
if (count <= 0)
|
||||
goto NextSpan;
|
||||
|
||||
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
|
||||
du = (float)pspan->u;
|
||||
dv = (float)pspan->v;
|
||||
|
||||
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
|
||||
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
|
||||
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izi = (int)(zi * 0x8000 * 0x10000);
|
||||
|
||||
s = (int)(sdivz * z) + sadjust;
|
||||
if (s > bbextents)
|
||||
s = bbextents;
|
||||
else if (s < 0)
|
||||
s = 0;
|
||||
|
||||
t = (int)(tdivz * z) + tadjust;
|
||||
if (t > bbextentt)
|
||||
t = bbextentt;
|
||||
else if (t < 0)
|
||||
t = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// calculate s and t at the far end of the span
|
||||
if (count >= 8)
|
||||
spancount = 8;
|
||||
else
|
||||
spancount = count;
|
||||
|
||||
count -= spancount;
|
||||
|
||||
if (count)
|
||||
{
|
||||
// calculate s/z, t/z, zi->fixed s and t at far end of span,
|
||||
// calculate s and t steps across span by shifting
|
||||
sdivz += sdivz8stepu;
|
||||
tdivz += tdivz8stepu;
|
||||
zi += zi8stepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 8)
|
||||
snext = 8; // prevent round-off error on <0 steps from
|
||||
// from causing overstepping & running off the
|
||||
// edge of the texture
|
||||
|
||||
tnext = (int)(tdivz * z) + tadjust;
|
||||
if (tnext > bbextentt)
|
||||
tnext = bbextentt;
|
||||
else if (tnext < 8)
|
||||
tnext = 8; // guard against round-off error on <0 steps
|
||||
|
||||
sstep = (snext - s) >> 3;
|
||||
tstep = (tnext - t) >> 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
|
||||
// can't step off polygon), clamp, calculate s and t steps across
|
||||
// span by division, biasing steps low so we don't run off the
|
||||
// texture
|
||||
spancountminus1 = (float)(spancount - 1);
|
||||
sdivz += d_sdivzstepu * spancountminus1;
|
||||
tdivz += d_tdivzstepu * spancountminus1;
|
||||
zi += d_zistepu * spancountminus1;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 8)
|
||||
snext = 8; // prevent round-off error on <0 steps from
|
||||
// from causing overstepping & running off the
|
||||
// edge of the texture
|
||||
|
||||
tnext = (int)(tdivz * z) + tadjust;
|
||||
if (tnext > bbextentt)
|
||||
tnext = bbextentt;
|
||||
else if (tnext < 8)
|
||||
tnext = 8; // guard against round-off error on <0 steps
|
||||
|
||||
if (spancount > 1)
|
||||
{
|
||||
sstep = (snext - s) / (spancount - 1);
|
||||
tstep = (tnext - t) / (spancount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
|
||||
if (btemp != 255)
|
||||
{
|
||||
if (*pz <= (izi >> 16))
|
||||
{
|
||||
*pz = izi >> 16;
|
||||
*pdest = Trans(*pdest, btemp);
|
||||
}
|
||||
}
|
||||
|
||||
izi += izistep;
|
||||
pdest++;
|
||||
pz++;
|
||||
s += sstep;
|
||||
t += tstep;
|
||||
} while (--spancount > 0);
|
||||
|
||||
s = snext;
|
||||
t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
NextSpan:
|
||||
pspan++;
|
||||
|
||||
} while (pspan->count != DS_SPAN_LIST_END);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=====================
|
||||
D_SpriteScanLeftEdge
|
||||
=====================
|
||||
*/
|
||||
void D_SpriteScanLeftEdge (void)
|
||||
{
|
||||
int i, v, itop, ibottom, lmaxindex;
|
||||
emitpoint_t *pvert, *pnext;
|
||||
sspan_t *pspan;
|
||||
float du, dv, vtop, vbottom, slope;
|
||||
fixed16_t u, u_step;
|
||||
|
||||
pspan = sprite_spans;
|
||||
i = minindex;
|
||||
if (i == 0)
|
||||
i = r_spritedesc.nump;
|
||||
|
||||
lmaxindex = maxindex;
|
||||
if (lmaxindex == 0)
|
||||
lmaxindex = r_spritedesc.nump;
|
||||
|
||||
vtop = ceil (r_spritedesc.pverts[i].v);
|
||||
|
||||
do
|
||||
{
|
||||
pvert = &r_spritedesc.pverts[i];
|
||||
pnext = pvert - 1;
|
||||
|
||||
vbottom = ceil (pnext->v);
|
||||
|
||||
if (vtop < vbottom)
|
||||
{
|
||||
du = pnext->u - pvert->u;
|
||||
dv = pnext->v - pvert->v;
|
||||
slope = du / dv;
|
||||
u_step = (int)(slope * 0x10000);
|
||||
// adjust u to ceil the integer portion
|
||||
u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
|
||||
(0x10000 - 1);
|
||||
itop = (int)vtop;
|
||||
ibottom = (int)vbottom;
|
||||
|
||||
for (v=itop ; v<ibottom ; v++)
|
||||
{
|
||||
pspan->u = u >> 16;
|
||||
pspan->v = v;
|
||||
u += u_step;
|
||||
pspan++;
|
||||
}
|
||||
}
|
||||
|
||||
vtop = vbottom;
|
||||
|
||||
i--;
|
||||
if (i == 0)
|
||||
i = r_spritedesc.nump;
|
||||
|
||||
} while (i != lmaxindex);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
D_SpriteScanRightEdge
|
||||
=====================
|
||||
*/
|
||||
void D_SpriteScanRightEdge (void)
|
||||
{
|
||||
int i, v, itop, ibottom;
|
||||
emitpoint_t *pvert, *pnext;
|
||||
sspan_t *pspan;
|
||||
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
|
||||
fixed16_t u, u_step;
|
||||
|
||||
pspan = sprite_spans;
|
||||
i = minindex;
|
||||
|
||||
vvert = r_spritedesc.pverts[i].v;
|
||||
if (vvert < r_refdef.fvrecty_adj)
|
||||
vvert = r_refdef.fvrecty_adj;
|
||||
if (vvert > r_refdef.fvrectbottom_adj)
|
||||
vvert = r_refdef.fvrectbottom_adj;
|
||||
|
||||
vtop = ceil (vvert);
|
||||
|
||||
do
|
||||
{
|
||||
pvert = &r_spritedesc.pverts[i];
|
||||
pnext = pvert + 1;
|
||||
|
||||
vnext = pnext->v;
|
||||
if (vnext < r_refdef.fvrecty_adj)
|
||||
vnext = r_refdef.fvrecty_adj;
|
||||
if (vnext > r_refdef.fvrectbottom_adj)
|
||||
vnext = r_refdef.fvrectbottom_adj;
|
||||
|
||||
vbottom = ceil (vnext);
|
||||
|
||||
if (vtop < vbottom)
|
||||
{
|
||||
uvert = pvert->u;
|
||||
if (uvert < r_refdef.fvrectx_adj)
|
||||
uvert = r_refdef.fvrectx_adj;
|
||||
if (uvert > r_refdef.fvrectright_adj)
|
||||
uvert = r_refdef.fvrectright_adj;
|
||||
|
||||
unext = pnext->u;
|
||||
if (unext < r_refdef.fvrectx_adj)
|
||||
unext = r_refdef.fvrectx_adj;
|
||||
if (unext > r_refdef.fvrectright_adj)
|
||||
unext = r_refdef.fvrectright_adj;
|
||||
|
||||
du = unext - uvert;
|
||||
dv = vnext - vvert;
|
||||
slope = du / dv;
|
||||
u_step = (int)(slope * 0x10000);
|
||||
// adjust u to ceil the integer portion
|
||||
u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
|
||||
(0x10000 - 1);
|
||||
itop = (int)vtop;
|
||||
ibottom = (int)vbottom;
|
||||
|
||||
for (v=itop ; v<ibottom ; v++)
|
||||
{
|
||||
pspan->count = (u >> 16) - pspan->u;
|
||||
u += u_step;
|
||||
pspan++;
|
||||
}
|
||||
}
|
||||
|
||||
vtop = vbottom;
|
||||
vvert = vnext;
|
||||
|
||||
i++;
|
||||
if (i == r_spritedesc.nump)
|
||||
i = 0;
|
||||
|
||||
} while (i != maxindex);
|
||||
|
||||
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
D_SpriteCalculateGradients
|
||||
=====================
|
||||
*/
|
||||
void D_SpriteCalculateGradients (void)
|
||||
{
|
||||
vec3_t p_normal, p_saxis, p_taxis, p_temp1;
|
||||
float distinv;
|
||||
|
||||
TransformVector (r_spritedesc.vpn, p_normal);
|
||||
TransformVector (r_spritedesc.vright, p_saxis);
|
||||
TransformVector (r_spritedesc.vup, p_taxis);
|
||||
VectorInverse (p_taxis);
|
||||
|
||||
distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
|
||||
|
||||
d_sdivzstepu = p_saxis[0] * xscaleinv;
|
||||
d_tdivzstepu = p_taxis[0] * xscaleinv;
|
||||
|
||||
d_sdivzstepv = -p_saxis[1] * yscaleinv;
|
||||
d_tdivzstepv = -p_taxis[1] * yscaleinv;
|
||||
|
||||
d_zistepu = p_normal[0] * xscaleinv * distinv;
|
||||
d_zistepv = -p_normal[1] * yscaleinv * distinv;
|
||||
|
||||
d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
|
||||
ycenter * d_sdivzstepv;
|
||||
d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
|
||||
ycenter * d_tdivzstepv;
|
||||
d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
|
||||
ycenter * d_zistepv;
|
||||
|
||||
TransformVector (modelorg, p_temp1);
|
||||
|
||||
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
|
||||
(-(cachewidth >> 1) << 16);
|
||||
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
|
||||
(-(sprite_height >> 1) << 16);
|
||||
|
||||
// -1 (-epsilon) so we never wander off the edge of the texture
|
||||
bbextents = (cachewidth << 16) - 1;
|
||||
bbextentt = (sprite_height << 16) - 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
D_DrawSprite
|
||||
=====================
|
||||
*/
|
||||
void D_DrawSprite (void)
|
||||
{
|
||||
int i, nump;
|
||||
float ymin, ymax;
|
||||
emitpoint_t *pverts;
|
||||
sspan_t spans[MAXHEIGHT+1];
|
||||
|
||||
sprite_spans = spans;
|
||||
|
||||
// find the top and bottom vertices, and make sure there's at least one scan to
|
||||
// draw
|
||||
ymin = 999999.9;
|
||||
ymax = -999999.9;
|
||||
pverts = r_spritedesc.pverts;
|
||||
|
||||
for (i=0 ; i<r_spritedesc.nump ; i++)
|
||||
{
|
||||
if (pverts->v < ymin)
|
||||
{
|
||||
ymin = pverts->v;
|
||||
minindex = i;
|
||||
}
|
||||
|
||||
if (pverts->v > ymax)
|
||||
{
|
||||
ymax = pverts->v;
|
||||
maxindex = i;
|
||||
}
|
||||
|
||||
pverts++;
|
||||
}
|
||||
|
||||
ymin = ceil (ymin);
|
||||
ymax = ceil (ymax);
|
||||
|
||||
if (ymin >= ymax)
|
||||
return; // doesn't cross any scans at all
|
||||
|
||||
cachewidth = r_spritedesc.pspriteframe->width;
|
||||
sprite_height = r_spritedesc.pspriteframe->height;
|
||||
cacheblock = (qbyte *)&r_spritedesc.pspriteframe->pixels[0];
|
||||
|
||||
// copy the first vertex to the last vertex, so we don't have to deal with
|
||||
// wrapping
|
||||
nump = r_spritedesc.nump;
|
||||
pverts = r_spritedesc.pverts;
|
||||
pverts[nump] = pverts[0];
|
||||
|
||||
D_SpriteCalculateGradients ();
|
||||
D_SpriteScanLeftEdge ();
|
||||
D_SpriteScanRightEdge ();
|
||||
#ifndef PEXT_TRANS
|
||||
D_SpriteDrawSpans (sprite_spans);
|
||||
#else
|
||||
if (r_pixbytes == 4)
|
||||
D_SpriteDrawSpans32 (sprite_spans);
|
||||
else if (r_pixbytes == 2)
|
||||
D_SpriteDrawSpans16 (sprite_spans);
|
||||
else //1
|
||||
{
|
||||
if (currententity->alpha>=0.9)
|
||||
D_SpriteDrawSpans (sprite_spans);
|
||||
else
|
||||
{
|
||||
Set_TransLevelF(currententity->alpha);
|
||||
D_SpriteDrawSpansTrans (sprite_spans);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
351
engine/sw/d_surf.c
Normal file
351
engine/sw/d_surf.c
Normal file
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_surf.c: rasterization driver surface heap manager
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "d_local.h"
|
||||
#include "r_local.h"
|
||||
|
||||
float surfscale;
|
||||
qboolean r_cache_thrash; // set if surface cache is thrashing
|
||||
|
||||
int r_flushcache;
|
||||
|
||||
int sc_size;
|
||||
surfcache_t *sc_rover, *sc_base;
|
||||
|
||||
#define GUARDSIZE 4
|
||||
|
||||
|
||||
int D_SurfaceCacheForRes (int width, int height, int bpp)
|
||||
{
|
||||
int size, pix;
|
||||
|
||||
if (COM_CheckParm ("-surfcachesize"))
|
||||
{
|
||||
size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
|
||||
return size;
|
||||
}
|
||||
|
||||
size = 4096*1024;//SURFCACHE_SIZE_AT_320X200;
|
||||
|
||||
pix = width*height;
|
||||
if (pix > 64000)
|
||||
size += (pix-64000)*4;
|
||||
|
||||
if (bpp)
|
||||
return size*bpp;
|
||||
return size;
|
||||
}
|
||||
|
||||
void D_CheckCacheGuard (void)
|
||||
{
|
||||
qbyte *s;
|
||||
int i;
|
||||
|
||||
s = (qbyte *)sc_base + sc_size;
|
||||
for (i=0 ; i<GUARDSIZE ; i++)
|
||||
if (s[i] != (qbyte)i)
|
||||
Sys_Error ("D_CheckCacheGuard: failed");
|
||||
}
|
||||
|
||||
void D_ClearCacheGuard (void)
|
||||
{
|
||||
qbyte *s;
|
||||
int i;
|
||||
|
||||
s = (qbyte *)sc_base + sc_size;
|
||||
for (i=0 ; i<GUARDSIZE ; i++)
|
||||
s[i] = (qbyte)i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
D_InitCaches
|
||||
|
||||
================
|
||||
*/
|
||||
void D_InitCaches (void *buffer, int size)
|
||||
{
|
||||
// if (!msg_suppress_1)
|
||||
// Con_Printf ("%ik surface cache\n", size/1024);
|
||||
|
||||
sc_size = size - GUARDSIZE;
|
||||
sc_base = (surfcache_t *)buffer;
|
||||
sc_rover = sc_base;
|
||||
|
||||
sc_base->next = NULL;
|
||||
sc_base->owner = NULL;
|
||||
sc_base->size = sc_size;
|
||||
|
||||
D_ClearCacheGuard ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
D_FlushCaches
|
||||
==================
|
||||
*/
|
||||
void D_FlushCaches (void)
|
||||
{
|
||||
surfcache_t *c;
|
||||
|
||||
if (!sc_base)
|
||||
return;
|
||||
|
||||
for (c = sc_base ; c ; c = c->next)
|
||||
{
|
||||
if (c->owner)
|
||||
*c->owner = NULL;
|
||||
}
|
||||
|
||||
sc_rover = sc_base;
|
||||
sc_base->next = NULL;
|
||||
sc_base->owner = NULL;
|
||||
sc_base->size = sc_size;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
D_SCAlloc
|
||||
=================
|
||||
*/
|
||||
surfcache_t *D_SCAlloc (int width, int bpp, int size)
|
||||
{
|
||||
surfcache_t *new;
|
||||
qboolean wrapped_this_time;
|
||||
|
||||
// if ((width < 0) || (width > 256))
|
||||
// Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
|
||||
|
||||
// if ((size <= 0) || (size > 0x10000*bpp))
|
||||
// Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
|
||||
|
||||
#ifdef __alpha__
|
||||
size = (int)((long)&((surfcache_t *)0)->data[size]);
|
||||
#else
|
||||
size = (int)&((surfcache_t *)0)->data[size];
|
||||
#endif
|
||||
size = (size + 3) & ~3;
|
||||
if (size > sc_size)
|
||||
Sys_Error ("D_SCAlloc: %i > cache size",size);
|
||||
|
||||
// if there is not size bytes after the rover, reset to the start
|
||||
wrapped_this_time = false;
|
||||
|
||||
if ( !sc_rover || (qbyte *)sc_rover - (qbyte *)sc_base > sc_size - size)
|
||||
{
|
||||
if (sc_rover)
|
||||
{
|
||||
wrapped_this_time = true;
|
||||
}
|
||||
sc_rover = sc_base;
|
||||
}
|
||||
|
||||
// colect and free surfcache_t blocks until the rover block is large enough
|
||||
new = sc_rover;
|
||||
if (sc_rover->owner)
|
||||
*sc_rover->owner = NULL;
|
||||
|
||||
while (new->size < size)
|
||||
{
|
||||
// free another
|
||||
sc_rover = sc_rover->next;
|
||||
if (!sc_rover)
|
||||
Sys_Error ("D_SCAlloc: hit the end of memory");
|
||||
if (sc_rover->owner)
|
||||
*sc_rover->owner = NULL;
|
||||
|
||||
new->size += sc_rover->size;
|
||||
new->next = sc_rover->next;
|
||||
}
|
||||
|
||||
// create a fragment out of any leftovers
|
||||
if (new->size - size > 256)
|
||||
{
|
||||
sc_rover = (surfcache_t *)( (qbyte *)new + size);
|
||||
sc_rover->size = new->size - size;
|
||||
sc_rover->next = new->next;
|
||||
sc_rover->width = 0;
|
||||
sc_rover->owner = NULL;
|
||||
new->next = sc_rover;
|
||||
new->size = size;
|
||||
}
|
||||
else
|
||||
sc_rover = new->next;
|
||||
|
||||
new->width = width;
|
||||
// DEBUG
|
||||
if (width > 0)
|
||||
new->height = (size - sizeof(*new) + sizeof(new->data)) / (width*bpp);
|
||||
|
||||
new->bytesperpix = bpp;
|
||||
|
||||
new->owner = NULL; // should be set properly after return
|
||||
|
||||
if (d_roverwrapped)
|
||||
{
|
||||
if (wrapped_this_time || (sc_rover >= d_initial_rover))
|
||||
r_cache_thrash = true;
|
||||
}
|
||||
else if (wrapped_this_time)
|
||||
{
|
||||
d_roverwrapped = true;
|
||||
}
|
||||
|
||||
D_CheckCacheGuard (); // DEBUG
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
D_SCDump
|
||||
=================
|
||||
*/
|
||||
void D_SCDump (void)
|
||||
{
|
||||
surfcache_t *test;
|
||||
|
||||
for (test = sc_base ; test ; test = test->next)
|
||||
{
|
||||
if (test == sc_rover)
|
||||
Sys_Printf ("ROVER:\n");
|
||||
Sys_Printf ("%p : %i bytes %i width\n",test, test->size, test->width);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// if the num is not a power of 2, assume it will not repeat
|
||||
|
||||
int MaskForNum (int num)
|
||||
{
|
||||
if (num==128)
|
||||
return 127;
|
||||
if (num==64)
|
||||
return 63;
|
||||
if (num==32)
|
||||
return 31;
|
||||
if (num==16)
|
||||
return 15;
|
||||
return 255;
|
||||
}
|
||||
|
||||
int D_log2 (int num)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = 0;
|
||||
|
||||
while (num>>=1)
|
||||
c++;
|
||||
return c;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
D_CacheSurface
|
||||
================
|
||||
*/
|
||||
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
|
||||
{
|
||||
surfcache_t *cache;
|
||||
int bpp;
|
||||
|
||||
//
|
||||
// if the surface is animating or flashing, flush the cache
|
||||
//
|
||||
r_drawsurf.texture = SWR_TextureAnimation (surface->texinfo->texture);
|
||||
r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
|
||||
r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
|
||||
r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
|
||||
r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
|
||||
|
||||
//
|
||||
// see if the cache holds apropriate data
|
||||
//
|
||||
cache = surface->cachespots[miplevel];
|
||||
|
||||
if (cache && !cache->dlight && surface->dlightframe != r_framecount
|
||||
&& cache->texture == r_drawsurf.texture && cache->fcache == r_flushcache //extra part added to flush caches over a group of frames on palette change...
|
||||
&& cache->lightadj[0] == r_drawsurf.lightadj[0]
|
||||
&& cache->lightadj[1] == r_drawsurf.lightadj[1]
|
||||
&& cache->lightadj[2] == r_drawsurf.lightadj[2]
|
||||
&& cache->lightadj[3] == r_drawsurf.lightadj[3] )
|
||||
return cache;
|
||||
|
||||
//
|
||||
// determine shape of surface
|
||||
//
|
||||
surfscale = 1.0 / (1<<miplevel);
|
||||
|
||||
r_drawsurf.surfmip = miplevel;
|
||||
r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
|
||||
r_drawsurf.rowbytes = r_drawsurf.surfwidth;
|
||||
r_drawsurf.surfheight = surface->extents[1] >> miplevel;
|
||||
|
||||
bpp = r_pixbytes;
|
||||
//
|
||||
// allocate memory if needed
|
||||
//
|
||||
if (!cache) // if a texture just animated, don't reallocate it
|
||||
{
|
||||
cache = D_SCAlloc (r_drawsurf.surfwidth, bpp,
|
||||
r_drawsurf.surfwidth * r_drawsurf.surfheight * bpp);
|
||||
surface->cachespots[miplevel] = cache;
|
||||
cache->owner = &surface->cachespots[miplevel];
|
||||
cache->mipscale = surfscale;
|
||||
}
|
||||
|
||||
if (surface->dlightframe == r_framecount)
|
||||
cache->dlight = 1;
|
||||
else
|
||||
cache->dlight = 0;
|
||||
|
||||
cache->fcache = r_flushcache;
|
||||
|
||||
r_drawsurf.surfdat = (pixel_t *)cache->data;
|
||||
|
||||
cache->texture = r_drawsurf.texture;
|
||||
cache->lightadj[0] = r_drawsurf.lightadj[0];
|
||||
cache->lightadj[1] = r_drawsurf.lightadj[1];
|
||||
cache->lightadj[2] = r_drawsurf.lightadj[2];
|
||||
cache->lightadj[3] = r_drawsurf.lightadj[3];
|
||||
|
||||
//
|
||||
// draw and light the surface texture
|
||||
//
|
||||
r_drawsurf.surf = surface;
|
||||
|
||||
c_surf++;
|
||||
if (cache->bytesperpix==4 && r_usinglits)
|
||||
R_DrawSurface32 ();
|
||||
else
|
||||
R_DrawSurface ();
|
||||
|
||||
return surface->cachespots[miplevel];
|
||||
}
|
||||
|
||||
|
180
engine/sw/d_trans.c
Normal file
180
engine/sw/d_trans.c
Normal file
|
@ -0,0 +1,180 @@
|
|||
#include "quakedef.h"
|
||||
#include "d_local.h"
|
||||
#include "r_local.h"
|
||||
|
||||
#ifdef PEXT_TRANS
|
||||
int t_numtables;
|
||||
|
||||
qbyte p1multitable[] = {1, 99, 49, 97, 48, 19, 47, 93, 23, 91, 9, 89, 22, 87, 43, 17, 21, 83, 41, 81, 4, 79, 39, 77, 19, 3, 37, 73, 18, 71, 7, 69, 17, 67, 33, 13, 16, 63, 31, 61, 3, 59, 29, 57, 14, 11, 27, 53, 13, 51, 1, 49, 12, 47, 23, 9, 11, 43, 21, 41, 2, 39, 19, 37, 9, 7, 17, 33, 8, 31, 3, 29, 7, 27, 13, 1, 6, 23, 11, 21, 1, 19, 9, 17, 4, 3, 7, 13, 3, 11, 1, 9, 2, 7, 3, 1, 1, 3, 1, 1, 0};
|
||||
qbyte p2multitable[] = {0, 1, 1, 3, 2, 1, 3, 7, 2, 9, 1, 11, 3, 13, 7, 3, 4, 17, 9, 19, 1, 21, 11, 23, 6, 1, 13, 27, 7, 29, 3, 31, 8, 33, 17, 7, 9, 37, 19, 39, 2, 41, 21, 43, 11, 9, 23, 47, 12, 49, 1, 51, 13, 53, 27, 11, 14, 57, 29, 59, 3, 61, 31, 63, 16, 13, 33, 67, 17, 69, 7, 71, 18, 73, 37, 3, 19, 77, 39, 79, 4, 81, 41, 83, 21, 17, 43, 87, 22, 89, 9, 91, 23, 93, 47, 19, 24, 97, 49, 99, 1};
|
||||
tlookup *t_lookup;
|
||||
tlookupp *t_curlookupp;
|
||||
int t_curtable;
|
||||
|
||||
int t_numtables;
|
||||
int t_numtablesinv;//numtables/65546
|
||||
|
||||
#define palette host_basepal
|
||||
#define _abs(x) ((x)*(x))
|
||||
|
||||
|
||||
void R_CalcTransTable(int table, int level)
|
||||
{
|
||||
FILE * f;
|
||||
int p;
|
||||
int p2;
|
||||
int r, g, b, j;
|
||||
int i;
|
||||
unsigned char *pa;
|
||||
int m;
|
||||
int dif, curdif;
|
||||
|
||||
qbyte p1multi;
|
||||
qbyte p2multi;
|
||||
qbyte pixdivide;
|
||||
|
||||
p1multi = p1multitable[level];
|
||||
p2multi = p2multitable[level];
|
||||
|
||||
pixdivide = p1multi + p2multi;
|
||||
|
||||
COM_FOpenFile (va("data/ttable%i.dat", (int) level) , &f); //we can ignore the filesize return value
|
||||
if (f)
|
||||
{
|
||||
if (fread (t_lookup[table], 256, 256, f) == 256)
|
||||
{
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
Con_Printf("Generating transtable %i%%\n", level);
|
||||
|
||||
for (p = 0; p < 256; p++)
|
||||
{
|
||||
j = p*3;
|
||||
for (p2 = 0; p2 < 256; p2++)
|
||||
{
|
||||
dif = 0x7fffffff;
|
||||
m=0;
|
||||
|
||||
i = p2*3;
|
||||
r = (palette[j+0] * p1multi + palette[i+0] * p2multi) / pixdivide;
|
||||
g = (palette[j+1] * p1multi + palette[i+1] * p2multi) / pixdivide;
|
||||
b = (palette[j+2] * p1multi + palette[i+2] * p2multi) / pixdivide;
|
||||
for (i = 0,pa=palette; i < 256-16; i++,pa+=3)
|
||||
{
|
||||
curdif = _abs(r - pa[0]) + _abs(g - pa[1]) + _abs(b - pa[2]);
|
||||
if (curdif <= 0) //force 0
|
||||
{
|
||||
m = i;
|
||||
break;
|
||||
}
|
||||
if (curdif < dif)
|
||||
{
|
||||
dif = curdif;
|
||||
m = i;
|
||||
}
|
||||
}
|
||||
(t_lookup[table])[p][p2] = m;
|
||||
}
|
||||
}
|
||||
|
||||
COM_CreatePath(va("%s/data/", com_gamedir));
|
||||
#if 1
|
||||
f = fopen (va("%s/data/ttable%i.dat", com_gamedir, (int) level), "wb");
|
||||
if (f)
|
||||
{
|
||||
if (fwrite (t_lookup[table], 256, 256, f) != 256)
|
||||
{
|
||||
Con_Printf("Couldn't write data to \"data/ttable%i.dat\"\n", (int) level);
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
Con_Printf("Couldn't write data to \"data/ttable%i.dat\"\n", (int) level);
|
||||
#else
|
||||
COM_WriteFile(va("data/ttable%i.dat", (int)level, t_lookup[table], 256*256);
|
||||
#endif
|
||||
}
|
||||
|
||||
void D_InitTrans(void)
|
||||
{
|
||||
int i;
|
||||
int table;
|
||||
|
||||
if (t_lookup)
|
||||
BZ_Free(t_lookup);
|
||||
//no trans palette yet..
|
||||
Con_SafePrintf("Making/loading transparency lookup tables\nPlease wait...\n");
|
||||
|
||||
MakeVideoPalette();
|
||||
|
||||
if ((i = COM_CheckParm("-ttables")) != 0)
|
||||
{
|
||||
t_numtables = Q_atoi(com_argv[i+1]);
|
||||
if (t_numtables < 1)
|
||||
t_numtables = 1;
|
||||
}
|
||||
else
|
||||
t_numtables = 5;
|
||||
|
||||
t_numtablesinv = ((float)65536/t_numtables)+1;//65546/numtables
|
||||
|
||||
t_curtable=0;
|
||||
//t_lookup = Hunk_AllocName(sizeof(tlookup)*t_numtables, "Transtables");
|
||||
t_lookup = BZ_Malloc(sizeof(tlookup)*t_numtables);
|
||||
t_curlookupp = t_lookup[t_curtable];
|
||||
|
||||
if (t_numtables == 1)
|
||||
R_CalcTransTable(0, 50);
|
||||
else if (t_numtables == 2)
|
||||
{
|
||||
R_CalcTransTable(0, 50);
|
||||
R_CalcTransTable(1, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (table = 0; table < t_numtables; table++)
|
||||
R_CalcTransTable(table, 100/((float)(t_numtables-1)/table));
|
||||
}
|
||||
Con_Printf("Done\n");
|
||||
}
|
||||
|
||||
#ifndef Trans
|
||||
byte _fastcall Trans(byte p, byte p2)
|
||||
{
|
||||
return t_curlookupp[p][p2];
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void Set_TransLevelI(int level)
|
||||
{
|
||||
/*
|
||||
0 =0
|
||||
12.5 =1
|
||||
25 =2
|
||||
37.5 =3
|
||||
50 =4
|
||||
62.5 =5
|
||||
75 =6
|
||||
87.5 =7
|
||||
100 =8
|
||||
*/
|
||||
t_curtable = level/(100.0f/(t_numtables-1));
|
||||
t_curlookupp = t_lookup[t_curtable];
|
||||
}
|
||||
void Set_TransLevelF(float level) //MUST be between 0 and 1
|
||||
{
|
||||
// level+=1.0/(NUMTABLES-1);
|
||||
if (level>1)
|
||||
level = 1;
|
||||
t_curtable = level*(t_numtables-1);
|
||||
t_curlookupp = t_lookup[t_curtable];
|
||||
}
|
||||
|
||||
#endif
|
51
engine/sw/d_vars.c
Normal file
51
engine/sw/d_vars.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
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
|
||||
|
||||
#if !id386
|
||||
|
||||
#include "quakedef.h"
|
||||
|
||||
// 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
|
||||
|
||||
float d_sdivzstepu, d_tdivzstepu, d_zistepu;
|
||||
float d_sdivzstepv, d_tdivzstepv, d_zistepv;
|
||||
float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
|
||||
|
||||
fixed16_t sadjust, tadjust, bbextents, bbextentt;
|
||||
|
||||
pixel_t *cacheblock;
|
||||
int cachewidth;
|
||||
int cacheheight;
|
||||
pixel_t *d_viewbuffer;
|
||||
short *d_pzbuffer;
|
||||
unsigned int d_zrowbytes;
|
||||
unsigned int d_zwidth;
|
||||
|
||||
#endif // !id386
|
||||
|
213
engine/sw/d_varsa.s
Normal file
213
engine/sw/d_varsa.s
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
//
|
||||
// d_varsa.s
|
||||
//
|
||||
|
||||
#include "asm_i386.h"
|
||||
#include "quakeasm.h"
|
||||
#include "asm_draw.h"
|
||||
#include "d_ifacea.h"
|
||||
|
||||
#if id386
|
||||
|
||||
.data
|
||||
|
||||
//-------------------------------------------------------
|
||||
// global refresh variables
|
||||
//-------------------------------------------------------
|
||||
|
||||
// FIXME: put all refresh variables into one contiguous block. Make into one
|
||||
// big structure, like cl or sv?
|
||||
|
||||
.align 4
|
||||
.globl C(d_sdivzstepu)
|
||||
.globl C(d_tdivzstepu)
|
||||
.globl C(d_zistepu)
|
||||
.globl C(d_sdivzstepv)
|
||||
.globl C(d_tdivzstepv)
|
||||
.globl C(d_zistepv)
|
||||
.globl C(d_sdivzorigin)
|
||||
.globl C(d_tdivzorigin)
|
||||
.globl C(d_ziorigin)
|
||||
C(d_sdivzstepu): .single 0
|
||||
C(d_tdivzstepu): .single 0
|
||||
C(d_zistepu): .single 0
|
||||
C(d_sdivzstepv): .single 0
|
||||
C(d_tdivzstepv): .single 0
|
||||
C(d_zistepv): .single 0
|
||||
C(d_sdivzorigin): .single 0
|
||||
C(d_tdivzorigin): .single 0
|
||||
C(d_ziorigin): .single 0
|
||||
|
||||
.globl C(sadjust)
|
||||
.globl C(tadjust)
|
||||
.globl C(bbextents)
|
||||
.globl C(bbextentt)
|
||||
C(sadjust): .long 0
|
||||
C(tadjust): .long 0
|
||||
C(bbextents): .long 0
|
||||
C(bbextentt): .long 0
|
||||
|
||||
.globl C(cacheblock)
|
||||
.globl C(d_viewbuffer)
|
||||
.globl C(cachewidth)
|
||||
.globl C(d_pzbuffer)
|
||||
.globl C(d_zrowbytes)
|
||||
.globl C(d_zwidth)
|
||||
C(cacheblock): .long 0
|
||||
C(cachewidth): .long 0
|
||||
C(d_viewbuffer): .long 0
|
||||
C(d_pzbuffer): .long 0
|
||||
C(d_zrowbytes): .long 0
|
||||
C(d_zwidth): .long 0
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// ASM-only variables
|
||||
//-------------------------------------------------------
|
||||
.globl izi
|
||||
izi: .long 0
|
||||
|
||||
.globl pbase, s, t, sfracf, tfracf, snext, tnext
|
||||
.globl spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu
|
||||
.globl zi8stepu, sdivz8stepu, tdivz8stepu, pz
|
||||
s: .long 0
|
||||
t: .long 0
|
||||
snext: .long 0
|
||||
tnext: .long 0
|
||||
sfracf: .long 0
|
||||
tfracf: .long 0
|
||||
pbase: .long 0
|
||||
zi8stepu: .long 0
|
||||
sdivz8stepu: .long 0
|
||||
tdivz8stepu: .long 0
|
||||
zi16stepu: .long 0
|
||||
sdivz16stepu: .long 0
|
||||
tdivz16stepu: .long 0
|
||||
spancountminus1: .long 0
|
||||
pz: .long 0
|
||||
|
||||
.globl izistep
|
||||
izistep: .long 0
|
||||
|
||||
//-------------------------------------------------------
|
||||
// local variables for d_draw16.s
|
||||
//-------------------------------------------------------
|
||||
|
||||
.globl reciprocal_table_16, entryvec_table_16
|
||||
// 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13,
|
||||
// 1/14, and 1/15 in 0.32 form
|
||||
reciprocal_table_16: .long 0x40000000, 0x2aaaaaaa, 0x20000000
|
||||
.long 0x19999999, 0x15555555, 0x12492492
|
||||
.long 0x10000000, 0xe38e38e, 0xccccccc, 0xba2e8ba
|
||||
.long 0xaaaaaaa, 0x9d89d89, 0x9249249, 0x8888888
|
||||
|
||||
#ifndef NeXT
|
||||
.extern Entry2_16
|
||||
.extern Entry3_16
|
||||
.extern Entry4_16
|
||||
.extern Entry5_16
|
||||
.extern Entry6_16
|
||||
.extern Entry7_16
|
||||
.extern Entry8_16
|
||||
.extern Entry9_16
|
||||
.extern Entry10_16
|
||||
.extern Entry11_16
|
||||
.extern Entry12_16
|
||||
.extern Entry13_16
|
||||
.extern Entry14_16
|
||||
.extern Entry15_16
|
||||
.extern Entry16_16
|
||||
#endif
|
||||
|
||||
entryvec_table_16: .long 0, Entry2_16, Entry3_16, Entry4_16
|
||||
.long Entry5_16, Entry6_16, Entry7_16, Entry8_16
|
||||
.long Entry9_16, Entry10_16, Entry11_16, Entry12_16
|
||||
.long Entry13_16, Entry14_16, Entry15_16, Entry16_16
|
||||
|
||||
//-------------------------------------------------------
|
||||
// local variables for d_parta.s
|
||||
//-------------------------------------------------------
|
||||
.globl DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix, DP_EntryTable
|
||||
DP_Count: .long 0
|
||||
DP_u: .long 0
|
||||
DP_v: .long 0
|
||||
DP_32768: .single 32768.0
|
||||
DP_Color: .long 0
|
||||
DP_Pix: .long 0
|
||||
|
||||
|
||||
#ifndef NeXT
|
||||
.extern DP_1x1
|
||||
.extern DP_2x2
|
||||
.extern DP_3x3
|
||||
.extern DP_4x4
|
||||
#endif
|
||||
|
||||
DP_EntryTable: .long DP_1x1, DP_2x2, DP_3x3, DP_4x4
|
||||
|
||||
//
|
||||
// advancetable is 8 bytes, but points to the middle of that range so negative
|
||||
// offsets will work
|
||||
//
|
||||
.globl advancetable, sstep, tstep, pspantemp, counttemp, jumptemp
|
||||
advancetable: .long 0, 0
|
||||
sstep: .long 0
|
||||
tstep: .long 0
|
||||
|
||||
pspantemp: .long 0
|
||||
counttemp: .long 0
|
||||
jumptemp: .long 0
|
||||
|
||||
// 1/2, 1/3, 1/4, 1/5, 1/6, and 1/7 in 0.32 form
|
||||
.globl reciprocal_table, entryvec_table
|
||||
reciprocal_table: .long 0x40000000, 0x2aaaaaaa, 0x20000000
|
||||
.long 0x19999999, 0x15555555, 0x12492492
|
||||
|
||||
#ifndef NeXT
|
||||
.extern Entry2_8
|
||||
.extern Entry3_8
|
||||
.extern Entry4_8
|
||||
.extern Entry5_8
|
||||
.extern Entry6_8
|
||||
.extern Entry7_8
|
||||
.extern Entry8_8
|
||||
#endif
|
||||
|
||||
entryvec_table: .long 0, Entry2_8, Entry3_8, Entry4_8
|
||||
.long Entry5_8, Entry6_8, Entry7_8, Entry8_8
|
||||
|
||||
#ifndef NeXT
|
||||
.extern Spr8Entry2_8
|
||||
.extern Spr8Entry3_8
|
||||
.extern Spr8Entry4_8
|
||||
.extern Spr8Entry5_8
|
||||
.extern Spr8Entry6_8
|
||||
.extern Spr8Entry7_8
|
||||
.extern Spr8Entry8_8
|
||||
#endif
|
||||
|
||||
.globl spr8entryvec_table
|
||||
spr8entryvec_table: .long 0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8
|
||||
.long Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8
|
||||
|
||||
#endif // id386
|
||||
|
53
engine/sw/d_zpoint.c
Normal file
53
engine/sw/d_zpoint.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// d_zpoint.c: software driver module for drawing z-buffered points
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "d_local.h"
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
D_DrawZPoint
|
||||
=====================
|
||||
*/
|
||||
void D_DrawZPoint (void)
|
||||
{
|
||||
qbyte *pdest;
|
||||
short *pz;
|
||||
int izi;
|
||||
|
||||
pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u;
|
||||
pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u;
|
||||
izi = (int)(r_zpointdesc.zi * 0x8000);
|
||||
|
||||
if (*pz <= izi)
|
||||
{
|
||||
*pz = izi;
|
||||
*pdest = r_zpointdesc.color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void D_ClearDepth(void)
|
||||
{
|
||||
memset(d_pzbuffer, 0, sizeof(*d_pzbuffer)*vid.width*vid.height);
|
||||
}
|
||||
|
62
engine/sw/nonintel.c
Normal file
62
engine/sw/nonintel.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
//
|
||||
// nonintel.c: code for non-Intel processors only
|
||||
//
|
||||
|
||||
#include "quakedef.h"
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
================
|
||||
R_Surf8Patch
|
||||
================
|
||||
*/
|
||||
void R_Surf8Patch ()
|
||||
{
|
||||
// we only patch code on Intel
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_Surf16Patch
|
||||
================
|
||||
*/
|
||||
void R_Surf16Patch ()
|
||||
{
|
||||
// we only patch code on Intel
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_SurfacePatch
|
||||
================
|
||||
*/
|
||||
void R_SurfacePatch (void)
|
||||
{
|
||||
// we only patch code on Intel
|
||||
}
|
||||
|
||||
|
||||
#endif // !id386
|
||||
|
358
engine/sw/r_aclip.c
Normal file
358
engine/sw/r_aclip.c
Normal file
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
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_aclip.c: clip routines for drawing Alias models directly to the screen
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "r_local.h"
|
||||
#include "d_local.h"
|
||||
|
||||
static finalvert_t fv[2][8];
|
||||
static mstvert_t fstv[2][8];
|
||||
static auxvert_t av[8];
|
||||
|
||||
void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
|
||||
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
|
||||
finalvert_t *out);
|
||||
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
|
||||
finalvert_t *out);
|
||||
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
|
||||
finalvert_t *out);
|
||||
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
|
||||
finalvert_t *out);
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_Alias_clip_z
|
||||
|
||||
pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
|
||||
================
|
||||
*/
|
||||
void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
auxvert_t *pav0, *pav1, avout;
|
||||
|
||||
pav0 = &av[pfv0 - &fv[0][0]];
|
||||
pav1 = &av[pfv1 - &fv[0][0]];
|
||||
|
||||
if (pfv0->v[1] >= pfv1->v[1])
|
||||
{
|
||||
scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
|
||||
(pav1->fv[2] - pav0->fv[2]);
|
||||
|
||||
avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
|
||||
avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
|
||||
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
|
||||
|
||||
out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale;
|
||||
out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale;
|
||||
out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
|
||||
(pav0->fv[2] - pav1->fv[2]);
|
||||
|
||||
avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale;
|
||||
avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale;
|
||||
avout.fv[2] = ALIAS_Z_CLIP_PLANE;
|
||||
|
||||
out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale;
|
||||
out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale;
|
||||
out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale;
|
||||
}
|
||||
|
||||
R_AliasProjectFinalVert (out, &avout);
|
||||
|
||||
if (out->v[0] < r_refdef.aliasvrect.x)
|
||||
out->flags |= ALIAS_LEFT_CLIP;
|
||||
if (out->v[1] < r_refdef.aliasvrect.y)
|
||||
out->flags |= ALIAS_TOP_CLIP;
|
||||
if (out->v[0] > r_refdef.aliasvrectright)
|
||||
out->flags |= ALIAS_RIGHT_CLIP;
|
||||
if (out->v[1] > r_refdef.aliasvrectbottom)
|
||||
out->flags |= ALIAS_BOTTOM_CLIP;
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
int i;
|
||||
|
||||
if (pfv0->v[1] >= pfv1->v[1])
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) /
|
||||
(pfv1->v[0] - pfv0->v[0]);
|
||||
for (i=0 ; i<6 ; i++)
|
||||
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) /
|
||||
(pfv0->v[0] - pfv1->v[0]);
|
||||
for (i=0 ; i<6 ; i++)
|
||||
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
|
||||
finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
int i;
|
||||
|
||||
if (pfv0->v[1] >= pfv1->v[1])
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) /
|
||||
(pfv1->v[0] - pfv0->v[0]);
|
||||
for (i=0 ; i<6 ; i++)
|
||||
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) /
|
||||
(pfv0->v[0] - pfv1->v[0]);
|
||||
for (i=0 ; i<6 ; i++)
|
||||
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
int i;
|
||||
|
||||
if (pfv0->v[1] >= pfv1->v[1])
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) /
|
||||
(pfv1->v[1] - pfv0->v[1]);
|
||||
for (i=0 ; i<6 ; i++)
|
||||
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) /
|
||||
(pfv0->v[1] - pfv1->v[1]);
|
||||
for (i=0 ; i<6 ; i++)
|
||||
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
|
||||
finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
int i;
|
||||
|
||||
if (pfv0->v[1] >= pfv1->v[1])
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) /
|
||||
(pfv1->v[1] - pfv0->v[1]);
|
||||
|
||||
for (i=0 ; i<6 ; i++)
|
||||
out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) /
|
||||
(pfv0->v[1] - pfv1->v[1]);
|
||||
|
||||
for (i=0 ; i<6 ; i++)
|
||||
out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
|
||||
void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
|
||||
{
|
||||
int i,j,k;
|
||||
int flags, oldflags;
|
||||
|
||||
j = count-1;
|
||||
k = 0;
|
||||
for (i=0 ; i<count ; j = i, i++)
|
||||
{
|
||||
oldflags = in[j].flags & flag;
|
||||
flags = in[i].flags & flag;
|
||||
|
||||
if (flags && oldflags)
|
||||
continue;
|
||||
if (oldflags ^ flags)
|
||||
{
|
||||
clip (&in[j], &in[i], &out[k]);
|
||||
out[k].flags = 0;
|
||||
if (out[k].v[0] < r_refdef.aliasvrect.x)
|
||||
out[k].flags |= ALIAS_LEFT_CLIP;
|
||||
if (out[k].v[1] < r_refdef.aliasvrect.y)
|
||||
out[k].flags |= ALIAS_TOP_CLIP;
|
||||
if (out[k].v[0] > r_refdef.aliasvrectright)
|
||||
out[k].flags |= ALIAS_RIGHT_CLIP;
|
||||
if (out[k].v[1] > r_refdef.aliasvrectbottom)
|
||||
out[k].flags |= ALIAS_BOTTOM_CLIP;
|
||||
k++;
|
||||
}
|
||||
if (!flags)
|
||||
{
|
||||
out[k] = in[i];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasClipTriangle
|
||||
================
|
||||
*/
|
||||
void R_AliasClipTriangle (mtriangle_t *ptri)
|
||||
{
|
||||
int i, k, pingpong;
|
||||
mtriangle_t mtri;
|
||||
unsigned clipflags;
|
||||
|
||||
mstvert_t *pst = r_affinetridesc.pstverts;
|
||||
|
||||
|
||||
// copy vertexes and fix seam texture coordinates
|
||||
fv[0][0] = pfinalverts[ptri->xyz_index[0]];
|
||||
fv[0][1] = pfinalverts[ptri->xyz_index[1]];
|
||||
fv[0][2] = pfinalverts[ptri->xyz_index[2]];
|
||||
|
||||
fv[0][0].v[2] = pst[ptri->st_index[0]].s;
|
||||
fv[0][0].v[3] = pst[ptri->st_index[0]].t;
|
||||
|
||||
fv[0][1].v[2] = pst[ptri->st_index[1]].s;
|
||||
fv[0][1].v[3] = pst[ptri->st_index[1]].t;
|
||||
|
||||
fv[0][2].v[2] = pst[ptri->st_index[2]].s;
|
||||
fv[0][2].v[3] = pst[ptri->st_index[2]].t;
|
||||
|
||||
// clip
|
||||
clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
|
||||
|
||||
if (clipflags & ALIAS_Z_CLIP)
|
||||
{
|
||||
for (i=0 ; i<3 ; i++)
|
||||
av[i] = pauxverts[ptri->xyz_index[i]];
|
||||
|
||||
k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
|
||||
if (k == 0)
|
||||
return;
|
||||
|
||||
pingpong = 1;
|
||||
clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
pingpong = 0;
|
||||
k = 3;
|
||||
}
|
||||
|
||||
if (clipflags & ALIAS_LEFT_CLIP)
|
||||
{
|
||||
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
|
||||
ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
|
||||
if (k == 0)
|
||||
return;
|
||||
|
||||
pingpong ^= 1;
|
||||
}
|
||||
|
||||
if (clipflags & ALIAS_RIGHT_CLIP)
|
||||
{
|
||||
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
|
||||
ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
|
||||
if (k == 0)
|
||||
return;
|
||||
|
||||
pingpong ^= 1;
|
||||
}
|
||||
|
||||
if (clipflags & ALIAS_BOTTOM_CLIP)
|
||||
{
|
||||
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
|
||||
ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
|
||||
if (k == 0)
|
||||
return;
|
||||
|
||||
pingpong ^= 1;
|
||||
}
|
||||
|
||||
if (clipflags & ALIAS_TOP_CLIP)
|
||||
{
|
||||
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
|
||||
ALIAS_TOP_CLIP, k, R_Alias_clip_top);
|
||||
if (k == 0)
|
||||
return;
|
||||
|
||||
pingpong ^= 1;
|
||||
}
|
||||
|
||||
for (i=0 ; i<k ; i++)
|
||||
{
|
||||
if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
|
||||
fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
|
||||
else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
|
||||
fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
|
||||
|
||||
if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
|
||||
fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
|
||||
else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
|
||||
fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
|
||||
|
||||
fv[pingpong][i].flags = 0;
|
||||
}
|
||||
|
||||
// draw triangles
|
||||
r_affinetridesc.ptriangles = &mtri;
|
||||
r_affinetridesc.pfinalverts = fv[pingpong];
|
||||
r_affinetridesc.pstverts = fstv[pingpong];
|
||||
|
||||
// FIXME: do all at once as trifan?
|
||||
mtri.xyz_index[0] = 0;
|
||||
mtri.st_index[0] = 0;
|
||||
|
||||
for (i=1 ; i<k-1 ; i++)
|
||||
{
|
||||
mtri.xyz_index[1] = i;
|
||||
mtri.st_index[1] = i;
|
||||
mtri.xyz_index[2] = i+1;
|
||||
mtri.st_index[2] = i+1;
|
||||
if (r_pixbytes == 4)
|
||||
D_PolysetDraw32 ();
|
||||
else
|
||||
D_PolysetDraw ();
|
||||
}
|
||||
r_affinetridesc.pstverts = pst;
|
||||
}
|
||||
|
216
engine/sw/r_aclipa.s
Normal file
216
engine/sw/r_aclipa.s
Normal 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
|
||||
|
935
engine/sw/r_alias.c
Normal file
935
engine/sw/r_alias.c
Normal file
|
@ -0,0 +1,935 @@
|
|||
/*
|
||||
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_alias.c: routines for setting up to draw alias models
|
||||
|
||||
//changes include stvertexes now being seperatly number from the triangles.
|
||||
//this allows q2 models to be supported.
|
||||
//lerping is also available.
|
||||
|
||||
//future aims include better skin management.
|
||||
|
||||
//the asm code cannot handle alias models anymore.
|
||||
#ifndef NOASM
|
||||
#define NOASM
|
||||
#endif
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "r_local.h"
|
||||
#include "d_local.h" // FIXME: shouldn't be needed (is needed for patch
|
||||
// right now, but that should move)
|
||||
|
||||
#define Q2RF_DEPTHHACK 16 // for view weapon Z crunching
|
||||
|
||||
#define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the
|
||||
// need for inner-loop light clamping
|
||||
|
||||
mtriangle_t *ptriangles;
|
||||
affinetridesc_t r_affinetridesc;
|
||||
|
||||
void * acolormap; // FIXME: should go away
|
||||
|
||||
dtrivertx_t *r_apoldverts;
|
||||
dtrivertx_t *r_apnewverts;
|
||||
vec3_t r_afrntlerp;
|
||||
vec3_t r_abacklerp;
|
||||
vec3_t r_amovelerp;
|
||||
|
||||
// TODO: these probably will go away with optimized rasterization
|
||||
mmdl_t *pmdl;
|
||||
vec3_t r_plightvec;
|
||||
int r_ambientlight;
|
||||
float r_shadelight;
|
||||
aliashdr_t *paliashdr;
|
||||
finalvert_t *pfinalverts;
|
||||
auxvert_t *pauxverts;
|
||||
static float ziscale;
|
||||
static model_t *pmodel;
|
||||
|
||||
extern int cl_playerindex;
|
||||
|
||||
static vec3_t alias_forward, alias_right, alias_up;
|
||||
|
||||
static maliasskindesc_t *pskindesc;
|
||||
|
||||
int r_amodels_drawn;
|
||||
int a_skinwidth;
|
||||
int r_anumverts;
|
||||
|
||||
float aliastransform[3][4];
|
||||
|
||||
typedef struct {
|
||||
int index0;
|
||||
int index1;
|
||||
} aedge_t;
|
||||
|
||||
static aedge_t aedges[12] = {
|
||||
{0, 1}, {1, 2}, {2, 3}, {3, 0},
|
||||
{4, 5}, {5, 6}, {6, 7}, {7, 4},
|
||||
{0, 5}, {1, 4}, {2, 7}, {3, 6}
|
||||
};
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
|
||||
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
|
||||
|
||||
void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv);//,
|
||||
//mstvert_t *pstverts);
|
||||
void R_AliasSetUpTransform (int trivial_accept);
|
||||
void R_AliasTransformVector (vec3_t in, vec3_t out);
|
||||
void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
|
||||
dtrivertx_t *pnewverts, dtrivertx_t *poldverts);//, mstvert_t *pstverts);
|
||||
void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasCheckBBox
|
||||
================
|
||||
*/
|
||||
qboolean R_AliasCheckBBox (void)
|
||||
{
|
||||
int i, flags, nframe, oframe, numv;
|
||||
aliashdr_t *pahdr;
|
||||
float zi, basepts[8][3], v0, v1, frac;
|
||||
finalvert_t *pv0, *pv1, viewpts[16];
|
||||
auxvert_t *pa0, *pa1, viewaux[16];
|
||||
maliasframedesc_t *pnewframedesc, *poldframedesc;
|
||||
qboolean zclipped, zfullyclipped;
|
||||
unsigned anyclip, allclip;
|
||||
int minz;
|
||||
float a, b;
|
||||
vec3_t min, max;
|
||||
|
||||
|
||||
// expand, rotate, and translate points into worldspace
|
||||
|
||||
currententity->trivial_accept = 0;
|
||||
pmodel = currententity->model;
|
||||
pahdr = SWMod_Extradata (pmodel);
|
||||
pmdl = (mmdl_t *)((qbyte *)pahdr + pahdr->model);
|
||||
|
||||
R_AliasSetUpTransform (0);
|
||||
|
||||
// construct the base bounding box for this frame
|
||||
nframe = currententity->frame;
|
||||
// TODO: don't repeat this check when drawing?
|
||||
if ((nframe >= pmdl->numframes) || (nframe < 0))
|
||||
{
|
||||
Con_DPrintf ("No such frame %d %s\n", nframe,
|
||||
pmodel->name);
|
||||
nframe = 0;
|
||||
}
|
||||
|
||||
// construct the base bounding box for this frame
|
||||
oframe = currententity->frame;
|
||||
// TODO: don't repeat this check when drawing?
|
||||
if ((oframe >= pmdl->numframes) || (oframe < 0))
|
||||
{
|
||||
Con_DPrintf ("No such frame %d %s\n", oframe,
|
||||
pmodel->name);
|
||||
oframe = 0;
|
||||
}
|
||||
|
||||
pnewframedesc = &pahdr->frames[nframe];
|
||||
poldframedesc = &pahdr->frames[oframe];
|
||||
|
||||
for (i = 0; i < 3; i++) //choose the most outward of the two.
|
||||
{
|
||||
a = poldframedesc->scale_origin[i] + poldframedesc->bboxmin.v[i]*poldframedesc->scale[i];
|
||||
b = pnewframedesc->scale_origin[i] + pnewframedesc->bboxmin.v[i]*pnewframedesc->scale[i];
|
||||
min[i] = a>b?b:a;
|
||||
|
||||
a = poldframedesc->scale_origin[i] + poldframedesc->bboxmax.v[i]*poldframedesc->scale[i];
|
||||
b = pnewframedesc->scale_origin[i] + pnewframedesc->bboxmax.v[i]*pnewframedesc->scale[i];
|
||||
max[i] = a>b?a:b;
|
||||
}
|
||||
|
||||
// x worldspace coordinates
|
||||
basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = min[0];
|
||||
basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = max[0];
|
||||
|
||||
// y worldspace coordinates
|
||||
basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = min[1];
|
||||
basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = max[1];
|
||||
|
||||
// z worldspace coordinates
|
||||
basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = min[2];
|
||||
basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = max[2];
|
||||
|
||||
zclipped = false;
|
||||
zfullyclipped = true;
|
||||
|
||||
minz = 9999;
|
||||
for (i=0; i<8 ; i++)
|
||||
{
|
||||
R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]);
|
||||
|
||||
if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE)
|
||||
{
|
||||
// we must clip points that are closer than the near clip plane
|
||||
viewpts[i].flags = ALIAS_Z_CLIP;
|
||||
zclipped = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (viewaux[i].fv[2] < minz)
|
||||
minz = viewaux[i].fv[2];
|
||||
viewpts[i].flags = 0;
|
||||
zfullyclipped = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (zfullyclipped)
|
||||
{
|
||||
return false; // everything was near-z-clipped
|
||||
}
|
||||
|
||||
numv = 8;
|
||||
|
||||
if (zclipped)
|
||||
{
|
||||
// organize points by edges, use edges to get new points (possible trivial
|
||||
// reject)
|
||||
for (i=0 ; i<12 ; i++)
|
||||
{
|
||||
// edge endpoints
|
||||
pv0 = &viewpts[aedges[i].index0];
|
||||
pv1 = &viewpts[aedges[i].index1];
|
||||
pa0 = &viewaux[aedges[i].index0];
|
||||
pa1 = &viewaux[aedges[i].index1];
|
||||
|
||||
// if one end is clipped and the other isn't, make a new point
|
||||
if (pv0->flags ^ pv1->flags)
|
||||
{
|
||||
frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
|
||||
(pa1->fv[2] - pa0->fv[2]);
|
||||
viewaux[numv].fv[0] = pa0->fv[0] +
|
||||
(pa1->fv[0] - pa0->fv[0]) * frac;
|
||||
viewaux[numv].fv[1] = pa0->fv[1] +
|
||||
(pa1->fv[1] - pa0->fv[1]) * frac;
|
||||
viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
|
||||
viewpts[numv].flags = 0;
|
||||
numv++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// project the vertices that remain after clipping
|
||||
anyclip = 0;
|
||||
allclip = ALIAS_XY_CLIP_MASK;
|
||||
|
||||
// TODO: probably should do this loop in ASM, especially if we use floats
|
||||
for (i=0 ; i<numv ; i++)
|
||||
{
|
||||
// we don't need to bother with vertices that were z-clipped
|
||||
if (viewpts[i].flags & ALIAS_Z_CLIP)
|
||||
continue;
|
||||
|
||||
zi = 1.0 / viewaux[i].fv[2];
|
||||
|
||||
// FIXME: do with chop mode in ASM, or convert to float
|
||||
v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter;
|
||||
v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter;
|
||||
|
||||
flags = 0;
|
||||
|
||||
if (v0 < r_refdef.fvrectx)
|
||||
flags |= ALIAS_LEFT_CLIP;
|
||||
if (v1 < r_refdef.fvrecty)
|
||||
flags |= ALIAS_TOP_CLIP;
|
||||
if (v0 > r_refdef.fvrectright)
|
||||
flags |= ALIAS_RIGHT_CLIP;
|
||||
if (v1 > r_refdef.fvrectbottom)
|
||||
flags |= ALIAS_BOTTOM_CLIP;
|
||||
|
||||
anyclip |= flags;
|
||||
allclip &= flags;
|
||||
}
|
||||
|
||||
if (allclip)
|
||||
return false; // trivial reject off one side
|
||||
|
||||
// currententity->trivial_accept = !anyclip & !zclipped;
|
||||
|
||||
if (currententity->trivial_accept)
|
||||
{
|
||||
if (minz > (r_aliastransition + (pmdl->size * r_resfudge)))
|
||||
{
|
||||
// currententity->trivial_accept |= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasTransformVector
|
||||
================
|
||||
*/
|
||||
void R_AliasTransformVector (vec3_t in, vec3_t out)
|
||||
{
|
||||
out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3];
|
||||
out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3];
|
||||
out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasPreparePoints
|
||||
|
||||
General clipped case
|
||||
================
|
||||
*/
|
||||
void R_AliasPreparePoints (void)
|
||||
{
|
||||
int i;
|
||||
mstvert_t *pstverts;
|
||||
finalvert_t *fv;
|
||||
auxvert_t *av;
|
||||
mtriangle_t *ptri;
|
||||
finalvert_t *pfv[3];
|
||||
|
||||
r_anumverts = pmdl->numverts;
|
||||
fv = pfinalverts;
|
||||
av = pauxverts;
|
||||
|
||||
#ifdef PEXT_TRANS
|
||||
if (currententity->alpha != 1)
|
||||
{
|
||||
Set_TransLevelF(currententity->alpha);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apnewverts++, r_apoldverts++)
|
||||
{
|
||||
R_AliasTransformFinalVert (fv, av, r_apnewverts, r_apoldverts);
|
||||
if (av->fv[2] < ALIAS_Z_CLIP_PLANE)
|
||||
fv->flags |= ALIAS_Z_CLIP;
|
||||
else
|
||||
{
|
||||
R_AliasProjectFinalVert (fv, av);
|
||||
|
||||
if (fv->v[0] < r_refdef.aliasvrect.x)
|
||||
fv->flags |= ALIAS_LEFT_CLIP;
|
||||
if (fv->v[1] < r_refdef.aliasvrect.y)
|
||||
fv->flags |= ALIAS_TOP_CLIP;
|
||||
if (fv->v[0] > r_refdef.aliasvrectright)
|
||||
fv->flags |= ALIAS_RIGHT_CLIP;
|
||||
if (fv->v[1] > r_refdef.aliasvrectbottom)
|
||||
fv->flags |= ALIAS_BOTTOM_CLIP;
|
||||
}
|
||||
}
|
||||
|
||||
pstverts = (mstvert_t *)((qbyte *)paliashdr + paliashdr->stverts);
|
||||
//
|
||||
// clip and draw all triangles
|
||||
//
|
||||
r_affinetridesc.numtriangles = 1;
|
||||
|
||||
ptri = (mtriangle_t *)((qbyte *)paliashdr + paliashdr->triangles);
|
||||
for (i=0 ; i<pmdl->numtris ; i++, ptri++)
|
||||
{
|
||||
pfv[0] = &pfinalverts[ptri->xyz_index[0]];
|
||||
pfv[1] = &pfinalverts[ptri->xyz_index[1]];
|
||||
pfv[2] = &pfinalverts[ptri->xyz_index[2]];
|
||||
|
||||
if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) )
|
||||
continue; // completely clipped
|
||||
|
||||
pfv[0]->v[2] = pstverts[ptri->st_index[0]].s;
|
||||
pfv[0]->v[3] = pstverts[ptri->st_index[0]].t;
|
||||
|
||||
pfv[1]->v[2] = pstverts[ptri->st_index[1]].s;
|
||||
pfv[1]->v[3] = pstverts[ptri->st_index[1]].t;
|
||||
|
||||
pfv[2]->v[2] = pstverts[ptri->st_index[2]].s;
|
||||
pfv[2]->v[3] = pstverts[ptri->st_index[2]].t;
|
||||
|
||||
if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &
|
||||
(ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) )
|
||||
{ // totally unclipped
|
||||
r_affinetridesc.pfinalverts = pfinalverts;
|
||||
r_affinetridesc.ptriangles = ptri;
|
||||
if (r_pixbytes == 4)
|
||||
D_PolysetDraw32 ();
|
||||
else if (r_pixbytes == 2)
|
||||
D_PolysetDraw16 ();
|
||||
else
|
||||
D_PolysetDraw ();
|
||||
}
|
||||
else
|
||||
{ // partially clipped
|
||||
R_AliasClipTriangle (ptri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasSetUpTransform
|
||||
================
|
||||
*/
|
||||
void R_AliasSetUpTransform (int trivial_accept)
|
||||
{
|
||||
int i;
|
||||
float rotationmatrix[3][4], t2matrix[3][4];
|
||||
static float tmatrix[3][4];
|
||||
static float viewmatrix[3][4];
|
||||
vec3_t angles;
|
||||
|
||||
// TODO: should really be stored with the entity instead of being reconstructed
|
||||
// TODO: should use a look-up table
|
||||
// TODO: could cache lazily, stored in the entity
|
||||
|
||||
angles[ROLL] = currententity->angles[ROLL];
|
||||
angles[PITCH] = -currententity->angles[PITCH];
|
||||
angles[YAW] = currententity->angles[YAW];
|
||||
AngleVectors (angles, alias_forward, alias_right, alias_up);
|
||||
|
||||
tmatrix[0][0] = currententity->scale;
|
||||
tmatrix[1][1] = currententity->scale;
|
||||
tmatrix[2][2] = currententity->scale;
|
||||
|
||||
tmatrix[0][3] = 0;
|
||||
tmatrix[1][3] = 0;
|
||||
tmatrix[2][3] = 0;
|
||||
|
||||
// TODO: can do this with simple matrix rearrangement
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
t2matrix[i][0] = alias_forward[i];
|
||||
t2matrix[i][1] = -alias_right[i];
|
||||
t2matrix[i][2] = alias_up[i];
|
||||
}
|
||||
|
||||
t2matrix[0][3] = -modelorg[0];
|
||||
t2matrix[1][3] = -modelorg[1];
|
||||
t2matrix[2][3] = -modelorg[2];
|
||||
|
||||
// FIXME: can do more efficiently than full concatenation
|
||||
R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
|
||||
|
||||
// TODO: should be global, set when vright, etc., set
|
||||
VectorCopy (vright, viewmatrix[0]);
|
||||
VectorCopy (vup, viewmatrix[1]);
|
||||
VectorInverse (viewmatrix[1]);
|
||||
VectorCopy (vpn, viewmatrix[2]);
|
||||
|
||||
// viewmatrix[0][3] = 0;
|
||||
// viewmatrix[1][3] = 0;
|
||||
// viewmatrix[2][3] = 0;
|
||||
|
||||
R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform);
|
||||
|
||||
// do the scaling up of x and y to screen coordinates as part of the transform
|
||||
// for the unclipped case (it would mess up clipping in the clipped case).
|
||||
// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
|
||||
// correspondingly so the projected x and y come out right
|
||||
// FIXME: make this work for clipped case too?
|
||||
if (trivial_accept)
|
||||
{
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
aliastransform[0][i] *= aliasxscale *
|
||||
(1.0 / ((float)0x8000 * 0x10000));
|
||||
aliastransform[1][i] *= aliasyscale *
|
||||
(1.0 / ((float)0x8000 * 0x10000));
|
||||
aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasTransformFinalVert
|
||||
================
|
||||
*/
|
||||
void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
|
||||
dtrivertx_t *pnewverts, dtrivertx_t *poldverts)//, mstvert_t *pstverts)
|
||||
{
|
||||
int temp;
|
||||
float lightcos, *plightnormal;
|
||||
|
||||
vec3_t lerp_org;
|
||||
|
||||
lerp_org[0] = r_amovelerp[0] + pnewverts->v[0]*r_afrntlerp[0] + poldverts->v[0]*r_abacklerp[0];
|
||||
lerp_org[1] = r_amovelerp[1] + pnewverts->v[1]*r_afrntlerp[1] + poldverts->v[1]*r_abacklerp[1];
|
||||
lerp_org[2] = r_amovelerp[2] + pnewverts->v[2]*r_afrntlerp[2] + poldverts->v[2]*r_abacklerp[2];
|
||||
|
||||
av->fv[0] = DotProduct(lerp_org, aliastransform[0]) +
|
||||
aliastransform[0][3];
|
||||
av->fv[1] = DotProduct(lerp_org, aliastransform[1]) +
|
||||
aliastransform[1][3];
|
||||
av->fv[2] = DotProduct(lerp_org, aliastransform[2]) +
|
||||
aliastransform[2][3];
|
||||
|
||||
fv->v[2] = 0;
|
||||
fv->v[3] = 0;
|
||||
|
||||
fv->flags = 0;
|
||||
|
||||
// lighting
|
||||
plightnormal = r_avertexnormals[pnewverts->lightnormalindex];
|
||||
lightcos = DotProduct (plightnormal, r_plightvec);
|
||||
temp = r_ambientlight;
|
||||
|
||||
if (lightcos < 0)
|
||||
{
|
||||
temp += (int)(r_shadelight * lightcos);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
fv->v[4] = temp;
|
||||
}
|
||||
|
||||
|
||||
#if 1 //!id386 since stvert_t was changed.
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasTransformAndProjectFinalVerts
|
||||
================
|
||||
*/
|
||||
void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv)//, stvert_t *pstverts)
|
||||
{
|
||||
int i, temp;
|
||||
float lightcos, *plightnormal, zi;
|
||||
dtrivertx_t *pnewverts, *poldverts;
|
||||
|
||||
vec3_t lerp_org;
|
||||
|
||||
pnewverts = r_apnewverts;
|
||||
poldverts = r_apoldverts;
|
||||
|
||||
for (i=0 ; i<r_anumverts ; i++, fv++, pnewverts++, poldverts++)
|
||||
{
|
||||
lerp_org[0] = r_amovelerp[0] + pnewverts->v[0]*r_afrntlerp[0] + poldverts->v[0]*r_abacklerp[0];
|
||||
lerp_org[1] = r_amovelerp[1] + pnewverts->v[1]*r_afrntlerp[1] + poldverts->v[1]*r_abacklerp[1];
|
||||
lerp_org[2] = r_amovelerp[2] + pnewverts->v[2]*r_afrntlerp[2] + poldverts->v[2]*r_abacklerp[2];
|
||||
|
||||
// transform and project
|
||||
zi = 1.0 / (DotProduct(lerp_org, aliastransform[2]) +
|
||||
aliastransform[2][3]);
|
||||
|
||||
// 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[5] = zi;
|
||||
|
||||
fv->v[0] = ((DotProduct(lerp_org, aliastransform[0]) +
|
||||
aliastransform[0][3]) * zi) + aliasxcenter;
|
||||
fv->v[1] = ((DotProduct(lerp_org, aliastransform[1]) +
|
||||
aliastransform[1][3]) * zi) + aliasycenter;
|
||||
|
||||
fv->v[2] = 0;//pstverts->s;
|
||||
fv->v[3] = 0;//pstverts->t;
|
||||
fv->flags = 0;
|
||||
|
||||
// lighting
|
||||
plightnormal = r_avertexnormals[pnewverts->lightnormalindex]; //don't bother lerping light.
|
||||
lightcos = DotProduct (plightnormal, r_plightvec);
|
||||
temp = r_ambientlight;
|
||||
|
||||
if (lightcos < 0)
|
||||
{
|
||||
temp += (int)(r_shadelight * lightcos);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
fv->v[4] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasProjectFinalVert
|
||||
================
|
||||
*/
|
||||
void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av)
|
||||
{
|
||||
float zi;
|
||||
|
||||
// project points
|
||||
zi = 1.0 / av->fv[2];
|
||||
|
||||
fv->v[5] = zi * ziscale;
|
||||
|
||||
fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter;
|
||||
fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasPrepareUnclippedPoints
|
||||
================
|
||||
*/
|
||||
void R_AliasPrepareUnclippedPoints (void)
|
||||
{
|
||||
finalvert_t *fv;
|
||||
|
||||
r_anumverts = pmdl->numverts;
|
||||
// FIXME: just use pfinalverts directly?
|
||||
fv = pfinalverts;
|
||||
|
||||
R_AliasTransformAndProjectFinalVerts (fv);
|
||||
|
||||
if (r_affinetridesc.drawtype)
|
||||
{
|
||||
if (r_pixbytes == 4)
|
||||
D_PolysetDrawFinalVerts32Trans (fv, r_anumverts);
|
||||
else
|
||||
D_PolysetDrawFinalVerts (fv, r_anumverts);
|
||||
}
|
||||
|
||||
r_affinetridesc.pfinalverts = pfinalverts;
|
||||
r_affinetridesc.ptriangles = (mtriangle_t *)
|
||||
((qbyte *)paliashdr + paliashdr->triangles);
|
||||
r_affinetridesc.numtriangles = pmdl->numtris;
|
||||
|
||||
if (r_pixbytes == 4)
|
||||
D_PolysetDraw32 ();
|
||||
else
|
||||
D_PolysetDraw ();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_AliasSetupSkin
|
||||
===============
|
||||
*/
|
||||
void R_AliasSetupSkin (void)
|
||||
{
|
||||
int skinnum;
|
||||
int i, numskins;
|
||||
maliasskingroup_t *paliasskingroup;
|
||||
float *pskinintervals, fullskininterval;
|
||||
float skintargettime, skintime;
|
||||
|
||||
skinnum = currententity->skinnum;
|
||||
if ((skinnum >= pmdl->numskins) || (skinnum < 0))
|
||||
{
|
||||
Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum);
|
||||
skinnum = 0;
|
||||
}
|
||||
|
||||
pskindesc = ((maliasskindesc_t *)
|
||||
((qbyte *)paliashdr + paliashdr->skindesc)) + skinnum;
|
||||
a_skinwidth = pmdl->skinwidth;
|
||||
|
||||
if (pskindesc->type == ALIAS_SKIN_GROUP)
|
||||
{
|
||||
paliasskingroup = (maliasskingroup_t *)((qbyte *)paliashdr +
|
||||
pskindesc->skin);
|
||||
pskinintervals = (float *)
|
||||
((qbyte *)paliashdr + paliasskingroup->intervals);
|
||||
numskins = paliasskingroup->numskins;
|
||||
fullskininterval = pskinintervals[numskins-1];
|
||||
|
||||
skintime = cl.time + currententity->syncbase;
|
||||
|
||||
// when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval
|
||||
// values are positive, so we don't have to worry about division by 0
|
||||
skintargettime = skintime -
|
||||
((int)(skintime / fullskininterval)) * fullskininterval;
|
||||
|
||||
for (i=0 ; i<(numskins-1) ; i++)
|
||||
{
|
||||
if (pskinintervals[i] > skintargettime)
|
||||
break;
|
||||
}
|
||||
|
||||
pskindesc = &paliasskingroup->skindescs[i];
|
||||
}
|
||||
|
||||
r_affinetridesc.pskindesc = pskindesc;
|
||||
r_affinetridesc.pskin = (void *)((qbyte *)paliashdr + pskindesc->skin);
|
||||
r_affinetridesc.skinwidth = a_skinwidth;
|
||||
r_affinetridesc.skinheight = pmdl->skinheight;
|
||||
|
||||
if (currententity->model != cl.model_precache[cl_playerindex])
|
||||
return;
|
||||
//alternate player skins.
|
||||
if (currententity->scoreboard && r_pixbytes == 1)
|
||||
{
|
||||
qbyte *base;
|
||||
skin_t *skin;
|
||||
|
||||
if (!currententity->scoreboard->skin)
|
||||
Skin_Find (currententity->scoreboard);
|
||||
base = Skin_Cache8 (currententity->scoreboard->skin);
|
||||
skin = currententity->scoreboard->skin;
|
||||
if (base && skin->cachedbpp == r_pixbytes*8)
|
||||
{
|
||||
r_affinetridesc.pskin = base;
|
||||
r_affinetridesc.skinwidth = skin->width;
|
||||
r_affinetridesc.skinheight = skin->height;
|
||||
}
|
||||
}
|
||||
else if (currententity->scoreboard)
|
||||
{
|
||||
qbyte *base;
|
||||
skin_t *skin;
|
||||
|
||||
if (!currententity->scoreboard->skin)
|
||||
Skin_Find (currententity->scoreboard);
|
||||
base = Skin_Cache32 (currententity->scoreboard->skin);
|
||||
skin = currententity->scoreboard->skin;
|
||||
if (base && skin->cachedbpp == r_pixbytes*8)
|
||||
{
|
||||
r_affinetridesc.pskin = base;
|
||||
r_affinetridesc.skinwidth = skin->width;
|
||||
r_affinetridesc.skinheight = skin->height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasSetupLighting
|
||||
================
|
||||
*/
|
||||
void R_AliasSetupLighting (alight_t *plighting)
|
||||
{
|
||||
|
||||
if (r_pixbytes == 4)
|
||||
{ //fixes inverse lighting in sw 32.
|
||||
//we fix it here so the lighting code doesn't have to have lots of extra minuses, as they are multiplied out
|
||||
plighting->ambientlight=(128-plighting->ambientlight);
|
||||
plighting->shadelight=(128-plighting->shadelight);
|
||||
}
|
||||
|
||||
// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
|
||||
// to clamp off the bottom
|
||||
r_ambientlight = plighting->ambientlight;
|
||||
|
||||
r_shadelight = plighting->shadelight;
|
||||
|
||||
if (r_ambientlight < LIGHT_MIN)
|
||||
r_ambientlight = LIGHT_MIN;
|
||||
|
||||
r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
|
||||
|
||||
if (r_ambientlight < LIGHT_MIN)
|
||||
r_ambientlight = LIGHT_MIN;
|
||||
|
||||
if (r_shadelight < 0)
|
||||
r_shadelight = 0;
|
||||
|
||||
r_shadelight *= VID_GRADES;
|
||||
|
||||
// rotate the lighting vector into the model's frame of reference
|
||||
r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
|
||||
r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
|
||||
r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_AliasSetupFrame
|
||||
|
||||
set r_apverts
|
||||
=================
|
||||
*/
|
||||
void R_AliasSetupFrame (void)
|
||||
{
|
||||
int frame, oframe;
|
||||
int i, numframes;
|
||||
maliasgroup_t *paliasgroup;
|
||||
float *pintervals, fullinterval, targettime, time;
|
||||
|
||||
// float *min1, *min2;
|
||||
// vec3_t max1, max2;
|
||||
float fl, bl;
|
||||
|
||||
frame = currententity->frame;
|
||||
if ((frame >= pmdl->numframes) || (frame < 0))
|
||||
{
|
||||
Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
|
||||
frame = 0;
|
||||
}
|
||||
oframe = currententity->oldframe;
|
||||
if ((oframe >= pmdl->numframes) || (oframe < 0))
|
||||
{
|
||||
// Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", oframe); //pointless
|
||||
oframe = 0;
|
||||
}
|
||||
|
||||
bl = currententity->lerptime;
|
||||
fl = 1.0 - bl;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
r_abacklerp[i] = paliashdr->frames[oframe].scale[i]*bl;
|
||||
r_afrntlerp[i] = paliashdr->frames[frame].scale[i]*fl;
|
||||
r_amovelerp[i] = paliashdr->frames[frame].scale_origin[i]*fl + paliashdr->frames[oframe].scale_origin[i]*bl;
|
||||
|
||||
}
|
||||
|
||||
if (paliashdr->frames[frame].type == ALIAS_SINGLE)
|
||||
{
|
||||
r_apnewverts = (dtrivertx_t *)
|
||||
((qbyte *)paliashdr + paliashdr->frames[frame].frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
paliasgroup = (maliasgroup_t *)
|
||||
((qbyte *)paliashdr + paliashdr->frames[frame].frame);
|
||||
pintervals = (float *)((qbyte *)paliashdr + paliasgroup->intervals);
|
||||
numframes = paliasgroup->numframes;
|
||||
fullinterval = pintervals[numframes-1];
|
||||
|
||||
time = cl.time + currententity->syncbase;
|
||||
|
||||
//
|
||||
// when loading in Mod_LoadAliasGroup, we guaranteed all interval values
|
||||
// are positive, so we don't have to worry about division by 0
|
||||
//
|
||||
targettime = time - ((int)(time / fullinterval)) * fullinterval;
|
||||
|
||||
for (i=0 ; i<(numframes-1) ; i++)
|
||||
{
|
||||
if (pintervals[i] > targettime)
|
||||
break;
|
||||
}
|
||||
|
||||
r_apnewverts = (dtrivertx_t *)
|
||||
((qbyte *)paliashdr + paliasgroup->frames[i].frame);
|
||||
}
|
||||
|
||||
if (paliashdr->frames[oframe].type == ALIAS_SINGLE) //things could go haywire here...
|
||||
{
|
||||
r_apoldverts = (dtrivertx_t *)
|
||||
((qbyte *)paliashdr + paliashdr->frames[oframe].frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
paliasgroup = (maliasgroup_t *)
|
||||
((qbyte *)paliashdr + paliashdr->frames[oframe].frame);
|
||||
pintervals = (float *)((qbyte *)paliashdr + paliasgroup->intervals);
|
||||
numframes = paliasgroup->numframes;
|
||||
fullinterval = pintervals[numframes-1];
|
||||
|
||||
time = cl.time + currententity->syncbase;
|
||||
|
||||
//
|
||||
// when loading in Mod_LoadAliasGroup, we guaranteed all interval values
|
||||
// are positive, so we don't have to worry about division by 0
|
||||
//
|
||||
targettime = time - ((int)(time / fullinterval)) * fullinterval;
|
||||
|
||||
for (i=0 ; i<(numframes-1) ; i++)
|
||||
{
|
||||
if (pintervals[i] > targettime)
|
||||
break;
|
||||
}
|
||||
|
||||
r_apoldverts = (dtrivertx_t *)
|
||||
((qbyte *)paliashdr + paliasgroup->frames[i].frame);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasDrawModel
|
||||
================
|
||||
*/
|
||||
void R_AliasDrawModel (alight_t *plighting)
|
||||
{
|
||||
finalvert_t finalverts[MAXALIASVERTS +
|
||||
((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1];
|
||||
auxvert_t auxverts[MAXALIASVERTS];
|
||||
|
||||
extern qbyte transfactor;
|
||||
extern qbyte transbackfac;
|
||||
|
||||
|
||||
r_amodels_drawn++;
|
||||
|
||||
// cache align
|
||||
pfinalverts = (finalvert_t *)
|
||||
(((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
|
||||
pauxverts = &auxverts[0];
|
||||
|
||||
paliashdr = (aliashdr_t *)SWMod_Extradata (currententity->model);
|
||||
pmdl = (mmdl_t *)((qbyte *)paliashdr + paliashdr->model);
|
||||
|
||||
R_AliasSetupSkin ();
|
||||
R_AliasSetUpTransform (currententity->trivial_accept);
|
||||
R_AliasSetupLighting (plighting);
|
||||
R_AliasSetupFrame ();
|
||||
|
||||
transfactor = currententity->alpha*255;
|
||||
transbackfac = 255 - transfactor;
|
||||
|
||||
if (!currententity->colormap)
|
||||
currententity->colormap = vid.colormap;
|
||||
// Sys_Error ("R_AliasDrawModel: !currententity->colormap");
|
||||
|
||||
r_affinetridesc.drawtype = (currententity->trivial_accept == 3) &&
|
||||
r_recursiveaffinetriangles;
|
||||
|
||||
r_affinetridesc.pstverts = (mstvert_t *)((qbyte *)paliashdr + paliashdr->stverts);
|
||||
|
||||
if (r_affinetridesc.drawtype)
|
||||
{
|
||||
D_PolysetUpdateTables (); // FIXME: precalc...
|
||||
}
|
||||
else
|
||||
{
|
||||
#if id386
|
||||
D_Aff8Patch (currententity->colormap);
|
||||
#endif
|
||||
}
|
||||
|
||||
acolormap = currententity->colormap;
|
||||
if (r_pixbytes == 2)
|
||||
acolormap = vid.colormap16;
|
||||
|
||||
if (currententity == &cl.viewent[r_refdef.currentplayernum] || currententity->flags & Q2RF_DEPTHHACK)
|
||||
ziscale = (float)0x8000 * (float)0x10000 * 3.0;
|
||||
else
|
||||
ziscale = (float)0x8000 * (float)0x10000;
|
||||
|
||||
if (currententity->trivial_accept)
|
||||
R_AliasPrepareUnclippedPoints ();
|
||||
else
|
||||
R_AliasPreparePoints ();
|
||||
}
|
||||
|
247
engine/sw/r_aliasa.s
Normal file
247
engine/sw/r_aliasa.s
Normal file
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
//FIXME: rework the changes to stvert_t in.
|
||||
#if 0//id386
|
||||
|
||||
.data
|
||||
|
||||
Lfloat_1: .single 1.0
|
||||
Ltemp: .long 0
|
||||
Lcoords: .long 0, 0, 0
|
||||
|
||||
.text
|
||||
|
||||
#define fv 12+4
|
||||
#if 0
|
||||
#define pstverts 12+8
|
||||
#endif
|
||||
|
||||
.globl C(R_AliasTransformAndProjectFinalVerts)
|
||||
C(R_AliasTransformAndProjectFinalVerts):
|
||||
#if 0
|
||||
pushl %ebp // preserve caller's stack frame
|
||||
#endif
|
||||
pushl %edi
|
||||
pushl %esi // preserve register variables
|
||||
|
||||
// int i, temp;
|
||||
// float lightcos, *plightnormal, zi;
|
||||
// trivertx_t *pverts;
|
||||
|
||||
// pverts = r_apverts;
|
||||
movl C(r_apnewverts),%esi
|
||||
|
||||
// for (i=0 ; i<r_anumverts ; i++, fv++, pverts++)
|
||||
// {
|
||||
#if 0
|
||||
movl pstverts(%esp),%ebp
|
||||
#endif
|
||||
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]
|
||||
|
||||
#if 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
|
||||
#endif
|
||||
// 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
|
||||
#if 0
|
||||
// popl %ebp // restore the caller's stack frame
|
||||
#endif
|
||||
ret
|
||||
|
||||
Lsavelight:
|
||||
fstp %st(0)
|
||||
jmp Lp1
|
||||
|
||||
#endif // id386
|
||||
|
907
engine/sw/r_bsp.c
Normal file
907
engine/sw/r_bsp.c
Normal file
|
@ -0,0 +1,907 @@
|
|||
/*
|
||||
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_bsp.c
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "r_local.h"
|
||||
|
||||
//
|
||||
// current entity info
|
||||
//
|
||||
qboolean insubmodel;
|
||||
entity_t *currententity;
|
||||
vec3_t modelorg, base_modelorg;
|
||||
// modelorg is the viewpoint reletive to
|
||||
// the currently rendering entity
|
||||
vec3_t r_entorigin; // the currently rendering entity in world
|
||||
// coordinates
|
||||
|
||||
float entity_rotation[3][3];
|
||||
|
||||
vec3_t r_worldmodelorg;
|
||||
|
||||
int r_currentbkey;
|
||||
|
||||
typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
|
||||
|
||||
#define MAX_BMODEL_VERTS 500 // 6K
|
||||
#define MAX_BMODEL_EDGES 1000 // 12K
|
||||
|
||||
static mvertex_t *pbverts;
|
||||
static bedge_t *pbedges;
|
||||
static int numbverts, numbedges;
|
||||
|
||||
static mvertex_t *pfrontenter, *pfrontexit;
|
||||
|
||||
static qboolean makeclippededge;
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
R_EntityRotate
|
||||
================
|
||||
*/
|
||||
void R_EntityRotate (vec3_t vec)
|
||||
{
|
||||
vec3_t tvec;
|
||||
|
||||
VectorCopy (vec, tvec);
|
||||
vec[0] = DotProduct (entity_rotation[0], tvec);
|
||||
vec[1] = DotProduct (entity_rotation[1], tvec);
|
||||
vec[2] = DotProduct (entity_rotation[2], tvec);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RotateBmodel
|
||||
================
|
||||
*/
|
||||
void R_RotateBmodel (void)
|
||||
{
|
||||
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
|
||||
|
||||
// TODO: should use a look-up table
|
||||
// TODO: should really be stored with the entity instead of being reconstructed
|
||||
// TODO: could cache lazily, stored in the entity
|
||||
// TODO: share work with R_SetUpAliasTransform
|
||||
|
||||
// yaw
|
||||
angle = currententity->angles[YAW];
|
||||
angle = angle * M_PI*2 / 360;
|
||||
s = sin(angle);
|
||||
c = cos(angle);
|
||||
|
||||
temp1[0][0] = c;
|
||||
temp1[0][1] = s;
|
||||
temp1[0][2] = 0;
|
||||
temp1[1][0] = -s;
|
||||
temp1[1][1] = c;
|
||||
temp1[1][2] = 0;
|
||||
temp1[2][0] = 0;
|
||||
temp1[2][1] = 0;
|
||||
temp1[2][2] = 1;
|
||||
|
||||
|
||||
// pitch
|
||||
angle = currententity->angles[PITCH];
|
||||
angle = angle * M_PI*2 / 360;
|
||||
s = sin(angle);
|
||||
c = cos(angle);
|
||||
|
||||
temp2[0][0] = c;
|
||||
temp2[0][1] = 0;
|
||||
temp2[0][2] = -s;
|
||||
temp2[1][0] = 0;
|
||||
temp2[1][1] = 1;
|
||||
temp2[1][2] = 0;
|
||||
temp2[2][0] = s;
|
||||
temp2[2][1] = 0;
|
||||
temp2[2][2] = c;
|
||||
|
||||
R_ConcatRotations (temp2, temp1, temp3);
|
||||
|
||||
// roll
|
||||
angle = currententity->angles[ROLL];
|
||||
angle = angle * M_PI*2 / 360;
|
||||
s = sin(angle);
|
||||
c = cos(angle);
|
||||
|
||||
temp1[0][0] = 1;
|
||||
temp1[0][1] = 0;
|
||||
temp1[0][2] = 0;
|
||||
temp1[1][0] = 0;
|
||||
temp1[1][1] = c;
|
||||
temp1[1][2] = s;
|
||||
temp1[2][0] = 0;
|
||||
temp1[2][1] = -s;
|
||||
temp1[2][2] = c;
|
||||
|
||||
R_ConcatRotations (temp1, temp3, entity_rotation);
|
||||
|
||||
//
|
||||
// rotate modelorg and the transformation matrix
|
||||
//
|
||||
R_EntityRotate (modelorg);
|
||||
R_EntityRotate (vpn);
|
||||
R_EntityRotate (vright);
|
||||
R_EntityRotate (vup);
|
||||
|
||||
R_TransformFrustum ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RecursiveClipBPoly
|
||||
================
|
||||
*/
|
||||
void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
|
||||
{
|
||||
bedge_t *psideedges[2], *pnextedge, *ptedge;
|
||||
int i, side, lastside;
|
||||
float dist, frac, lastdist;
|
||||
mplane_t *splitplane, tplane;
|
||||
mvertex_t *pvert, *plastvert, *ptvert;
|
||||
mnode_t *pn;
|
||||
|
||||
psideedges[0] = psideedges[1] = NULL;
|
||||
|
||||
makeclippededge = false;
|
||||
|
||||
// transform the BSP plane into model space
|
||||
// FIXME: cache these?
|
||||
splitplane = pnode->plane;
|
||||
if (!splitplane)
|
||||
return;
|
||||
tplane.dist = splitplane->dist -
|
||||
DotProduct(r_entorigin, splitplane->normal);
|
||||
tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
|
||||
tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
|
||||
tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
|
||||
|
||||
// clip edges to BSP plane
|
||||
for ( ; pedges ; pedges = pnextedge)
|
||||
{
|
||||
pnextedge = pedges->pnext;
|
||||
|
||||
// set the status for the last point as the previous point
|
||||
// FIXME: cache this stuff somehow?
|
||||
plastvert = pedges->v[0];
|
||||
lastdist = DotProduct (plastvert->position, tplane.normal) -
|
||||
tplane.dist;
|
||||
|
||||
if (lastdist > 0)
|
||||
lastside = 0;
|
||||
else
|
||||
lastside = 1;
|
||||
|
||||
pvert = pedges->v[1];
|
||||
|
||||
dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
|
||||
|
||||
if (dist > 0)
|
||||
side = 0;
|
||||
else
|
||||
side = 1;
|
||||
|
||||
if (side != lastside)
|
||||
{
|
||||
// clipped
|
||||
if (numbverts >= MAX_BMODEL_VERTS)
|
||||
return;
|
||||
|
||||
// generate the clipped vertex
|
||||
frac = lastdist / (lastdist - dist);
|
||||
ptvert = &pbverts[numbverts++];
|
||||
ptvert->position[0] = plastvert->position[0] +
|
||||
frac * (pvert->position[0] -
|
||||
plastvert->position[0]);
|
||||
ptvert->position[1] = plastvert->position[1] +
|
||||
frac * (pvert->position[1] -
|
||||
plastvert->position[1]);
|
||||
ptvert->position[2] = plastvert->position[2] +
|
||||
frac * (pvert->position[2] -
|
||||
plastvert->position[2]);
|
||||
|
||||
// split into two edges, one on each side, and remember entering
|
||||
// and exiting points
|
||||
// FIXME: share the clip edge by having a winding direction flag?
|
||||
if (numbedges >= (MAX_BMODEL_EDGES - 1))
|
||||
{
|
||||
Con_Printf ("Out of edges for bmodel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptedge = &pbedges[numbedges];
|
||||
ptedge->pnext = psideedges[lastside];
|
||||
psideedges[lastside] = ptedge;
|
||||
ptedge->v[0] = plastvert;
|
||||
ptedge->v[1] = ptvert;
|
||||
|
||||
ptedge = &pbedges[numbedges + 1];
|
||||
ptedge->pnext = psideedges[side];
|
||||
psideedges[side] = ptedge;
|
||||
ptedge->v[0] = ptvert;
|
||||
ptedge->v[1] = pvert;
|
||||
|
||||
numbedges += 2;
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
// entering for front, exiting for back
|
||||
pfrontenter = ptvert;
|
||||
makeclippededge = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pfrontexit = ptvert;
|
||||
makeclippededge = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// add the edge to the appropriate side
|
||||
pedges->pnext = psideedges[side];
|
||||
psideedges[side] = pedges;
|
||||
}
|
||||
}
|
||||
|
||||
// if anything was clipped, reconstitute and add the edges along the clip
|
||||
// plane to both sides (but in opposite directions)
|
||||
if (makeclippededge)
|
||||
{
|
||||
if (numbedges >= (MAX_BMODEL_EDGES - 2))
|
||||
{
|
||||
Con_Printf ("Out of edges for bmodel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptedge = &pbedges[numbedges];
|
||||
ptedge->pnext = psideedges[0];
|
||||
psideedges[0] = ptedge;
|
||||
ptedge->v[0] = pfrontexit;
|
||||
ptedge->v[1] = pfrontenter;
|
||||
|
||||
ptedge = &pbedges[numbedges + 1];
|
||||
ptedge->pnext = psideedges[1];
|
||||
psideedges[1] = ptedge;
|
||||
ptedge->v[0] = pfrontenter;
|
||||
ptedge->v[1] = pfrontexit;
|
||||
|
||||
numbedges += 2;
|
||||
}
|
||||
|
||||
// draw or recurse further
|
||||
for (i=0 ; i<2 ; i++)
|
||||
{
|
||||
if (psideedges[i])
|
||||
{
|
||||
// draw if we've reached a non-solid leaf, done if all that's left is a
|
||||
// solid leaf, and continue down the tree if it's not a leaf
|
||||
pn = pnode->children[i];
|
||||
|
||||
// we're done with this branch if the node or leaf isn't in the PVS
|
||||
if (pn->visframe == r_visframecount)
|
||||
{
|
||||
if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
|
||||
{
|
||||
if (pn->contents != -1)
|
||||
{
|
||||
if (pn->contents != Q2CONTENTS_SOLID)
|
||||
{
|
||||
r_currentbkey = ((mleaf_t *)pn)->key;
|
||||
R_RenderBmodelFace (psideedges[i], psurf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
|
||||
psurf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pn->contents < 0)
|
||||
{
|
||||
if (pn->contents != Q1CONTENTS_SOLID)
|
||||
{
|
||||
r_currentbkey = ((mleaf_t *)pn)->key;
|
||||
R_RenderBmodelFace (psideedges[i], psurf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
|
||||
psurf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSolidClippedSubmodelPolygons
|
||||
================
|
||||
*/
|
||||
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel)
|
||||
{
|
||||
int i, j, lindex;
|
||||
vec_t dot;
|
||||
msurface_t *psurf;
|
||||
int numsurfaces;
|
||||
mplane_t *pplane;
|
||||
mvertex_t bverts[MAX_BMODEL_VERTS];
|
||||
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
|
||||
medge_t *pedge, *pedges;
|
||||
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
|
||||
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
|
||||
numsurfaces = pmodel->nummodelsurfaces;
|
||||
pedges = pmodel->edges;
|
||||
|
||||
for (i=0 ; i<numsurfaces ; i++, psurf++)
|
||||
{
|
||||
// find which side of the node we are on
|
||||
pplane = psurf->plane;
|
||||
|
||||
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
|
||||
|
||||
// draw the polygon
|
||||
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
|
||||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
|
||||
{
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
|
||||
// copy the edges to bedges, flipping if necessary so always
|
||||
// clockwise winding
|
||||
// FIXME: if edges and vertices get caches, these assignments must move
|
||||
// outside the loop, and overflow checking must be done here
|
||||
pbverts = bverts;
|
||||
pbedges = bedges;
|
||||
numbverts = numbedges = 0;
|
||||
|
||||
if (psurf->numedges > 0)
|
||||
{
|
||||
pbedge = &bedges[numbedges];
|
||||
numbedges += psurf->numedges;
|
||||
|
||||
for (j=0 ; j<psurf->numedges ; j++)
|
||||
{
|
||||
lindex = pmodel->surfedges[psurf->firstedge+j];
|
||||
|
||||
if (lindex > 0)
|
||||
{
|
||||
pedge = &pedges[lindex];
|
||||
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
|
||||
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
lindex = -lindex;
|
||||
pedge = &pedges[lindex];
|
||||
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
|
||||
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
|
||||
}
|
||||
|
||||
pbedge[j].pnext = &pbedge[j+1];
|
||||
}
|
||||
|
||||
pbedge[j-1].pnext = NULL; // mark end of edges
|
||||
|
||||
R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys_Error ("no edges in bmodel");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSubmodelPolygons
|
||||
================
|
||||
*/
|
||||
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags)
|
||||
{
|
||||
int i;
|
||||
vec_t dot;
|
||||
msurface_t *psurf;
|
||||
int numsurfaces;
|
||||
mplane_t *pplane;
|
||||
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
|
||||
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
|
||||
numsurfaces = pmodel->nummodelsurfaces;
|
||||
|
||||
for (i=0 ; i<numsurfaces ; i++, psurf++)
|
||||
{
|
||||
// find which side of the node we are on
|
||||
pplane = psurf->plane;
|
||||
|
||||
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
|
||||
|
||||
// draw the polygon
|
||||
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
|
||||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
|
||||
{
|
||||
r_currentkey = ((mleaf_t *)currententity->topnode)->key;
|
||||
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
R_RenderFace (psurf, clipflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RecursiveWorldNode
|
||||
================
|
||||
*/
|
||||
void SWR_RecursiveWorldNode (mnode_t *node, int clipflags)
|
||||
{
|
||||
int i, c, side, *pindex;
|
||||
vec3_t acceptpt, rejectpt;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf, **mark;
|
||||
mleaf_t *pleaf;
|
||||
double d, dot;
|
||||
|
||||
if (node->contents == Q1CONTENTS_SOLID)
|
||||
return; // solid
|
||||
|
||||
if (node->visframe != r_visframecount)
|
||||
return;
|
||||
|
||||
// cull the clipping planes if not trivial accept
|
||||
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
|
||||
// twice as fast in ASM
|
||||
if (clipflags)
|
||||
{
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
if (! (clipflags & (1<<i)) )
|
||||
continue; // don't need to clip against it
|
||||
|
||||
// generate accept and reject points
|
||||
// FIXME: do with fast look-ups or integer tests based on the sign bit
|
||||
// of the floating point values
|
||||
|
||||
pindex = pfrustum_indexes[i];
|
||||
|
||||
rejectpt[0] = (float)node->minmaxs[pindex[0]];
|
||||
rejectpt[1] = (float)node->minmaxs[pindex[1]];
|
||||
rejectpt[2] = (float)node->minmaxs[pindex[2]];
|
||||
|
||||
d = DotProduct (rejectpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
||||
if (d <= 0)
|
||||
return;
|
||||
|
||||
acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
|
||||
acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
|
||||
acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
|
||||
|
||||
d = DotProduct (acceptpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
||||
if (d >= 0)
|
||||
clipflags &= ~(1<<i); // node is entirely on screen
|
||||
}
|
||||
}
|
||||
|
||||
// if a leaf node, draw stuff
|
||||
if (node->contents < 0)
|
||||
{
|
||||
pleaf = (mleaf_t *)node;
|
||||
|
||||
mark = pleaf->firstmarksurface;
|
||||
c = pleaf->nummarksurfaces;
|
||||
|
||||
if (c)
|
||||
{
|
||||
do
|
||||
{
|
||||
(*mark)->visframe = r_framecount;
|
||||
mark++;
|
||||
} while (--c);
|
||||
}
|
||||
|
||||
// deal with model fragments in this leaf
|
||||
if (pleaf->efrags)
|
||||
{
|
||||
R_StoreEfrags (&pleaf->efrags);
|
||||
}
|
||||
|
||||
pleaf->key = r_currentkey;
|
||||
r_currentkey++; // all bmodels in a leaf share the same key
|
||||
}
|
||||
else
|
||||
{
|
||||
// node is just a decision point, so go down the apropriate sides
|
||||
|
||||
// find which side of the node we are on
|
||||
plane = node->plane;
|
||||
|
||||
switch (plane->type)
|
||||
{
|
||||
case PLANE_X:
|
||||
dot = modelorg[0] - plane->dist;
|
||||
break;
|
||||
case PLANE_Y:
|
||||
dot = modelorg[1] - plane->dist;
|
||||
break;
|
||||
case PLANE_Z:
|
||||
dot = modelorg[2] - plane->dist;
|
||||
break;
|
||||
default:
|
||||
dot = DotProduct (modelorg, plane->normal) - plane->dist;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dot >= 0)
|
||||
side = 0;
|
||||
else
|
||||
side = 1;
|
||||
|
||||
// recurse down the children, front side first
|
||||
SWR_RecursiveWorldNode (node->children[side], clipflags);
|
||||
|
||||
// draw stuff
|
||||
c = node->numsurfaces;
|
||||
|
||||
if (c)
|
||||
{
|
||||
surf = cl.worldmodel->surfaces + node->firstsurface;
|
||||
|
||||
if (dot < -BACKFACE_EPSILON)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((surf->flags & SURF_PLANEBACK) &&
|
||||
(surf->visframe == r_framecount))
|
||||
{
|
||||
if (r_drawpolys)
|
||||
{
|
||||
if (r_worldpolysbacktofront)
|
||||
{
|
||||
if (numbtofpolys < MAX_BTOFPOLYS)
|
||||
{
|
||||
pbtofpolys[numbtofpolys].clipflags =
|
||||
clipflags;
|
||||
pbtofpolys[numbtofpolys].psurf = surf;
|
||||
numbtofpolys++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RenderPoly (surf, clipflags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
surf++;
|
||||
} while (--c);
|
||||
}
|
||||
else if (dot > BACKFACE_EPSILON)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!(surf->flags & SURF_PLANEBACK) &&
|
||||
(surf->visframe == r_framecount))
|
||||
{
|
||||
if (r_drawpolys)
|
||||
{
|
||||
if (r_worldpolysbacktofront)
|
||||
{
|
||||
if (numbtofpolys < MAX_BTOFPOLYS)
|
||||
{
|
||||
pbtofpolys[numbtofpolys].clipflags =
|
||||
clipflags;
|
||||
pbtofpolys[numbtofpolys].psurf = surf;
|
||||
numbtofpolys++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RenderPoly (surf, clipflags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
surf++;
|
||||
} while (--c);
|
||||
}
|
||||
|
||||
// all surfaces on the same node share the same sequence number
|
||||
r_currentkey++;
|
||||
}
|
||||
|
||||
// recurse down the back side
|
||||
SWR_RecursiveWorldNode (node->children[!side], clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
qbyte areabits[MAX_Q2MAP_AREAS/8];
|
||||
void SWR_RecursiveQ2WorldNode (mnode_t *node, int clipflags)
|
||||
{
|
||||
int i, c, side, *pindex;
|
||||
vec3_t acceptpt, rejectpt;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf, **mark;
|
||||
mleaf_t *pleaf;
|
||||
double d, dot;
|
||||
|
||||
if (node->contents == Q2CONTENTS_SOLID)
|
||||
return; // solid
|
||||
|
||||
if (node->visframe != r_visframecount)
|
||||
return;
|
||||
|
||||
// cull the clipping planes if not trivial accept
|
||||
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
|
||||
// twice as fast in ASM
|
||||
if (clipflags)
|
||||
{
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
if (! (clipflags & (1<<i)) )
|
||||
continue; // don't need to clip against it
|
||||
|
||||
// generate accept and reject points
|
||||
// FIXME: do with fast look-ups or integer tests based on the sign bit
|
||||
// of the floating point values
|
||||
|
||||
pindex = pfrustum_indexes[i];
|
||||
|
||||
rejectpt[0] = (float)node->minmaxs[pindex[0]];
|
||||
rejectpt[1] = (float)node->minmaxs[pindex[1]];
|
||||
rejectpt[2] = (float)node->minmaxs[pindex[2]];
|
||||
|
||||
d = DotProduct (rejectpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
||||
if (d <= 0)
|
||||
return;
|
||||
|
||||
acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
|
||||
acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
|
||||
acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
|
||||
|
||||
d = DotProduct (acceptpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
||||
if (d >= 0)
|
||||
clipflags &= ~(1<<i); // node is entirely on screen
|
||||
}
|
||||
}
|
||||
|
||||
// if a leaf node, draw stuff
|
||||
if (node->contents != -1)
|
||||
{
|
||||
pleaf = (mleaf_t *)node;
|
||||
|
||||
// check for door connected areas
|
||||
// if (areabits)
|
||||
// {
|
||||
if (! (areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
|
||||
return; // not visible
|
||||
// }
|
||||
|
||||
mark = pleaf->firstmarksurface;
|
||||
c = pleaf->nummarksurfaces;
|
||||
|
||||
if (c)
|
||||
{
|
||||
do
|
||||
{
|
||||
(*mark)->visframe = r_framecount;
|
||||
mark++;
|
||||
} while (--c);
|
||||
}
|
||||
|
||||
pleaf->key = r_currentkey;
|
||||
r_currentkey++; // all bmodels in a leaf share the same key
|
||||
}
|
||||
else
|
||||
{
|
||||
// node is just a decision point, so go down the apropriate sides
|
||||
|
||||
// find which side of the node we are on
|
||||
plane = node->plane;
|
||||
|
||||
switch (plane->type)
|
||||
{
|
||||
case PLANE_X:
|
||||
dot = modelorg[0] - plane->dist;
|
||||
break;
|
||||
case PLANE_Y:
|
||||
dot = modelorg[1] - plane->dist;
|
||||
break;
|
||||
case PLANE_Z:
|
||||
dot = modelorg[2] - plane->dist;
|
||||
break;
|
||||
default:
|
||||
dot = DotProduct (modelorg, plane->normal) - plane->dist;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dot >= 0)
|
||||
side = 0;
|
||||
else
|
||||
side = 1;
|
||||
|
||||
// recurse down the children, front side first
|
||||
SWR_RecursiveQ2WorldNode (node->children[side], clipflags);
|
||||
|
||||
// draw stuff
|
||||
c = node->numsurfaces;
|
||||
|
||||
if (c)
|
||||
{
|
||||
surf = cl.worldmodel->surfaces + node->firstsurface;
|
||||
|
||||
if (dot < -BACKFACE_EPSILON)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((surf->flags & SURF_PLANEBACK) &&
|
||||
(surf->visframe == r_framecount))
|
||||
{
|
||||
if (r_drawpolys)
|
||||
{
|
||||
if (r_worldpolysbacktofront)
|
||||
{
|
||||
if (numbtofpolys < MAX_BTOFPOLYS)
|
||||
{
|
||||
pbtofpolys[numbtofpolys].clipflags =
|
||||
clipflags;
|
||||
pbtofpolys[numbtofpolys].psurf = surf;
|
||||
numbtofpolys++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RenderPoly (surf, clipflags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
surf++;
|
||||
} while (--c);
|
||||
}
|
||||
else if (dot > BACKFACE_EPSILON)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!(surf->flags & SURF_PLANEBACK) &&
|
||||
(surf->visframe == r_framecount))
|
||||
{
|
||||
if (r_drawpolys)
|
||||
{
|
||||
if (r_worldpolysbacktofront)
|
||||
{
|
||||
if (numbtofpolys < MAX_BTOFPOLYS)
|
||||
{
|
||||
pbtofpolys[numbtofpolys].clipflags =
|
||||
clipflags;
|
||||
pbtofpolys[numbtofpolys].psurf = surf;
|
||||
numbtofpolys++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RenderPoly (surf, clipflags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
surf++;
|
||||
} while (--c);
|
||||
}
|
||||
|
||||
// all surfaces on the same node share the same sequence number
|
||||
r_currentkey++;
|
||||
}
|
||||
|
||||
// recurse down the back side
|
||||
SWR_RecursiveQ2WorldNode (node->children[!side], clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderWorld
|
||||
================
|
||||
*/
|
||||
void R_RenderWorld (void)
|
||||
{
|
||||
int i;
|
||||
model_t *clmodel;
|
||||
btofpoly_t btofpolys[MAX_BTOFPOLYS];
|
||||
|
||||
pbtofpolys = btofpolys;
|
||||
|
||||
currententity = &r_worldentity;
|
||||
VectorCopy (r_origin, modelorg);
|
||||
clmodel = currententity->model;
|
||||
r_pcurrentvertbase = clmodel->vertexes;
|
||||
|
||||
if (clmodel->fromgame == fg_quake2)
|
||||
{
|
||||
int leafnum;
|
||||
int clientarea;
|
||||
int CM_WriteAreaBits (qbyte *buffer, int area);
|
||||
if (cls.q2server)
|
||||
memcpy(areabits, cl.q2frame.areabits, sizeof(areabits));
|
||||
else
|
||||
{
|
||||
leafnum = CM_PointLeafnum (r_refdef.vieworg);
|
||||
clientarea = CM_LeafArea (leafnum);
|
||||
CM_WriteAreaBits(areabits, clientarea);
|
||||
}
|
||||
|
||||
SWR_RecursiveQ2WorldNode (clmodel->nodes, 15);
|
||||
}
|
||||
else
|
||||
SWR_RecursiveWorldNode (clmodel->nodes, 15);
|
||||
|
||||
// if the driver wants the polygons back to front, play the visible ones back
|
||||
// in that order
|
||||
|
||||
if (r_worldpolysbacktofront)
|
||||
{
|
||||
for (i=numbtofpolys-1 ; i>=0 ; i--)
|
||||
{
|
||||
R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
2696
engine/sw/r_draw.c
Normal file
2696
engine/sw/r_draw.c
Normal file
File diff suppressed because it is too large
Load diff
838
engine/sw/r_drawa.s
Normal file
838
engine/sw/r_drawa.s
Normal 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
|
||||
|
931
engine/sw/r_edge.c
Normal file
931
engine/sw/r_edge.c
Normal file
|
@ -0,0 +1,931 @@
|
|||
/*
|
||||
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_edge.c
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "r_local.h"
|
||||
|
||||
#if 0
|
||||
// FIXME
|
||||
the complex cases add new polys on most lines, so dont optimize for keeping them the same
|
||||
have multiple free span lists to try to get better coherence?
|
||||
low depth complexity -- 1 to 3 or so
|
||||
|
||||
this breaks spans at every edge, even hidden ones (bad)
|
||||
|
||||
have a sentinal at both ends?
|
||||
#endif
|
||||
|
||||
|
||||
edge_t *auxedges;
|
||||
edge_t *r_edges, *edge_p, *edge_max;
|
||||
|
||||
surf_t *surfaces, *surface_p, *surf_max;
|
||||
|
||||
// surfaces are generated in back to front order by the bsp, so if a surf
|
||||
// pointer is greater than another one, it should be drawn in front
|
||||
// surfaces[1] is the background, and is used as the active surface stack
|
||||
|
||||
edge_t *newedges[MAXHEIGHT];
|
||||
edge_t *removeedges[MAXHEIGHT];
|
||||
|
||||
espan_t *span_p, *max_span_p;
|
||||
|
||||
int r_currentkey;
|
||||
|
||||
extern int screenwidth;
|
||||
|
||||
int current_iv;
|
||||
|
||||
int edge_head_u_shift20, edge_tail_u_shift20;
|
||||
|
||||
static void (*pdrawfunc)(void);
|
||||
|
||||
edge_t edge_head;
|
||||
edge_t edge_tail;
|
||||
edge_t edge_aftertail;
|
||||
edge_t edge_sentinel;
|
||||
|
||||
float fv;
|
||||
|
||||
void R_GenerateSpans (void);
|
||||
void R_GenerateSpansTrans (void);
|
||||
void R_GenerateSpansBackward (void);
|
||||
|
||||
void R_LeadingEdge (edge_t *edge);
|
||||
void R_LeadingEdgeBackwards (edge_t *edge);
|
||||
void R_TrailingEdge (surf_t *surf, edge_t *edge);
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
R_DrawCulledPolys
|
||||
==============
|
||||
*/
|
||||
void R_DrawCulledPolys (void)
|
||||
{
|
||||
surf_t *s;
|
||||
msurface_t *pface;
|
||||
|
||||
currententity = &r_worldentity;
|
||||
|
||||
if (r_worldpolysbacktofront)
|
||||
{
|
||||
for (s=surface_p-1 ; s>&surfaces[1] ; s--)
|
||||
{
|
||||
if (!s->spans)
|
||||
continue;
|
||||
|
||||
if (!(s->flags & SURF_DRAWBACKGROUND))
|
||||
{
|
||||
pface = (msurface_t *)s->data;
|
||||
R_RenderPoly (pface, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (s = &surfaces[1] ; s<surface_p ; s++)
|
||||
{
|
||||
if (!s->spans)
|
||||
continue;
|
||||
|
||||
if (!(s->flags & SURF_DRAWBACKGROUND))
|
||||
{
|
||||
pface = (msurface_t *)s->data;
|
||||
R_RenderPoly (pface, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
R_BeginEdgeFrame
|
||||
==============
|
||||
*/
|
||||
void R_BeginEdgeFrame (void)
|
||||
{
|
||||
int v;
|
||||
|
||||
edge_p = r_edges;
|
||||
edge_max = &r_edges[r_numallocatededges];
|
||||
|
||||
surface_p = &surfaces[2]; // background is surface 1,
|
||||
// surface 0 is a dummy
|
||||
surfaces[1].spans = NULL; // no background spans yet
|
||||
surfaces[1].flags = SURF_DRAWBACKGROUND;
|
||||
|
||||
// put the background behind everything in the world
|
||||
if (r_draworder.value)
|
||||
{
|
||||
pdrawfunc = R_GenerateSpansBackward;
|
||||
surfaces[1].key = 0;
|
||||
r_currentkey = 1;
|
||||
}
|
||||
else if (cl.worldmodel->fromgame == fg_halflife)
|
||||
{
|
||||
pdrawfunc = R_GenerateSpansTrans;
|
||||
surfaces[1].key = 0x7FFFFFFF;
|
||||
r_currentkey = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdrawfunc = R_GenerateSpans;
|
||||
surfaces[1].key = 0x7FFFFFFF;
|
||||
r_currentkey = 0;
|
||||
}
|
||||
|
||||
// FIXME: set with memset
|
||||
for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++)
|
||||
{
|
||||
newedges[v] = removeedges[v] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
==============
|
||||
R_InsertNewEdges
|
||||
|
||||
Adds the edges in the linked list edgestoadd, adding them to the edges in the
|
||||
linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]). edgelist is assumed to be sorted on u, with a
|
||||
sentinel at the end (actually, this is the active edge table starting at
|
||||
edge_head.next).
|
||||
==============
|
||||
*/
|
||||
void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
|
||||
{
|
||||
edge_t *next_edge;
|
||||
|
||||
do
|
||||
{
|
||||
next_edge = edgestoadd->next;
|
||||
edgesearch:
|
||||
if (edgelist->u >= edgestoadd->u)
|
||||
goto addedge;
|
||||
edgelist=edgelist->next;
|
||||
if (edgelist->u >= edgestoadd->u)
|
||||
goto addedge;
|
||||
edgelist=edgelist->next;
|
||||
if (edgelist->u >= edgestoadd->u)
|
||||
goto addedge;
|
||||
edgelist=edgelist->next;
|
||||
if (edgelist->u >= edgestoadd->u)
|
||||
goto addedge;
|
||||
edgelist=edgelist->next;
|
||||
goto edgesearch;
|
||||
|
||||
// insert edgestoadd before edgelist
|
||||
addedge:
|
||||
edgestoadd->next = edgelist;
|
||||
edgestoadd->prev = edgelist->prev;
|
||||
edgelist->prev->next = edgestoadd;
|
||||
edgelist->prev = edgestoadd;
|
||||
} while ((edgestoadd = next_edge) != NULL);
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
==============
|
||||
R_RemoveEdges
|
||||
==============
|
||||
*/
|
||||
void R_RemoveEdges (edge_t *pedge)
|
||||
{
|
||||
|
||||
do
|
||||
{
|
||||
pedge->next->prev = pedge->prev;
|
||||
pedge->prev->next = pedge->next;
|
||||
} while ((pedge = pedge->nextremove) != NULL);
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
==============
|
||||
R_StepActiveU
|
||||
==============
|
||||
*/
|
||||
void R_StepActiveU (edge_t *pedge)
|
||||
{
|
||||
edge_t *pnext_edge, *pwedge;
|
||||
|
||||
while (1)
|
||||
{
|
||||
nextedge:
|
||||
pedge->u += pedge->u_step;
|
||||
if (pedge->u < pedge->prev->u)
|
||||
goto pushback;
|
||||
pedge = pedge->next;
|
||||
|
||||
pedge->u += pedge->u_step;
|
||||
if (pedge->u < pedge->prev->u)
|
||||
goto pushback;
|
||||
pedge = pedge->next;
|
||||
|
||||
pedge->u += pedge->u_step;
|
||||
if (pedge->u < pedge->prev->u)
|
||||
goto pushback;
|
||||
pedge = pedge->next;
|
||||
|
||||
pedge->u += pedge->u_step;
|
||||
if (pedge->u < pedge->prev->u)
|
||||
goto pushback;
|
||||
pedge = pedge->next;
|
||||
|
||||
goto nextedge;
|
||||
|
||||
pushback:
|
||||
if (pedge == &edge_aftertail)
|
||||
return;
|
||||
|
||||
// push it back to keep it sorted
|
||||
pnext_edge = pedge->next;
|
||||
|
||||
// pull the edge out of the edge list
|
||||
pedge->next->prev = pedge->prev;
|
||||
pedge->prev->next = pedge->next;
|
||||
|
||||
// find out where the edge goes in the edge list
|
||||
pwedge = pedge->prev->prev;
|
||||
|
||||
while (pwedge->u > pedge->u)
|
||||
{
|
||||
pwedge = pwedge->prev;
|
||||
}
|
||||
|
||||
// put the edge back into the edge list
|
||||
pedge->next = pwedge->next;
|
||||
pedge->prev = pwedge;
|
||||
pedge->next->prev = pedge;
|
||||
pwedge->next = pedge;
|
||||
|
||||
pedge = pnext_edge;
|
||||
if (pedge == &edge_tail)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
R_CleanupSpan
|
||||
==============
|
||||
*/
|
||||
void R_CleanupSpan (void)
|
||||
{
|
||||
surf_t *surf;
|
||||
int iu;
|
||||
espan_t *span;
|
||||
|
||||
// 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
|
||||
surf = surfaces[1].next;
|
||||
iu = edge_tail_u_shift20;
|
||||
if (iu > surf->last_u)
|
||||
{
|
||||
span = span_p++;
|
||||
span->u = surf->last_u;
|
||||
span->count = iu - span->u;
|
||||
span->v = current_iv;
|
||||
span->pnext = surf->spans;
|
||||
surf->spans = span;
|
||||
}
|
||||
|
||||
// reset spanstate for all surfaces in the surface stack
|
||||
do
|
||||
{
|
||||
surf->spanstate = 0;
|
||||
surf = surf->next;
|
||||
} while (surf != &surfaces[1]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
R_LeadingEdgeBackwards
|
||||
==============
|
||||
*/
|
||||
void R_LeadingEdgeBackwards (edge_t *edge)
|
||||
{
|
||||
espan_t *span;
|
||||
surf_t *surf, *surf2;
|
||||
int iu;
|
||||
|
||||
// it's adding a new surface in, so find the correct place
|
||||
surf = &surfaces[edge->surfs[1]];
|
||||
|
||||
// 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)
|
||||
if (++surf->spanstate == 1)
|
||||
{
|
||||
surf2 = surfaces[1].next;
|
||||
|
||||
if (surf->key > surf2->key)
|
||||
goto newtop;
|
||||
|
||||
// if it's two surfaces on the same plane, the one that's already
|
||||
// active is in front, so keep going unless it's a bmodel
|
||||
if (surf->insubmodel && (surf->key == surf2->key))
|
||||
{
|
||||
// must be two bmodels in the same leaf; don't care, because they'll
|
||||
// never be farthest anyway
|
||||
goto newtop;
|
||||
}
|
||||
|
||||
continue_search:
|
||||
|
||||
do
|
||||
{
|
||||
surf2 = surf2->next;
|
||||
} while (surf->key < surf2->key);
|
||||
|
||||
if (surf->key == surf2->key)
|
||||
{
|
||||
// if it's two surfaces on the same plane, the one that's already
|
||||
// active is in front, so keep going unless it's a bmodel
|
||||
if (!surf->insubmodel)
|
||||
goto continue_search;
|
||||
|
||||
// must be two bmodels in the same leaf; don't care which is really
|
||||
// in front, because they'll never be farthest anyway
|
||||
}
|
||||
|
||||
goto gotposition;
|
||||
|
||||
newtop:
|
||||
// emit a span (obscures current top)
|
||||
iu = edge->u >> 20;
|
||||
|
||||
if (iu > surf2->last_u)
|
||||
{
|
||||
span = span_p++;
|
||||
span->u = surf2->last_u;
|
||||
span->count = iu - span->u;
|
||||
span->v = current_iv;
|
||||
span->pnext = surf2->spans;
|
||||
surf2->spans = span;
|
||||
}
|
||||
|
||||
// set last_u on the new span
|
||||
surf->last_u = iu;
|
||||
|
||||
gotposition:
|
||||
// insert before surf2
|
||||
surf->next = surf2;
|
||||
surf->prev = surf2->prev;
|
||||
surf2->prev->next = surf;
|
||||
surf2->prev = surf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
R_TrailingEdge
|
||||
==============
|
||||
*/
|
||||
void R_TrailingEdge (surf_t *surf, edge_t *edge)
|
||||
{
|
||||
espan_t *span;
|
||||
int iu;
|
||||
|
||||
// don't generate a span if this is an inverted span, with the end
|
||||
// edge preceding the start edge (that is, we haven't seen the
|
||||
// start edge yet)
|
||||
if (--surf->spanstate == 0)
|
||||
{
|
||||
if (surf->insubmodel)
|
||||
r_bmodelactive--;
|
||||
|
||||
if (surf == surfaces[1].next)
|
||||
{
|
||||
// emit a span (current top going away)
|
||||
iu = edge->u >> 20;
|
||||
if (iu > surf->last_u)
|
||||
{
|
||||
span = span_p++;
|
||||
span->u = surf->last_u;
|
||||
span->count = iu - span->u;
|
||||
span->v = current_iv;
|
||||
span->pnext = surf->spans;
|
||||
surf->spans = span;
|
||||
}
|
||||
|
||||
// set last_u on the surface below
|
||||
surf->next->last_u = iu;
|
||||
}
|
||||
|
||||
surf->prev->next = surf->next;
|
||||
surf->next->prev = surf->prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
==============
|
||||
R_LeadingEdge
|
||||
==============
|
||||
*/
|
||||
void R_LeadingEdge (edge_t *edge)
|
||||
{
|
||||
espan_t *span;
|
||||
surf_t *surf, *surf2;
|
||||
int iu;
|
||||
double fu, newzi, testzi, newzitop, newzibottom;
|
||||
|
||||
if (edge->surfs[1])
|
||||
{
|
||||
// it's adding a new surface in, so find the correct place
|
||||
surf = &surfaces[edge->surfs[1]];
|
||||
|
||||
// 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)
|
||||
if (++surf->spanstate == 1)
|
||||
{
|
||||
if (surf->insubmodel)
|
||||
r_bmodelactive++;
|
||||
|
||||
surf2 = surfaces[1].next;
|
||||
|
||||
if (surf->key < surf2->key)
|
||||
goto newtop;
|
||||
|
||||
// if it's two surfaces on the same plane, the one that's already
|
||||
// active is in front, so keep going unless it's a bmodel
|
||||
if (surf->insubmodel && (surf->key == surf2->key))
|
||||
{
|
||||
// must be two bmodels in the same leaf; sort on 1/z
|
||||
fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
|
||||
newzi = surf->d_ziorigin + fv*surf->d_zistepv +
|
||||
fu*surf->d_zistepu;
|
||||
newzibottom = newzi * 0.99;
|
||||
|
||||
testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
|
||||
fu*surf2->d_zistepu;
|
||||
|
||||
if (newzibottom >= testzi)
|
||||
{
|
||||
goto newtop;
|
||||
}
|
||||
|
||||
newzitop = newzi * 1.01;
|
||||
if (newzitop >= testzi)
|
||||
{
|
||||
if (surf->d_zistepu >= surf2->d_zistepu)
|
||||
{
|
||||
goto newtop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue_search:
|
||||
|
||||
do
|
||||
{
|
||||
surf2 = surf2->next;
|
||||
} while (surf->key > surf2->key);
|
||||
|
||||
if (surf->key == surf2->key)
|
||||
{
|
||||
// if it's two surfaces on the same plane, the one that's already
|
||||
// active is in front, so keep going unless it's a bmodel
|
||||
if (!surf->insubmodel)
|
||||
goto continue_search;
|
||||
|
||||
// must be two bmodels in the same leaf; sort on 1/z
|
||||
fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
|
||||
newzi = surf->d_ziorigin + fv*surf->d_zistepv +
|
||||
fu*surf->d_zistepu;
|
||||
newzibottom = newzi * 0.99;
|
||||
|
||||
testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
|
||||
fu*surf2->d_zistepu;
|
||||
|
||||
if (newzibottom >= testzi)
|
||||
{
|
||||
goto gotposition;
|
||||
}
|
||||
|
||||
newzitop = newzi * 1.01;
|
||||
if (newzitop >= testzi)
|
||||
{
|
||||
if (surf->d_zistepu >= surf2->d_zistepu)
|
||||
{
|
||||
goto gotposition;
|
||||
}
|
||||
}
|
||||
|
||||
goto continue_search;
|
||||
}
|
||||
|
||||
goto gotposition;
|
||||
|
||||
newtop:
|
||||
// emit a span (obscures current top)
|
||||
iu = edge->u >> 20;
|
||||
|
||||
if (iu > surf2->last_u)
|
||||
{
|
||||
span = span_p++;
|
||||
span->u = surf2->last_u;
|
||||
span->count = iu - span->u;
|
||||
span->v = current_iv;
|
||||
span->pnext = surf2->spans;
|
||||
surf2->spans = span;
|
||||
}
|
||||
|
||||
// set last_u on the new span
|
||||
surf->last_u = iu;
|
||||
|
||||
gotposition:
|
||||
// insert before surf2
|
||||
surf->next = surf2;
|
||||
surf->prev = surf2->prev;
|
||||
surf2->prev->next = surf;
|
||||
surf2->prev = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
R_GenerateSpans
|
||||
==============
|
||||
*/
|
||||
void R_GenerateSpans (void)
|
||||
{
|
||||
edge_t *edge;
|
||||
surf_t *surf;
|
||||
|
||||
r_bmodelactive = 0;
|
||||
|
||||
// clear active surfaces to just the background surface
|
||||
surfaces[1].next = surfaces[1].prev = &surfaces[1];
|
||||
surfaces[1].last_u = edge_head_u_shift20;
|
||||
|
||||
// generate spans
|
||||
for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
|
||||
{
|
||||
if (edge->surfs[0])
|
||||
{
|
||||
// it has a left surface, so a surface is going away for this span
|
||||
surf = &surfaces[edge->surfs[0]];
|
||||
|
||||
R_TrailingEdge (surf, edge);
|
||||
|
||||
if (!edge->surfs[1])
|
||||
continue;
|
||||
}
|
||||
|
||||
R_LeadingEdge (edge);
|
||||
}
|
||||
|
||||
R_CleanupSpan ();
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
void R_LeadingTransEdge (edge_t *edge)
|
||||
{
|
||||
espan_t *span;
|
||||
surf_t *surf, *surf2;
|
||||
int iu;
|
||||
double fu, newzi, testzi, newzitop, newzibottom;
|
||||
|
||||
if (edge->surfs[1])
|
||||
{
|
||||
// it's adding a new surface in, so find the correct place
|
||||
surf = &surfaces[edge->surfs[1]];
|
||||
|
||||
// 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)
|
||||
if (++surf->spanstate == 1)
|
||||
{
|
||||
if (surf->insubmodel)
|
||||
r_bmodelactive++;
|
||||
|
||||
surf2 = surfaces[1].next;
|
||||
|
||||
if (surf->key < surf2->key)
|
||||
goto newtop;
|
||||
|
||||
// if it's two surfaces on the same plane, the one that's already
|
||||
// active is in front, so keep going unless it's a bmodel
|
||||
if (surf->insubmodel && (surf->key == surf2->key))
|
||||
{
|
||||
// must be two bmodels in the same leaf; sort on 1/z
|
||||
fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
|
||||
newzi = surf->d_ziorigin + fv*surf->d_zistepv +
|
||||
fu*surf->d_zistepu;
|
||||
newzibottom = newzi * 0.99;
|
||||
|
||||
testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
|
||||
fu*surf2->d_zistepu;
|
||||
|
||||
if (newzibottom >= testzi)
|
||||
{
|
||||
goto newtop;
|
||||
}
|
||||
|
||||
newzitop = newzi * 1.01;
|
||||
if (newzitop >= testzi)
|
||||
{
|
||||
if (surf->d_zistepu >= surf2->d_zistepu)
|
||||
{
|
||||
goto newtop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue_search:
|
||||
|
||||
do
|
||||
{
|
||||
surf2 = surf2->next;
|
||||
} while (surf->key > surf2->key);
|
||||
|
||||
if (surf->key == surf2->key)
|
||||
{
|
||||
// if it's two surfaces on the same plane, the one that's already
|
||||
// active is in front, so keep going unless it's a bmodel
|
||||
if (!surf->insubmodel)
|
||||
goto continue_search;
|
||||
|
||||
// must be two bmodels in the same leaf; sort on 1/z
|
||||
fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
|
||||
newzi = surf->d_ziorigin + fv*surf->d_zistepv +
|
||||
fu*surf->d_zistepu;
|
||||
newzibottom = newzi * 0.99;
|
||||
|
||||
testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
|
||||
fu*surf2->d_zistepu;
|
||||
|
||||
if (newzibottom >= testzi)
|
||||
{
|
||||
goto gotposition;
|
||||
}
|
||||
|
||||
newzitop = newzi * 1.01;
|
||||
if (newzitop >= testzi)
|
||||
{
|
||||
if (surf->d_zistepu >= surf2->d_zistepu)
|
||||
{
|
||||
goto gotposition;
|
||||
}
|
||||
}
|
||||
|
||||
goto continue_search;
|
||||
}
|
||||
|
||||
goto gotposition;
|
||||
|
||||
newtop:
|
||||
// emit a span (obscures current top)
|
||||
iu = edge->u >> 20;
|
||||
|
||||
if (iu > surf2->last_u)
|
||||
{
|
||||
span = span_p++;
|
||||
span->u = surf2->last_u;
|
||||
span->count = iu - span->u;
|
||||
span->v = current_iv;
|
||||
span->pnext = surf2->spans;
|
||||
surf2->spans = span;
|
||||
}
|
||||
|
||||
// set last_u on the new span
|
||||
surf->last_u = iu;
|
||||
|
||||
gotposition:
|
||||
// insert before surf2
|
||||
surf->next = surf2;
|
||||
surf->prev = surf2->prev;
|
||||
surf2->prev->next = surf;
|
||||
surf2->prev = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_GenerateSpansTrans (void)
|
||||
{
|
||||
edge_t *edge;
|
||||
surf_t *surf;
|
||||
|
||||
r_bmodelactive = 0;
|
||||
|
||||
// clear active surfaces to just the background surface
|
||||
surfaces[1].next = surfaces[1].prev = &surfaces[1];
|
||||
surfaces[1].last_u = edge_head_u_shift20;
|
||||
|
||||
// generate spans
|
||||
for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
|
||||
{
|
||||
if (edge->surfs[0])
|
||||
{
|
||||
// it has a left surface, so a surface is going away for this span
|
||||
surf = &surfaces[edge->surfs[0]];
|
||||
|
||||
R_TrailingEdge (surf, edge);
|
||||
|
||||
if (!edge->surfs[1])
|
||||
continue;
|
||||
}
|
||||
|
||||
R_LeadingTransEdge (edge);
|
||||
}
|
||||
|
||||
R_CleanupSpan ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
R_GenerateSpansBackward
|
||||
==============
|
||||
*/
|
||||
void R_GenerateSpansBackward (void)
|
||||
{
|
||||
edge_t *edge;
|
||||
|
||||
r_bmodelactive = 0;
|
||||
|
||||
// clear active surfaces to just the background surface
|
||||
surfaces[1].next = surfaces[1].prev = &surfaces[1];
|
||||
surfaces[1].last_u = edge_head_u_shift20;
|
||||
|
||||
// generate spans
|
||||
for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
|
||||
{
|
||||
if (edge->surfs[0])
|
||||
R_TrailingEdge (&surfaces[edge->surfs[0]], edge);
|
||||
|
||||
if (edge->surfs[1])
|
||||
R_LeadingEdgeBackwards (edge);
|
||||
}
|
||||
|
||||
R_CleanupSpan ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
R_ScanEdges
|
||||
|
||||
Input:
|
||||
newedges[] array
|
||||
this has links to edges, which have links to surfaces
|
||||
|
||||
Output:
|
||||
Each surface has a linked list of its visible spans
|
||||
==============
|
||||
*/
|
||||
void R_ScanEdges (void)
|
||||
{
|
||||
int iv, bottom;
|
||||
qbyte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
|
||||
espan_t *basespan_p;
|
||||
surf_t *s;
|
||||
|
||||
basespan_p = (espan_t *)
|
||||
((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
|
||||
max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
|
||||
|
||||
span_p = basespan_p;
|
||||
|
||||
// clear active edges to just the background edges around the whole screen
|
||||
// FIXME: most of this only needs to be set up once
|
||||
edge_head.u = r_refdef.vrect.x << 20;
|
||||
edge_head_u_shift20 = edge_head.u >> 20;
|
||||
edge_head.u_step = 0;
|
||||
edge_head.prev = NULL;
|
||||
edge_head.next = &edge_tail;
|
||||
edge_head.surfs[0] = 0;
|
||||
edge_head.surfs[1] = 1;
|
||||
|
||||
edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
|
||||
edge_tail_u_shift20 = edge_tail.u >> 20;
|
||||
edge_tail.u_step = 0;
|
||||
edge_tail.prev = &edge_head;
|
||||
edge_tail.next = &edge_aftertail;
|
||||
edge_tail.surfs[0] = 1;
|
||||
edge_tail.surfs[1] = 0;
|
||||
|
||||
edge_aftertail.u = -1; // force a move
|
||||
edge_aftertail.u_step = 0;
|
||||
edge_aftertail.next = &edge_sentinel;
|
||||
edge_aftertail.prev = &edge_tail;
|
||||
|
||||
// FIXME: do we need this now that we clamp x in r_draw.c?
|
||||
edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this
|
||||
edge_sentinel.prev = &edge_aftertail;
|
||||
|
||||
//
|
||||
// process all scan lines
|
||||
//
|
||||
bottom = r_refdef.vrectbottom - 1;
|
||||
|
||||
for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
|
||||
{
|
||||
current_iv = iv;
|
||||
fv = (float)iv;
|
||||
|
||||
// mark that the head (background start) span is pre-included
|
||||
surfaces[1].spanstate = 1;
|
||||
|
||||
if (newedges[iv])
|
||||
{
|
||||
R_InsertNewEdges (newedges[iv], edge_head.next);
|
||||
}
|
||||
|
||||
(*pdrawfunc) ();
|
||||
|
||||
// flush the span list if we can't be sure we have enough spans left for
|
||||
// the next scan
|
||||
if (span_p > max_span_p)
|
||||
{
|
||||
VID_UnlockBuffer ();
|
||||
S_ExtraUpdate (); // don't let sound get messed up if going slow
|
||||
VID_LockBuffer ();
|
||||
|
||||
if (r_drawculledpolys)
|
||||
R_DrawCulledPolys ();
|
||||
else
|
||||
D_DrawSurfaces ();
|
||||
|
||||
// clear the surface span pointers
|
||||
for (s = &surfaces[1] ; s<surface_p ; s++)
|
||||
s->spans = NULL;
|
||||
|
||||
span_p = basespan_p;
|
||||
}
|
||||
|
||||
if (removeedges[iv])
|
||||
R_RemoveEdges (removeedges[iv]);
|
||||
|
||||
if (edge_head.next != &edge_tail)
|
||||
R_StepActiveU (edge_head.next);
|
||||
}
|
||||
|
||||
// do the last scan (no need to step or sort or remove on the last scan)
|
||||
|
||||
current_iv = iv;
|
||||
fv = (float)iv;
|
||||
|
||||
// mark that the head (background start) span is pre-included
|
||||
surfaces[1].spanstate = 1;
|
||||
|
||||
if (newedges[iv])
|
||||
R_InsertNewEdges (newedges[iv], edge_head.next);
|
||||
|
||||
(*pdrawfunc) ();
|
||||
|
||||
// draw whatever's left in the span list
|
||||
if (r_drawculledpolys)
|
||||
R_DrawCulledPolys ();
|
||||
else
|
||||
D_DrawSurfaces ();
|
||||
}
|
||||
|
||||
|
750
engine/sw/r_edgea.s
Normal file
750
engine/sw/r_edgea.s
Normal 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
|
||||
|
462
engine/sw/r_light.c
Normal file
462
engine/sw/r_light.c
Normal file
|
@ -0,0 +1,462 @@
|
|||
/*
|
||||
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 SWR_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 SWR_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)
|
||||
{
|
||||
SWR_MarkLights (light, bit, node->children[0]);
|
||||
return;
|
||||
}
|
||||
if (dist < -light->radius)
|
||||
{
|
||||
SWR_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;
|
||||
}
|
||||
|
||||
SWR_MarkLights (light, bit, node->children[0]);
|
||||
SWR_MarkLights (light, bit, node->children[1]);
|
||||
}
|
||||
|
||||
void SWR_Q2MarkLights (dlight_t *light, int bit, mnode_t *node)
|
||||
{
|
||||
mplane_t *splitplane;
|
||||
float dist;
|
||||
msurface_t *surf;
|
||||
int i;
|
||||
|
||||
if (node->contents != -1)
|
||||
return;
|
||||
|
||||
splitplane = node->plane;
|
||||
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
|
||||
|
||||
if (dist > light->radius)
|
||||
{
|
||||
SWR_Q2MarkLights (light, bit, node->children[0]);
|
||||
return;
|
||||
}
|
||||
if (dist < -light->radius)
|
||||
{
|
||||
SWR_Q2MarkLights (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;
|
||||
}
|
||||
|
||||
SWR_Q2MarkLights (light, bit, node->children[0]);
|
||||
SWR_Q2MarkLights (light, bit, node->children[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PushDlights
|
||||
=============
|
||||
*/
|
||||
void SWR_PushDlights (void)
|
||||
{
|
||||
int i;
|
||||
dlight_t *l;
|
||||
|
||||
r_dlightframecount = r_framecount + 1; // because the count hasn't
|
||||
// advanced yet for this frame
|
||||
|
||||
if (!r_dynamic.value)
|
||||
return;
|
||||
|
||||
l = cl_dlights;
|
||||
|
||||
if (cl.worldmodel->fromgame == fg_quake2)
|
||||
{
|
||||
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
|
||||
{
|
||||
if (l->die < cl.time || !l->radius)
|
||||
continue;
|
||||
SWR_Q2MarkLights ( l, 1<<i, cl.worldmodel->nodes );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
|
||||
{
|
||||
if (l->die < cl.time || !l->radius)
|
||||
continue;
|
||||
SWR_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LIGHT SAMPLING
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
int SWRecursiveLightPoint (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;
|
||||
qbyte *lightmap;
|
||||
unsigned scale;
|
||||
int maps;
|
||||
|
||||
if (cl.worldmodel->fromgame == fg_quake2)
|
||||
{
|
||||
if (node->contents != -1)
|
||||
return -1; // solid
|
||||
}
|
||||
else 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 SWRecursiveLightPoint (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 = SWRecursiveLightPoint (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 SWRecursiveLightPoint (node->children[!side], mid, end);
|
||||
}
|
||||
int SWRecursiveLightPoint3C (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;
|
||||
qbyte *lightmap;
|
||||
unsigned scale;
|
||||
int maps;
|
||||
|
||||
|
||||
if (cl.worldmodel->fromgame == fg_quake2)
|
||||
{
|
||||
if (node->contents != -1)
|
||||
return -1; // solid
|
||||
}
|
||||
else 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 SWRecursiveLightPoint3C (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 = SWRecursiveLightPoint (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)*3;
|
||||
|
||||
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
|
||||
maps++)
|
||||
{
|
||||
scale = d_lightstylevalue[surf->styles[maps]];
|
||||
r += (lightmap[0]+lightmap[1]+lightmap[2])/3 * scale;
|
||||
lightmap += ((surf->extents[0]>>4)+1) *
|
||||
((surf->extents[1]>>4)+1)*3;
|
||||
}
|
||||
|
||||
r >>= 8;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return SWRecursiveLightPoint3C (node->children[!side], mid, end);
|
||||
}
|
||||
int SWR_LightPoint (vec3_t p)
|
||||
{
|
||||
vec3_t end;
|
||||
int r;
|
||||
extern qboolean r_usinglits;
|
||||
|
||||
if (r_refdef.flags & 1 || !cl.worldmodel || !cl.worldmodel->lightdata)
|
||||
return 255;
|
||||
|
||||
end[0] = p[0];
|
||||
end[1] = p[1];
|
||||
end[2] = p[2] - 2048;
|
||||
|
||||
if (r_usinglits)
|
||||
r = SWRecursiveLightPoint3C (cl.worldmodel->nodes, p, end);
|
||||
else
|
||||
r = SWRecursiveLightPoint (cl.worldmodel->nodes, p, end);
|
||||
|
||||
if (r == -1)
|
||||
r = 0;
|
||||
|
||||
if (r < r_refdef.ambientlight)
|
||||
r = r_refdef.ambientlight;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void SWQ1BSP_LightPointValues(vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
|
||||
{
|
||||
vec3_t end;
|
||||
float r;
|
||||
|
||||
res_dir[0] = 0; //software doesn't load luxes
|
||||
res_dir[1] = 1;
|
||||
res_dir[2] = 1;
|
||||
|
||||
end[0] = point[0];
|
||||
end[1] = point[1];
|
||||
end[2] = point[2] - 2048;
|
||||
|
||||
r = SWRecursiveLightPoint3C(cl.worldmodel->nodes, point, end);
|
||||
if (r < 0)
|
||||
{
|
||||
res_diffuse[0] = 0;
|
||||
res_diffuse[1] = 0;
|
||||
res_diffuse[2] = 0;
|
||||
|
||||
res_ambient[0] = 0;
|
||||
res_ambient[1] = 0;
|
||||
res_ambient[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res_diffuse[0] = r;
|
||||
res_diffuse[1] = r;
|
||||
res_diffuse[2] = r;
|
||||
|
||||
res_ambient[0] = r;
|
||||
res_ambient[1] = r;
|
||||
res_ambient[2] = r;
|
||||
}
|
||||
}
|
||||
|
323
engine/sw/r_local.h
Normal file
323
engine/sw/r_local.h
Normal file
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
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_local.h -- private refresh defs
|
||||
|
||||
#ifdef SWQUAKE
|
||||
|
||||
#include "r_shared.h"
|
||||
|
||||
#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0)
|
||||
// normalizing factor so player model works out to about
|
||||
// 1 pixel per triangle
|
||||
|
||||
#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox ()
|
||||
// if bbox is trivially rejected
|
||||
|
||||
//===========================================================================
|
||||
// viewmodel lighting
|
||||
|
||||
typedef struct {
|
||||
int ambientlight;
|
||||
int shadelight;
|
||||
float *plightvec;
|
||||
} alight_t;
|
||||
|
||||
//===========================================================================
|
||||
// clipped bmodel edges
|
||||
|
||||
typedef struct bedge_s
|
||||
{
|
||||
mvertex_t *v[2];
|
||||
struct bedge_s *pnext;
|
||||
} bedge_t;
|
||||
|
||||
typedef struct {
|
||||
float fv[3]; // viewspace x, y
|
||||
} auxvert_t;
|
||||
|
||||
//===========================================================================
|
||||
|
||||
extern cvar_t r_draworder;
|
||||
extern cvar_t r_speeds;
|
||||
extern cvar_t r_timegraph;
|
||||
extern cvar_t r_graphheight;
|
||||
extern cvar_t r_clearcolor;
|
||||
extern cvar_t r_waterwarp;
|
||||
extern cvar_t r_fullbright;
|
||||
extern cvar_t r_drawentities;
|
||||
extern cvar_t r_aliasstats;
|
||||
extern cvar_t r_dspeeds;
|
||||
extern cvar_t r_drawflat;
|
||||
extern cvar_t r_ambient;
|
||||
extern cvar_t r_reportsurfout;
|
||||
extern cvar_t r_maxsurfs;
|
||||
extern cvar_t r_numsurfs;
|
||||
extern cvar_t r_reportedgeout;
|
||||
extern cvar_t r_maxedges;
|
||||
extern cvar_t r_numedges;
|
||||
|
||||
#define XCENTERING (1.0 / 2.0)
|
||||
#define YCENTERING (1.0 / 2.0)
|
||||
|
||||
#define CLIP_EPSILON 0.001
|
||||
|
||||
#define BACKFACE_EPSILON 0.01
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define DIST_NOT_SET 98765
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct clipplane_s
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
struct clipplane_s *next;
|
||||
qbyte leftedge;
|
||||
qbyte rightedge;
|
||||
qbyte reserved[2];
|
||||
} clipplane_t;
|
||||
|
||||
extern clipplane_t view_clipplanes[4];
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void R_RenderWorld (void);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
extern mplane_t screenedge[4];
|
||||
|
||||
extern vec3_t r_origin;
|
||||
|
||||
extern vec3_t r_entorigin;
|
||||
|
||||
extern float screenAspect;
|
||||
extern float verticalFieldOfView;
|
||||
extern float xOrigin, yOrigin;
|
||||
|
||||
extern int r_visframecount;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
extern int vstartscan;
|
||||
|
||||
|
||||
void R_ClearPolyList (void);
|
||||
void R_DrawPolyList (void);
|
||||
|
||||
//
|
||||
// current entity info
|
||||
//
|
||||
extern qboolean insubmodel;
|
||||
extern vec3_t r_worldmodelorg;
|
||||
|
||||
|
||||
void R_DrawSprite (void);
|
||||
void R_RenderFace (msurface_t *fa, int clipflags);
|
||||
void R_RenderPoly (msurface_t *fa, int clipflags);
|
||||
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
|
||||
void R_TransformPlane (mplane_t *p, float *normal, float *dist);
|
||||
void R_TransformFrustum (void);
|
||||
void R_SetSkyFrame (void);
|
||||
void R_DrawSurfaceBlock16From8 (void);
|
||||
void R_DrawSurfaceBlock8 (void);
|
||||
texture_t *SWR_TextureAnimation (texture_t *base);
|
||||
|
||||
#if id386
|
||||
|
||||
void R_DrawSurfaceBlock8_mip0 (void);
|
||||
void R_DrawSurfaceBlock8_mip1 (void);
|
||||
void R_DrawSurfaceBlock8_mip2 (void);
|
||||
void R_DrawSurfaceBlock8_mip3 (void);
|
||||
|
||||
#endif
|
||||
|
||||
void R_GenSkyTile (void *pdest);
|
||||
void R_GenSkyTile16 (void *pdest);
|
||||
void R_Surf8Patch (void);
|
||||
void R_Surf16Patch (void);
|
||||
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags);
|
||||
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel);
|
||||
|
||||
void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
|
||||
surf_t *R_GetSurf (void);
|
||||
void R_AliasDrawModel (alight_t *plighting);
|
||||
void R_BeginEdgeFrame (void);
|
||||
void R_ScanEdges (void);
|
||||
void D_DrawSurfaces (void);
|
||||
void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist);
|
||||
void R_StepActiveU (edge_t *pedge);
|
||||
void R_RemoveEdges (edge_t *pedge);
|
||||
|
||||
extern void R_Surf8Start (void);
|
||||
extern void R_Surf8End (void);
|
||||
extern void R_Surf16Start (void);
|
||||
extern void R_Surf16End (void);
|
||||
extern void R_EdgeCodeStart (void);
|
||||
extern void R_EdgeCodeEnd (void);
|
||||
|
||||
extern void R_RotateBmodel (void);
|
||||
|
||||
extern int c_faceclip;
|
||||
extern int r_polycount;
|
||||
extern int r_wholepolycount;
|
||||
|
||||
extern model_t *cl_worldmodel;
|
||||
|
||||
extern int *pfrustum_indexes[4];
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
#define NEAR_CLIP 0.01
|
||||
|
||||
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
|
||||
extern int vstartscan;
|
||||
|
||||
extern fixed16_t sadjust, tadjust;
|
||||
extern fixed16_t bbextents, bbextentt;
|
||||
|
||||
#define MAXBVERTINDEXES 1000 // new clipped vertices when clipping bmodels
|
||||
// to the world BSP
|
||||
extern mvertex_t *r_ptverts, *r_ptvertsmax;
|
||||
|
||||
extern vec3_t sbaseaxis[3], tbaseaxis[3];
|
||||
extern float entity_rotation[3][3];
|
||||
|
||||
extern int reinit_surfcache;
|
||||
|
||||
extern int r_currentkey;
|
||||
extern int r_currentbkey;
|
||||
|
||||
typedef struct btofpoly_s {
|
||||
int clipflags;
|
||||
msurface_t *psurf;
|
||||
} btofpoly_t;
|
||||
|
||||
#define MAX_BTOFPOLYS 5000 // FIXME: tune this
|
||||
|
||||
extern int numbtofpolys;
|
||||
extern btofpoly_t *pbtofpolys;
|
||||
|
||||
void R_InitTurb (void);
|
||||
void R_ZDrawSubmodelPolys (model_t *clmodel);
|
||||
|
||||
//=========================================================
|
||||
// Alias models
|
||||
//=========================================================
|
||||
|
||||
extern int numverts;
|
||||
extern int a_skinwidth;
|
||||
extern mtriangle_t *ptriangles;
|
||||
extern int numtriangles;
|
||||
extern aliashdr_t *paliashdr;
|
||||
extern mmdl_t *pmdl;
|
||||
extern float leftclip, topclip, rightclip, bottomclip;
|
||||
extern int r_acliptype;
|
||||
extern finalvert_t *pfinalverts;
|
||||
extern auxvert_t *pauxverts;
|
||||
|
||||
qboolean R_AliasCheckBBox (void);
|
||||
|
||||
//=========================================================
|
||||
// turbulence stuff
|
||||
|
||||
#define AMP 8*0x10000
|
||||
#define AMP2 3
|
||||
#define SPEED 20
|
||||
|
||||
//=========================================================
|
||||
// particle stuff
|
||||
|
||||
void R_DrawParticles (void);
|
||||
void R_InitParticles (void);
|
||||
void R_EmitSkyEffectTris(model_t *mod, msurface_t *fa);
|
||||
void R_ClearParticles (void);
|
||||
void R_ReadPointFile_f (void);
|
||||
void R_SurfacePatch (void);
|
||||
|
||||
extern int r_amodels_drawn;
|
||||
extern edge_t *auxedges;
|
||||
extern int r_numallocatededges;
|
||||
extern edge_t *r_edges, *edge_p, *edge_max;
|
||||
|
||||
extern edge_t *newedges[MAXHEIGHT];
|
||||
extern edge_t *removeedges[MAXHEIGHT];
|
||||
|
||||
extern int screenwidth;
|
||||
|
||||
extern qboolean r_usinglits;
|
||||
|
||||
// FIXME: make stack vars when debugging done
|
||||
extern edge_t edge_head;
|
||||
extern edge_t edge_tail;
|
||||
extern edge_t edge_aftertail;
|
||||
extern int r_bmodelactive;
|
||||
|
||||
extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
|
||||
extern float r_aliastransition, r_resfudge;
|
||||
|
||||
extern int r_outofsurfaces;
|
||||
extern int r_outofedges;
|
||||
|
||||
extern mvertex_t *r_pcurrentvertbase;
|
||||
extern int r_maxvalidedgeoffset;
|
||||
|
||||
void R_AliasClipTriangle (mtriangle_t *ptri);
|
||||
|
||||
extern float r_time1;
|
||||
extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
|
||||
extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
|
||||
extern int r_frustum_indexes[4*6];
|
||||
extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
|
||||
extern qboolean r_surfsonstack;
|
||||
extern cshift_t cshift_water;
|
||||
extern qboolean r_dowarpold, r_viewchanged;
|
||||
|
||||
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
|
||||
|
||||
extern vec3_t r_emins, r_emaxs;
|
||||
extern mnode_t *r_pefragtopnode;
|
||||
extern int r_clipflags;
|
||||
extern int r_dlightframecount;
|
||||
extern qboolean r_fov_greater_than_90;
|
||||
|
||||
void R_StoreEfrags (efrag_t **ppefrag);
|
||||
void SWR_TimeRefresh_f (void);
|
||||
void R_TimeGraph (void);
|
||||
void R_PrintAliasStats (void);
|
||||
void R_PrintTimes (void);
|
||||
void R_PrintDSpeeds (void);
|
||||
void SWR_AnimateLight (void);
|
||||
int SWR_LightPoint (vec3_t p);
|
||||
//void R_SetupFrame (void);
|
||||
void R_cshift_f (void);
|
||||
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
|
||||
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
|
||||
void R_Q1BSP_SplitEntityOnNode2 (mnode_t *node);
|
||||
void SWR_MarkLights (dlight_t *light, int bit, mnode_t *node);
|
||||
|
||||
void SWR_DrawAlphaSurfaces( void );
|
||||
void SWR_SetupFrame (void);
|
||||
void R_InitSkyBox (void);
|
||||
void R_InitSkyBox (void);
|
||||
void SWR_BuildLightmaps(void);
|
||||
void SWR_NetGraph (void);
|
||||
|
||||
#endif //def SWQUAKE
|
1816
engine/sw/r_main.c
Normal file
1816
engine/sw/r_main.c
Normal file
File diff suppressed because it is too large
Load diff
639
engine/sw/r_misc.c
Normal file
639
engine/sw/r_misc.c
Normal file
|
@ -0,0 +1,639 @@
|
|||
/*
|
||||
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_misc.c
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "r_local.h"
|
||||
extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
|
||||
|
||||
/*
|
||||
===============
|
||||
R_CheckVariables
|
||||
===============
|
||||
*/
|
||||
void R_CheckVariables (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Show
|
||||
|
||||
Debugging use
|
||||
============
|
||||
*/
|
||||
void Show (void)
|
||||
{
|
||||
vrect_t vr;
|
||||
|
||||
vr.x = vr.y = 0;
|
||||
vr.width = vid.width;
|
||||
vr.height = vid.height;
|
||||
vr.pnext = NULL;
|
||||
SWVID_Update (&vr);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_TimeRefresh_f
|
||||
|
||||
For program optimization
|
||||
====================
|
||||
*/
|
||||
void SWR_TimeRefresh_f (void)
|
||||
{
|
||||
int i;
|
||||
float start, stop, time;
|
||||
int startangle;
|
||||
vrect_t vr;
|
||||
|
||||
startangle = r_refdef.viewangles[1];
|
||||
|
||||
start = Sys_DoubleTime ();
|
||||
for (i=0 ; i<128 ; i++)
|
||||
{
|
||||
r_refdef.viewangles[1] = i/128.0*360.0;
|
||||
|
||||
VID_LockBuffer ();
|
||||
|
||||
R_RenderView ();
|
||||
|
||||
VID_UnlockBuffer ();
|
||||
|
||||
vr.x = r_refdef.vrect.x;
|
||||
vr.y = r_refdef.vrect.y;
|
||||
vr.width = r_refdef.vrect.width;
|
||||
vr.height = r_refdef.vrect.height;
|
||||
vr.pnext = NULL;
|
||||
SWVID_Update (&vr);
|
||||
}
|
||||
stop = Sys_DoubleTime ();
|
||||
time = stop-start;
|
||||
Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
|
||||
|
||||
r_refdef.viewangles[1] = startangle;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_LineGraph
|
||||
|
||||
Only called by R_DisplayTime
|
||||
================
|
||||
*/
|
||||
void R_LineGraph (int x, int y, int h)
|
||||
{
|
||||
int i;
|
||||
qbyte *dest;
|
||||
int s;
|
||||
int color;
|
||||
|
||||
// FIXME: should be disabled on no-buffer adapters, or should be in the driver
|
||||
|
||||
// x += r_refdef.vrect.x;
|
||||
// y += r_refdef.vrect.y;
|
||||
|
||||
dest = vid.buffer + vid.rowbytes*y + x;
|
||||
|
||||
s = r_graphheight.value;
|
||||
|
||||
if (h == 10000)
|
||||
color = 0x6f; // yellow
|
||||
else if (h == 9999)
|
||||
color = 0x4f; // red
|
||||
else if (h == 9998)
|
||||
color = 0xd0; // blue
|
||||
else
|
||||
color = 0xff; // pink
|
||||
|
||||
if (h>s)
|
||||
h = s;
|
||||
|
||||
for (i=0 ; i<h ; i++, dest -= vid.rowbytes*2)
|
||||
{
|
||||
dest[0] = color;
|
||||
// *(dest-vid.rowbytes) = 0x30;
|
||||
}
|
||||
#if 0
|
||||
for ( ; i<s ; i++, dest -= vid.rowbytes*2)
|
||||
{
|
||||
dest[0] = 0x30;
|
||||
*(dest-vid.rowbytes) = 0x30;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_TimeGraph
|
||||
|
||||
Performance monitoring tool
|
||||
==============
|
||||
*/
|
||||
#define MAX_TIMINGS 100
|
||||
extern float mouse_x, mouse_y;
|
||||
int graphval;
|
||||
void R_TimeGraph (void)
|
||||
{
|
||||
static int timex;
|
||||
int a;
|
||||
float r_time2;
|
||||
static qbyte r_timings[MAX_TIMINGS];
|
||||
int x;
|
||||
|
||||
r_time2 = Sys_DoubleTime ();
|
||||
|
||||
a = (r_time2-r_time1)/0.01;
|
||||
//a = fabs(mouse_y * 0.05);
|
||||
//a = (int)((r_refdef.vieworg[2] + 1024)/1)%(int)r_graphheight.value;
|
||||
//a = (int)((pmove.velocity[2] + 500)/10);
|
||||
//a = fabs(velocity[0])/20;
|
||||
//a = ((int)fabs(origin[0])/8)%20;
|
||||
//a = (cl.idealpitch + 30)/5;
|
||||
//a = (int)(cl.simangles[YAW] * 64/360) & 63;
|
||||
a = graphval;
|
||||
|
||||
r_timings[timex] = a;
|
||||
a = timex;
|
||||
|
||||
if (r_refdef.vrect.width <= MAX_TIMINGS)
|
||||
x = r_refdef.vrect.width-1;
|
||||
else
|
||||
x = r_refdef.vrect.width -
|
||||
(r_refdef.vrect.width - MAX_TIMINGS)/2;
|
||||
do
|
||||
{
|
||||
R_LineGraph (x, r_refdef.vrect.height-2, r_timings[a]);
|
||||
if (x==0)
|
||||
break; // screen too small to hold entire thing
|
||||
x--;
|
||||
a--;
|
||||
if (a == -1)
|
||||
a = MAX_TIMINGS-1;
|
||||
} while (a != timex);
|
||||
|
||||
timex = (timex+1)%MAX_TIMINGS;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_NetGraph
|
||||
==============
|
||||
*/
|
||||
void SWR_NetGraph (void)
|
||||
{
|
||||
int a, x, y, y2, w, i;
|
||||
int lost;
|
||||
char st[80];
|
||||
|
||||
if (vid.width - 16 <= NET_TIMINGS)
|
||||
w = vid.width - 16;
|
||||
else
|
||||
w = NET_TIMINGS;
|
||||
|
||||
x = -(int)((vid.width - 320)>>1);
|
||||
y = vid.height - sb_lines - 24 - (int)r_graphheight.value*2 - 2;
|
||||
|
||||
M_DrawTextBox (x, y, (w+7)/8, ((int)r_graphheight.value*2+7)/8 + 1);
|
||||
y2 = y + 8;
|
||||
y = vid.height - sb_lines - 8 - 2;
|
||||
|
||||
x = 8;
|
||||
lost = CL_CalcNet();
|
||||
for (a=NET_TIMINGS-w ; a<w ; a++)
|
||||
{
|
||||
i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
|
||||
R_LineGraph (x+w-1-a, y, packet_latency[i]);
|
||||
}
|
||||
sprintf(st, "%3i%% packet loss", lost);
|
||||
Draw_String(8, y2, st);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_ZGraph
|
||||
==============
|
||||
*/
|
||||
void R_ZGraph (void)
|
||||
{
|
||||
int a, x, w, i;
|
||||
static int height[256];
|
||||
|
||||
if (r_refdef.vrect.width <= 256)
|
||||
w = r_refdef.vrect.width;
|
||||
else
|
||||
w = 256;
|
||||
|
||||
height[r_framecount&255] = ((int)r_origin[2]) & 31;
|
||||
|
||||
x = 0;
|
||||
for (a=0 ; a<w ; a++)
|
||||
{
|
||||
i = (r_framecount-a) & 255;
|
||||
R_LineGraph (x+w-1-a, r_refdef.vrect.height-2, height[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PrintTimes
|
||||
=============
|
||||
*/
|
||||
void R_PrintTimes (void)
|
||||
{
|
||||
float r_time2;
|
||||
float ms;
|
||||
|
||||
r_time2 = Sys_DoubleTime ();
|
||||
|
||||
ms = 1000* (r_time2 - r_time1);
|
||||
|
||||
Con_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n",
|
||||
ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
|
||||
c_surf = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PrintDSpeeds
|
||||
=============
|
||||
*/
|
||||
void R_PrintDSpeeds (void)
|
||||
{
|
||||
float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, dv_time;
|
||||
|
||||
r_time2 = Sys_DoubleTime ();
|
||||
|
||||
dp_time = (dp_time2 - dp_time1) * 1000;
|
||||
rw_time = (rw_time2 - rw_time1) * 1000;
|
||||
db_time = (db_time2 - db_time1) * 1000;
|
||||
se_time = (se_time2 - se_time1) * 1000;
|
||||
de_time = (de_time2 - de_time1) * 1000;
|
||||
dv_time = (dv_time2 - dv_time1) * 1000;
|
||||
ms = (r_time2 - r_time1) * 1000;
|
||||
|
||||
Con_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n",
|
||||
(int)ms, dp_time, (int)rw_time, db_time, (int)se_time, de_time,
|
||||
dv_time);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PrintAliasStats
|
||||
=============
|
||||
*/
|
||||
void R_PrintAliasStats (void)
|
||||
{
|
||||
Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn);
|
||||
}
|
||||
|
||||
|
||||
void WarpPalette (void)
|
||||
{
|
||||
int i,j;
|
||||
qbyte newpalette[768];
|
||||
int basecolor[3];
|
||||
|
||||
basecolor[0] = 130;
|
||||
basecolor[1] = 80;
|
||||
basecolor[2] = 50;
|
||||
|
||||
// pull the colors halfway to bright brown
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
newpalette[i*3+j] = (host_basepal[i*3+j] + basecolor[j])/2;
|
||||
}
|
||||
}
|
||||
|
||||
VID_ShiftPalette (newpalette);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
R_TransformFrustum
|
||||
===================
|
||||
*/
|
||||
void R_TransformFrustum (void)
|
||||
{
|
||||
int i;
|
||||
vec3_t v, v2;
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
v[0] = screenedge[i].normal[2];
|
||||
v[1] = -screenedge[i].normal[0];
|
||||
v[2] = screenedge[i].normal[1];
|
||||
|
||||
v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
|
||||
v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
|
||||
v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
|
||||
|
||||
VectorCopy (v2, view_clipplanes[i].normal);
|
||||
|
||||
view_clipplanes[i].dist = DotProduct (modelorg, v2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
================
|
||||
TransformVector
|
||||
================
|
||||
*/
|
||||
void TransformVector (vec3_t in, vec3_t out)
|
||||
{
|
||||
out[0] = DotProduct(in,vright);
|
||||
out[1] = DotProduct(in,vup);
|
||||
out[2] = DotProduct(in,vpn);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_TransformPlane
|
||||
================
|
||||
*/
|
||||
void R_TransformPlane (mplane_t *p, float *normal, float *dist)
|
||||
{
|
||||
float d;
|
||||
|
||||
d = DotProduct (r_origin, p->normal);
|
||||
*dist = p->dist - d;
|
||||
// TODO: when we have rotating entities, this will need to use the view matrix
|
||||
TransformVector (p->normal, normal);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SetUpFrustumIndexes
|
||||
===============
|
||||
*/
|
||||
void R_SetUpFrustumIndexes (void)
|
||||
{
|
||||
int i, j, *pindex;
|
||||
|
||||
pindex = r_frustum_indexes;
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
if (view_clipplanes[i].normal[j] < 0)
|
||||
{
|
||||
pindex[j] = j;
|
||||
pindex[j+3] = j+3;
|
||||
}
|
||||
else
|
||||
{
|
||||
pindex[j] = j+3;
|
||||
pindex[j+3] = j;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: do just once at start
|
||||
pfrustum_indexes[i] = pindex;
|
||||
pindex += 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SetupFrame
|
||||
===============
|
||||
*/
|
||||
void SWR_SetupFrame (void)
|
||||
{
|
||||
static mleaf_t fakeleaf;
|
||||
extern int r_dosirds;
|
||||
|
||||
extern int scr_chatmode;
|
||||
|
||||
int edgecount;
|
||||
vrect_t vrect;
|
||||
float w, h;
|
||||
|
||||
// don't allow cheats in multiplayer
|
||||
|
||||
if (r_numsurfs.value)
|
||||
{
|
||||
if ((surface_p - surfaces) > r_maxsurfsseen)
|
||||
r_maxsurfsseen = surface_p - surfaces;
|
||||
|
||||
Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces,
|
||||
surf_max - surfaces, r_maxsurfsseen);
|
||||
}
|
||||
|
||||
if (r_numedges.value)
|
||||
{
|
||||
edgecount = edge_p - r_edges;
|
||||
|
||||
if (edgecount > r_maxedgesseen)
|
||||
r_maxedgesseen = edgecount;
|
||||
|
||||
Con_Printf ("Used %d of %d edges; %d max\n", edgecount,
|
||||
r_numallocatededges, r_maxedgesseen);
|
||||
}
|
||||
|
||||
r_refdef.ambientlight = r_ambient.value;
|
||||
|
||||
if (r_refdef.ambientlight < 0)
|
||||
r_refdef.ambientlight = 0;
|
||||
|
||||
// if (!sv.active)
|
||||
r_draworder.value = 0; // don't let cheaters look behind walls
|
||||
|
||||
R_CheckVariables ();
|
||||
|
||||
SWR_AnimateLight ();
|
||||
|
||||
r_framecount++;
|
||||
|
||||
numbtofpolys = 0;
|
||||
|
||||
// debugging
|
||||
#if 0
|
||||
r_refdef.vieworg[0]= 80;
|
||||
r_refdef.vieworg[1]= 64;
|
||||
r_refdef.vieworg[2]= 40;
|
||||
r_refdef.viewangles[0]= 0;
|
||||
r_refdef.viewangles[1]= 46.763641357;
|
||||
r_refdef.viewangles[2]= 0;
|
||||
#endif
|
||||
|
||||
// build the transformation matrix for the given view angles
|
||||
VectorCopy (r_refdef.vieworg, modelorg);
|
||||
VectorCopy (r_refdef.vieworg, r_origin);
|
||||
|
||||
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
|
||||
|
||||
if (r_refdef.flags & 1)
|
||||
{
|
||||
r_oldviewleaf = r_viewleaf = &fakeleaf; //so we can use quake1 rendering routines for q2 bsps.
|
||||
r_viewleaf->contents = Q1CONTENTS_EMPTY;
|
||||
}
|
||||
else if (cl.worldmodel->fromgame == fg_quake2)
|
||||
{
|
||||
mleaf_t *leaf;
|
||||
|
||||
r_viewleaf = &fakeleaf; //so we can use quake1 rendering routines for q2 bsps.
|
||||
r_viewleaf->contents = Q1CONTENTS_EMPTY;
|
||||
|
||||
r_oldviewcluster = r_viewcluster;
|
||||
r_oldviewcluster2 = r_viewcluster2;
|
||||
leaf = SWMod_PointInLeaf (r_origin, cl.worldmodel);
|
||||
r_viewcluster = r_viewcluster2 = leaf->cluster;
|
||||
|
||||
// check above and below so crossing solid water doesn't draw wrong
|
||||
if (!leaf->contents)
|
||||
{ // look down a bit
|
||||
vec3_t temp;
|
||||
|
||||
VectorCopy (r_origin, temp);
|
||||
temp[2] -= 16;
|
||||
leaf = SWMod_PointInLeaf (temp, cl.worldmodel);
|
||||
if ( !(leaf->contents & Q2CONTENTS_SOLID) &&
|
||||
(leaf->cluster != r_viewcluster2) )
|
||||
r_viewcluster2 = leaf->cluster;
|
||||
}
|
||||
else
|
||||
{ // look up a bit
|
||||
vec3_t temp;
|
||||
|
||||
VectorCopy (r_origin, temp);
|
||||
temp[2] += 16;
|
||||
leaf = SWMod_PointInLeaf (temp, cl.worldmodel);
|
||||
if ( !(leaf->contents & Q2CONTENTS_SOLID) &&
|
||||
(leaf->cluster != r_viewcluster2) )
|
||||
r_viewcluster2 = leaf->cluster;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// current viewleaf
|
||||
r_oldviewleaf = r_viewleaf;
|
||||
r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
|
||||
}
|
||||
|
||||
r_dowarpold = r_dowarp;
|
||||
#ifdef SIDEVIEWS
|
||||
r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= Q1CONTENTS_WATER) && !r_secondaryview;
|
||||
#else
|
||||
r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= Q1CONTENTS_WATER);
|
||||
#endif
|
||||
if (vid.width > MAXWIDTH || r_pixbytes == 4 || scr_chatmode)
|
||||
r_dowarp = 0;
|
||||
if (r_dosirds)
|
||||
r_dowarp = 0;
|
||||
|
||||
if ((r_dowarp != r_dowarpold) || r_viewchanged)
|
||||
{
|
||||
if (r_dowarp)
|
||||
{
|
||||
if ((vid.width <= vid.maxwarpwidth) &&
|
||||
(vid.height <= vid.maxwarpheight))
|
||||
{
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height;
|
||||
|
||||
SWR_ViewChanged (&vrect, sb_lines, vid.aspect);
|
||||
}
|
||||
else
|
||||
{
|
||||
w = vid.width;
|
||||
h = vid.height;
|
||||
|
||||
if (w > vid.maxwarpwidth)
|
||||
{
|
||||
h *= (float)vid.maxwarpwidth / w;
|
||||
w = vid.maxwarpwidth;
|
||||
}
|
||||
|
||||
if (h > vid.maxwarpheight)
|
||||
{
|
||||
h = vid.maxwarpheight;
|
||||
w *= (float)vid.maxwarpheight / h;
|
||||
}
|
||||
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
vrect.width = (int)w;
|
||||
vrect.height = (int)h;
|
||||
|
||||
SWR_ViewChanged (&vrect,
|
||||
(int)((float)sb_lines * (h/(float)vid.height)),
|
||||
vid.aspect * (h / w) *
|
||||
((float)vid.width / (float)vid.height));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height;
|
||||
|
||||
SWR_ViewChanged (&vrect, sb_lines, vid.aspect);
|
||||
}
|
||||
|
||||
r_viewchanged = false;
|
||||
}
|
||||
|
||||
// start off with just the four screen edge clip planes
|
||||
R_TransformFrustum ();
|
||||
|
||||
// save base values
|
||||
VectorCopy (vpn, base_vpn);
|
||||
VectorCopy (vright, base_vright);
|
||||
VectorCopy (vup, base_vup);
|
||||
VectorCopy (modelorg, base_modelorg);
|
||||
|
||||
R_SetSkyFrame ();
|
||||
|
||||
R_SetUpFrustumIndexes ();
|
||||
|
||||
r_cache_thrash = false;
|
||||
|
||||
// clear frame counts
|
||||
c_faceclip = 0;
|
||||
d_spanpixcount = 0;
|
||||
r_polycount = 0;
|
||||
r_drawnpolycount = 0;
|
||||
r_wholepolycount = 0;
|
||||
r_amodels_drawn = 0;
|
||||
r_outofsurfaces = 0;
|
||||
r_outofedges = 0;
|
||||
|
||||
D_SetupFrame ();
|
||||
}
|
||||
|
155
engine/sw/r_shared.h
Normal file
155
engine/sw/r_shared.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
#ifdef SWQUAKE
|
||||
// r_shared.h: general refresh-related stuff shared between the refresh and the
|
||||
// driver
|
||||
|
||||
// FIXME: clean up and move into d_iface.h
|
||||
|
||||
#ifndef _R_SHARED_H_
|
||||
#define _R_SHARED_H_
|
||||
|
||||
#define MAXVERTS 16 // max points in a surface polygon
|
||||
#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
|
||||
// polygon (while processing)
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
#define MAXHEIGHT 1024
|
||||
#define MAXWIDTH 1280
|
||||
|
||||
#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
|
||||
// be farther away than anything in
|
||||
// the scene
|
||||
|
||||
//===================================================================
|
||||
|
||||
extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
|
||||
|
||||
extern int cachewidth;
|
||||
extern int cacheheight;
|
||||
extern pixel_t *cacheblock;
|
||||
extern int screenwidth;
|
||||
|
||||
extern float pixelAspect;
|
||||
|
||||
extern int r_drawnpolycount;
|
||||
|
||||
extern cvar_t r_clearcolor;
|
||||
#define SINTABLESIZE (MAXWIDTH+CYCLE)
|
||||
extern int sintable[SINTABLESIZE];
|
||||
extern int intsintable[SINTABLESIZE];
|
||||
|
||||
extern vec3_t vup, base_vup;
|
||||
extern vec3_t vpn, base_vpn;
|
||||
extern vec3_t vright, base_vright;
|
||||
extern entity_t *currententity;
|
||||
|
||||
#define NUMSTACKEDGES 2000
|
||||
#define MINEDGES NUMSTACKEDGES
|
||||
#define NUMSTACKSURFACES 1000
|
||||
#define MINSURFACES NUMSTACKSURFACES
|
||||
#define MAXSPANS 3000
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct espan_s
|
||||
{
|
||||
int u, v, count;
|
||||
struct espan_s *pnext;
|
||||
} espan_t;
|
||||
|
||||
// FIXME: compress, make a union if that will help
|
||||
// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
|
||||
typedef struct surf_s
|
||||
{
|
||||
struct surf_s *next; // active surface stack in r_edge.c
|
||||
struct surf_s *prev; // used in r_edge.c for active surf stack
|
||||
struct espan_s *spans; // pointer to linked list of spans to draw
|
||||
int key; // sorting key (BSP order)
|
||||
int last_u; // set during tracing
|
||||
int spanstate; // 0 = not in span
|
||||
// 1 = in span
|
||||
// -1 = in inverted span (end before
|
||||
// start)
|
||||
int flags; // currentface flags
|
||||
void *data; // associated data like msurface_t
|
||||
entity_t *entity;
|
||||
float nearzi; // nearest 1/z on surface, for mipmapping
|
||||
qboolean insubmodel;
|
||||
float d_ziorigin, d_zistepu, d_zistepv;
|
||||
|
||||
int pad[2]; // to 64 bytes
|
||||
} surf_t;
|
||||
|
||||
extern surf_t *surfaces, *surface_p, *surf_max;
|
||||
|
||||
// surfaces are generated in back to front order by the bsp, so if a surf
|
||||
// pointer is greater than another one, it should be drawn in front
|
||||
// surfaces[1] is the background, and is used as the active surface stack.
|
||||
// surfaces[0] is a dummy, because index 0 is used to indicate no surface
|
||||
// attached to an edge_t
|
||||
|
||||
//===================================================================
|
||||
|
||||
extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
|
||||
extern vec3_t txformaxis[4]; // t axis transformed into viewspac
|
||||
|
||||
extern vec3_t modelorg, base_modelorg;
|
||||
|
||||
extern float xcenter, ycenter;
|
||||
extern float xscale, yscale;
|
||||
extern float xscaleinv, yscaleinv;
|
||||
extern float xscaleshrink, yscaleshrink;
|
||||
|
||||
extern int d_lightstylevalue[256]; // 8.8 frac of base light value
|
||||
|
||||
extern void TransformVector (vec3_t in, vec3_t out);
|
||||
extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
|
||||
fixed8_t endvertu, fixed8_t endvertv);
|
||||
|
||||
extern int r_skymade;
|
||||
extern void R_MakeSky (void);
|
||||
|
||||
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
|
||||
|
||||
// flags in finalvert_t.flags
|
||||
#define ALIAS_LEFT_CLIP 0x0001
|
||||
#define ALIAS_TOP_CLIP 0x0002
|
||||
#define ALIAS_RIGHT_CLIP 0x0004
|
||||
#define ALIAS_BOTTOM_CLIP 0x0008
|
||||
#define ALIAS_Z_CLIP 0x0010
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h;
|
||||
// must be kept in sync
|
||||
#define ALIAS_XY_CLIP_MASK 0x000F
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct edge_s
|
||||
{
|
||||
fixed16_t u;
|
||||
fixed16_t u_step;
|
||||
struct edge_s *prev, *next;
|
||||
unsigned short surfs[2];
|
||||
struct edge_s *nextremove;
|
||||
float nearzi;
|
||||
medge_t *owner;
|
||||
} edge_t;
|
||||
|
||||
#endif // _R_SHARED_H_
|
||||
|
||||
#endif // SWQUAKE
|
280
engine/sw/r_sky.c
Normal file
280
engine/sw/r_sky.c
Normal 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;
|
||||
|
||||
qbyte *r_skysource;
|
||||
|
||||
int r_skymade;
|
||||
int r_skydirect; // not used?
|
||||
|
||||
|
||||
// TODO: clean up these routines
|
||||
|
||||
qbyte bottomsky[128*131];
|
||||
qbyte bottommask[128*131];
|
||||
qbyte 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-qbyte scan widths
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
R_InitSky
|
||||
|
||||
A sky texture is 256*128, with the right side being a masked overlay
|
||||
==============
|
||||
*/
|
||||
void SWR_InitSky (texture_t *mt)
|
||||
{
|
||||
int i, j;
|
||||
qbyte *src;
|
||||
|
||||
src = (qbyte *)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);
|
||||
|
||||
*(qbyte *)pnewsky = (*((qbyte *)pnewsky + 128) &
|
||||
*(qbyte *)&bottommask[ofs]) |
|
||||
*(qbyte *)&bottomsky[ofs];
|
||||
pnewsky = (unsigned *)((qbyte *)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);
|
||||
|
||||
*(qbyte *)pd = (*((qbyte *)pnewsky + 128) &
|
||||
*(qbyte *)&bottommask[ofs]) |
|
||||
*(qbyte *)&bottomsky[ofs];
|
||||
pnewsky = (unsigned *)((qbyte *)pnewsky + 1);
|
||||
pd = (unsigned *)((qbyte *)pd + 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pnewsky += 128 / sizeof (unsigned);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
R_GenSkyTile16
|
||||
=================
|
||||
*/
|
||||
void R_GenSkyTile16 (void *pdest)
|
||||
{
|
||||
int x, y;
|
||||
int ofs, baseofs;
|
||||
int xshift, yshift;
|
||||
qbyte *pnewsky;
|
||||
unsigned short *pd;
|
||||
|
||||
xshift = skytime * skyspeed;
|
||||
yshift = skytime * skyspeed;
|
||||
|
||||
pnewsky = (qbyte *)&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) &
|
||||
*(qbyte *)&bottommask[ofs]) |
|
||||
*(qbyte *)&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;
|
||||
}
|
||||
|
||||
|
401
engine/sw/r_sprite.c
Normal file
401
engine/sw/r_sprite.c
Normal file
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
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_sprite.c
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "r_local.h"
|
||||
|
||||
static int clip_current;
|
||||
static vec5_t clip_verts[2][MAXWORKINGVERTS];
|
||||
static int sprite_width, sprite_height;
|
||||
|
||||
spritedesc_t r_spritedesc;
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RotateSprite
|
||||
================
|
||||
*/
|
||||
void R_RotateSprite (float beamlength)
|
||||
{
|
||||
vec3_t vec;
|
||||
|
||||
if (beamlength == 0.0)
|
||||
return;
|
||||
|
||||
VectorScale (r_spritedesc.vpn, -beamlength, vec);
|
||||
VectorAdd (r_entorigin, vec, r_entorigin);
|
||||
VectorSubtract (modelorg, vec, modelorg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
R_ClipSpriteFace
|
||||
|
||||
Clips the winding at clip_verts[clip_current] and changes clip_current
|
||||
Throws out the back side
|
||||
==============
|
||||
*/
|
||||
int R_ClipSpriteFace (int nump, clipplane_t *pclipplane)
|
||||
{
|
||||
int i, outcount;
|
||||
float dists[MAXWORKINGVERTS+1];
|
||||
float frac, clipdist, *pclipnormal;
|
||||
float *in, *instep, *outstep, *vert2;
|
||||
|
||||
clipdist = pclipplane->dist;
|
||||
pclipnormal = pclipplane->normal;
|
||||
|
||||
// calc dists
|
||||
if (clip_current)
|
||||
{
|
||||
in = clip_verts[1][0];
|
||||
outstep = clip_verts[0][0];
|
||||
clip_current = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
in = clip_verts[0][0];
|
||||
outstep = clip_verts[1][0];
|
||||
clip_current = 1;
|
||||
}
|
||||
|
||||
instep = in;
|
||||
for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
|
||||
{
|
||||
dists[i] = DotProduct (instep, pclipnormal) - clipdist;
|
||||
}
|
||||
|
||||
// handle wraparound case
|
||||
dists[nump] = dists[0];
|
||||
Q_memcpy (instep, in, sizeof (vec5_t));
|
||||
|
||||
|
||||
// clip the winding
|
||||
instep = in;
|
||||
outcount = 0;
|
||||
|
||||
for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
|
||||
{
|
||||
if (dists[i] >= 0)
|
||||
{
|
||||
Q_memcpy (outstep, instep, sizeof (vec5_t));
|
||||
outstep += sizeof (vec5_t) / sizeof (float);
|
||||
outcount++;
|
||||
}
|
||||
|
||||
if (dists[i] == 0 || dists[i+1] == 0)
|
||||
continue;
|
||||
|
||||
if ( (dists[i] > 0) == (dists[i+1] > 0) )
|
||||
continue;
|
||||
|
||||
// split it into a new vertex
|
||||
frac = dists[i] / (dists[i] - dists[i+1]);
|
||||
|
||||
vert2 = instep + sizeof (vec5_t) / sizeof (float);
|
||||
|
||||
outstep[0] = instep[0] + frac*(vert2[0] - instep[0]);
|
||||
outstep[1] = instep[1] + frac*(vert2[1] - instep[1]);
|
||||
outstep[2] = instep[2] + frac*(vert2[2] - instep[2]);
|
||||
outstep[3] = instep[3] + frac*(vert2[3] - instep[3]);
|
||||
outstep[4] = instep[4] + frac*(vert2[4] - instep[4]);
|
||||
|
||||
outstep += sizeof (vec5_t) / sizeof (float);
|
||||
outcount++;
|
||||
}
|
||||
|
||||
return outcount;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_SetupAndDrawSprite
|
||||
================
|
||||
*/
|
||||
void R_SetupAndDrawSprite ()
|
||||
{
|
||||
int i, nump;
|
||||
float dot, scale, *pv;
|
||||
vec5_t *pverts;
|
||||
vec3_t left, up, right, down, transformed, local;
|
||||
emitpoint_t outverts[MAXWORKINGVERTS+1], *pout;
|
||||
|
||||
dot = DotProduct (r_spritedesc.vpn, modelorg);
|
||||
|
||||
// backface cull
|
||||
if (dot >= 0)
|
||||
return;
|
||||
|
||||
// build the sprite poster in worldspace
|
||||
VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->right, right);
|
||||
VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->up, up);
|
||||
VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->left, left);
|
||||
VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->down, down);
|
||||
|
||||
pverts = clip_verts[0];
|
||||
|
||||
pverts[0][0] = r_entorigin[0] + up[0] + left[0];
|
||||
pverts[0][1] = r_entorigin[1] + up[1] + left[1];
|
||||
pverts[0][2] = r_entorigin[2] + up[2] + left[2];
|
||||
pverts[0][3] = 0;
|
||||
pverts[0][4] = 0;
|
||||
|
||||
pverts[1][0] = r_entorigin[0] + up[0] + right[0];
|
||||
pverts[1][1] = r_entorigin[1] + up[1] + right[1];
|
||||
pverts[1][2] = r_entorigin[2] + up[2] + right[2];
|
||||
pverts[1][3] = sprite_width;
|
||||
pverts[1][4] = 0;
|
||||
|
||||
pverts[2][0] = r_entorigin[0] + down[0] + right[0];
|
||||
pverts[2][1] = r_entorigin[1] + down[1] + right[1];
|
||||
pverts[2][2] = r_entorigin[2] + down[2] + right[2];
|
||||
pverts[2][3] = sprite_width;
|
||||
pverts[2][4] = sprite_height;
|
||||
|
||||
pverts[3][0] = r_entorigin[0] + down[0] + left[0];
|
||||
pverts[3][1] = r_entorigin[1] + down[1] + left[1];
|
||||
pverts[3][2] = r_entorigin[2] + down[2] + left[2];
|
||||
pverts[3][3] = 0;
|
||||
pverts[3][4] = sprite_height;
|
||||
|
||||
// clip to the frustum in worldspace
|
||||
nump = 4;
|
||||
clip_current = 0;
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
nump = R_ClipSpriteFace (nump, &view_clipplanes[i]);
|
||||
if (nump < 3)
|
||||
return;
|
||||
if (nump >= MAXWORKINGVERTS)
|
||||
Sys_Error("R_SetupAndDrawSprite: too many points");
|
||||
}
|
||||
|
||||
// transform vertices into viewspace and project
|
||||
pv = &clip_verts[clip_current][0][0];
|
||||
r_spritedesc.nearzi = -999999;
|
||||
|
||||
for (i=0 ; i<nump ; i++)
|
||||
{
|
||||
VectorSubtract (pv, r_origin, local);
|
||||
TransformVector (local, transformed);
|
||||
|
||||
if (transformed[2] < NEAR_CLIP)
|
||||
transformed[2] = NEAR_CLIP;
|
||||
|
||||
pout = &outverts[i];
|
||||
pout->zi = 1.0 / transformed[2];
|
||||
if (pout->zi > r_spritedesc.nearzi)
|
||||
r_spritedesc.nearzi = pout->zi;
|
||||
|
||||
pout->s = pv[3];
|
||||
pout->t = pv[4];
|
||||
|
||||
scale = xscale * pout->zi;
|
||||
pout->u = (xcenter + scale * transformed[0]);
|
||||
|
||||
scale = yscale * pout->zi;
|
||||
pout->v = (ycenter - scale * transformed[1]);
|
||||
|
||||
pv += sizeof (vec5_t) / sizeof (pv);
|
||||
}
|
||||
|
||||
// draw it
|
||||
r_spritedesc.nump = nump;
|
||||
r_spritedesc.pverts = outverts;
|
||||
D_DrawSprite ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_GetSpriteframe
|
||||
================
|
||||
*/
|
||||
mspriteframe_t *R_GetSpriteframe (msprite_t *psprite)
|
||||
{
|
||||
mspritegroup_t *pspritegroup;
|
||||
mspriteframe_t *pspriteframe;
|
||||
int i, numframes, frame;
|
||||
float *pintervals, fullinterval, targettime, time;
|
||||
|
||||
frame = currententity->frame;
|
||||
|
||||
if ((frame >= psprite->numframes) || (frame < 0))
|
||||
{
|
||||
Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
if (psprite->frames[frame].type == SPR_SINGLE)
|
||||
{
|
||||
pspriteframe = psprite->frames[frame].frameptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
|
||||
pintervals = pspritegroup->intervals;
|
||||
numframes = pspritegroup->numframes;
|
||||
fullinterval = pintervals[numframes-1];
|
||||
|
||||
time = cl.time + currententity->syncbase;
|
||||
|
||||
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
|
||||
// are positive, so we don't have to worry about division by 0
|
||||
targettime = time - ((int)(time / fullinterval)) * fullinterval;
|
||||
|
||||
for (i=0 ; i<(numframes-1) ; i++)
|
||||
{
|
||||
if (pintervals[i] > targettime)
|
||||
break;
|
||||
}
|
||||
|
||||
pspriteframe = pspritegroup->frames[i];
|
||||
}
|
||||
|
||||
return pspriteframe;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSprite
|
||||
================
|
||||
*/
|
||||
void R_DrawSprite (void)
|
||||
{
|
||||
int i;
|
||||
msprite_t *psprite;
|
||||
vec3_t tvec;
|
||||
float dot, angle, sr, cr;
|
||||
|
||||
psprite = currententity->model->cache.data;
|
||||
|
||||
r_spritedesc.pspriteframe = R_GetSpriteframe (psprite);
|
||||
|
||||
sprite_width = r_spritedesc.pspriteframe->width;
|
||||
sprite_height = r_spritedesc.pspriteframe->height;
|
||||
|
||||
// TODO: make this caller-selectable
|
||||
if (psprite->type == SPR_FACING_UPRIGHT)
|
||||
{
|
||||
// generate the sprite's axes, with vup straight up in worldspace, and
|
||||
// r_spritedesc.vright perpendicular to modelorg.
|
||||
// This will not work if the view direction is very close to straight up or
|
||||
// down, because the cross product will be between two nearly parallel
|
||||
// vectors and starts to approach an undefined state, so we don't draw if
|
||||
// the two vectors are less than 1 degree apart
|
||||
tvec[0] = -modelorg[0];
|
||||
tvec[1] = -modelorg[1];
|
||||
tvec[2] = -modelorg[2];
|
||||
VectorNormalize (tvec);
|
||||
dot = tvec[2]; // same as DotProduct (tvec, r_spritedesc.vup) because
|
||||
// r_spritedesc.vup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848
|
||||
return;
|
||||
r_spritedesc.vup[0] = 0;
|
||||
r_spritedesc.vup[1] = 0;
|
||||
r_spritedesc.vup[2] = 1;
|
||||
r_spritedesc.vright[0] = tvec[1];
|
||||
// CrossProduct(r_spritedesc.vup, -modelorg,
|
||||
r_spritedesc.vright[1] = -tvec[0];
|
||||
// r_spritedesc.vright)
|
||||
r_spritedesc.vright[2] = 0;
|
||||
VectorNormalize (r_spritedesc.vright);
|
||||
r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
|
||||
r_spritedesc.vpn[1] = r_spritedesc.vright[0];
|
||||
r_spritedesc.vpn[2] = 0;
|
||||
// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
|
||||
// r_spritedesc.vpn)
|
||||
}
|
||||
else if (psprite->type == SPR_VP_PARALLEL)
|
||||
{
|
||||
// generate the sprite's axes, completely parallel to the viewplane. There
|
||||
// are no problem situations, because the sprite is always in the same
|
||||
// position relative to the viewer
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
r_spritedesc.vup[i] = vup[i];
|
||||
r_spritedesc.vright[i] = vright[i];
|
||||
r_spritedesc.vpn[i] = vpn[i];
|
||||
}
|
||||
}
|
||||
else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT)
|
||||
{
|
||||
// generate the sprite's axes, with vup straight up in worldspace, and
|
||||
// r_spritedesc.vright parallel to the viewplane.
|
||||
// This will not work if the view direction is very close to straight up or
|
||||
// down, because the cross product will be between two nearly parallel
|
||||
// vectors and starts to approach an undefined state, so we don't draw if
|
||||
// the two vectors are less than 1 degree apart
|
||||
dot = vpn[2]; // same as DotProduct (vpn, r_spritedesc.vup) because
|
||||
// r_spritedesc.vup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848
|
||||
return;
|
||||
r_spritedesc.vup[0] = 0;
|
||||
r_spritedesc.vup[1] = 0;
|
||||
r_spritedesc.vup[2] = 1;
|
||||
r_spritedesc.vright[0] = vpn[1];
|
||||
// CrossProduct (r_spritedesc.vup, vpn,
|
||||
r_spritedesc.vright[1] = -vpn[0]; // r_spritedesc.vright)
|
||||
r_spritedesc.vright[2] = 0;
|
||||
VectorNormalize (r_spritedesc.vright);
|
||||
r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
|
||||
r_spritedesc.vpn[1] = r_spritedesc.vright[0];
|
||||
r_spritedesc.vpn[2] = 0;
|
||||
// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
|
||||
// r_spritedesc.vpn)
|
||||
}
|
||||
else if (psprite->type == SPR_ORIENTED)
|
||||
{
|
||||
// generate the sprite's axes, according to the sprite's world orientation
|
||||
AngleVectors (currententity->angles, r_spritedesc.vpn,
|
||||
r_spritedesc.vright, r_spritedesc.vup);
|
||||
}
|
||||
else if (psprite->type == SPR_VP_PARALLEL_ORIENTED)
|
||||
{
|
||||
// generate the sprite's axes, parallel to the viewplane, but rotated in
|
||||
// that plane around the center according to the sprite entity's roll
|
||||
// angle. So vpn stays the same, but vright and vup rotate
|
||||
angle = currententity->angles[ROLL] * (M_PI*2 / 360);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
r_spritedesc.vpn[i] = vpn[i];
|
||||
r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
|
||||
r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type);
|
||||
}
|
||||
|
||||
R_RotateSprite (psprite->beamlength);
|
||||
|
||||
R_SetupAndDrawSprite ();
|
||||
}
|
||||
|
1604
engine/sw/r_surf.c
Normal file
1604
engine/sw/r_surf.c
Normal file
File diff suppressed because it is too large
Load diff
39
engine/sw/r_vars.c
Normal file
39
engine/sw/r_vars.c
Normal 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
|
||||
|
64
engine/sw/r_varsa.s
Normal file
64
engine/sw/r_varsa.s
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
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_varsa.s
|
||||
//
|
||||
|
||||
#include "asm_i386.h"
|
||||
#include "quakeasm.h"
|
||||
#include "asm_draw.h"
|
||||
#include "d_ifacea.h"
|
||||
|
||||
#if id386
|
||||
|
||||
.data
|
||||
|
||||
//-------------------------------------------------------
|
||||
// ASM-only variables
|
||||
//-------------------------------------------------------
|
||||
.globl float_1, float_particle_z_clip, float_point5
|
||||
.globl float_minus_1, float_0
|
||||
float_0: .single 0.0
|
||||
float_1: .single 1.0
|
||||
float_minus_1: .single -1.0
|
||||
float_particle_z_clip: .single PARTICLE_Z_CLIP
|
||||
float_point5: .single 0.5
|
||||
|
||||
.globl fp_16, fp_64k, fp_1m, fp_64kx64k
|
||||
.globl fp_1m_minus_1
|
||||
.globl fp_8
|
||||
fp_1m: .single 1048576.0
|
||||
fp_1m_minus_1: .single 1048575.0
|
||||
fp_64k: .single 65536.0
|
||||
fp_8: .single 8.0
|
||||
fp_16: .single 16.0
|
||||
fp_64kx64k: .long 0x4f000000 // (float)0x8000*0x10000
|
||||
|
||||
|
||||
.globl FloatZero, Float2ToThe31nd, FloatMinus2ToThe31nd
|
||||
FloatZero: .long 0
|
||||
Float2ToThe31nd: .long 0x4f000000
|
||||
FloatMinus2ToThe31nd: .long 0xcf000000
|
||||
|
||||
.globl C(r_bmodelactive)
|
||||
C(r_bmodelactive): .long 0
|
||||
|
||||
#endif // id386
|
||||
|
172
engine/sw/surf16.s
Normal file
172
engine/sw/surf16.s
Normal 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
engine/sw/surf8.s
Normal file
783
engine/sw/surf8.s
Normal 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
|
2301
engine/sw/sw_draw.c
Normal file
2301
engine/sw/sw_draw.c
Normal file
File diff suppressed because it is too large
Load diff
48
engine/sw/sw_draw.h
Normal file
48
engine/sw/sw_draw.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// draw.h -- these are the only functions outside the refresh allowed
|
||||
// to touch the vid buffer
|
||||
|
||||
void SWDraw_Init (void);
|
||||
void SWDraw_ReInit (void);
|
||||
void SWDraw_Shutdown(void);
|
||||
void SWDraw_Character (int x, int y, unsigned int num);
|
||||
void SWDraw_ColouredCharacter (int x, int y, unsigned int num);
|
||||
void SWDraw_DebugChar (qbyte num);
|
||||
void SWDraw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
|
||||
void SWDraw_Pic (int x, int y, qpic_t *pic);
|
||||
void SWDraw_TransPic (int x, int y, qpic_t *pic);
|
||||
void SWDraw_TransPicTranslate (int x, int y, qpic_t *pic, qbyte *translation);
|
||||
void SWDraw_ConsoleBackground (int lines);
|
||||
void SWDraw_EditorBackground (int lines);
|
||||
void SWDraw_BeginDisc (void);
|
||||
void SWDraw_EndDisc (void);
|
||||
void SWDraw_TileClear (int x, int y, int w, int h);
|
||||
void SWDraw_Fill (int x, int y, int w, int h, int c);
|
||||
void SWDraw_FadeScreen (void);
|
||||
void SWDraw_String (int x, int y, const qbyte *str);
|
||||
void SWDraw_Alt_String (int x, int y, const qbyte *str);
|
||||
qpic_t *SWDraw_SafePicFromWad (char *name);
|
||||
qpic_t *SWDraw_PicFromWad (char *name);
|
||||
qpic_t *SWDraw_SafeCachePic (char *path);
|
||||
qpic_t *SWDraw_CachePic (char *path);
|
||||
void SWDraw_Crosshair(void);
|
||||
|
3610
engine/sw/sw_model.c
Normal file
3610
engine/sw/sw_model.c
Normal file
File diff suppressed because it is too large
Load diff
303
engine/sw/sw_screen.c
Normal file
303
engine/sw/sw_screen.c
Normal file
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
// screen.c -- master for refresh, status bar, console, chat, notify, etc
|
||||
|
||||
#include "quakedef.h"
|
||||
#include "r_local.h"
|
||||
|
||||
|
||||
|
||||
extern qboolean scr_drawdialog;
|
||||
|
||||
extern cvar_t gl_triplebuffer;
|
||||
extern cvar_t scr_fov;
|
||||
|
||||
extern qboolean scr_initialized;
|
||||
extern float oldsbar;
|
||||
extern qboolean scr_drawloading;
|
||||
|
||||
extern float oldfov, oldscreensize;
|
||||
|
||||
|
||||
extern int scr_chatmode;
|
||||
extern cvar_t scr_chatmodecvar;
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_UpdateScreen
|
||||
|
||||
This is called every frame, and can also be called explicitly to flush
|
||||
text to the screen.
|
||||
|
||||
WARNING: be very careful calling this from elsewhere, because the refresh
|
||||
needs almost the entire 256k of stack space!
|
||||
==================
|
||||
*/
|
||||
void SWSCR_UpdateScreen (void)
|
||||
{
|
||||
int uimenu;
|
||||
vrect_t vrect;
|
||||
|
||||
if (scr_skipupdate || block_drawing)
|
||||
return;
|
||||
|
||||
if (scr_disabled_for_loading)
|
||||
{
|
||||
if (key_dest != key_console)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
{ // don't suck up any cpu if minimized
|
||||
extern int Minimized;
|
||||
|
||||
if (Minimized)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
scr_copytop = 0;
|
||||
scr_copyeverything = 0;
|
||||
|
||||
if (!scr_initialized || !con_initialized)
|
||||
return; // not initialized yet
|
||||
|
||||
uimenu = UI_MenuState();
|
||||
|
||||
//
|
||||
// check for vid changes
|
||||
//
|
||||
if (oldfov != scr_fov.value)
|
||||
{
|
||||
oldfov = scr_fov.value;
|
||||
vid.recalc_refdef = true;
|
||||
}
|
||||
|
||||
if (scr_chatmode != scr_chatmodecvar.value)
|
||||
vid.recalc_refdef = true;
|
||||
|
||||
if (oldsbar != cl_sbar.value)
|
||||
{
|
||||
oldsbar = cl_sbar.value;
|
||||
vid.recalc_refdef = true;
|
||||
}
|
||||
#ifdef TEXTEDITOR
|
||||
if (editormodal)
|
||||
{
|
||||
Editor_Draw();
|
||||
SWV_UpdatePalette ();
|
||||
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height;
|
||||
vrect.pnext = 0;
|
||||
|
||||
SWVID_Update (&vrect);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (Media_ShowFilm())
|
||||
{
|
||||
SWV_UpdatePalette ();
|
||||
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height;
|
||||
vrect.pnext = 0;
|
||||
|
||||
SWVID_Update (&vrect);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vid.recalc_refdef || scr_viewsize.modified)
|
||||
{
|
||||
// something changed, so reorder the screen
|
||||
SCR_CalcRefdef ();
|
||||
}
|
||||
|
||||
//
|
||||
// do 3D refresh drawing, and then update the screen
|
||||
//
|
||||
D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly
|
||||
|
||||
SCR_TileClear();
|
||||
SCR_SetUpToDrawConsole ();
|
||||
SCR_EraseCenterString ();
|
||||
|
||||
D_DisableBackBufferAccess (); // for adapters that can't stay mapped in
|
||||
// for linear writes all the time
|
||||
#ifdef TEXTEDIT
|
||||
if (!editormodal) //don't render view.
|
||||
#endif
|
||||
if (cl.worldmodel)
|
||||
{
|
||||
VID_LockBuffer ();
|
||||
V_RenderView ();
|
||||
VID_UnlockBuffer ();
|
||||
}
|
||||
|
||||
D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly
|
||||
|
||||
if (scr_drawloading)
|
||||
{
|
||||
SCR_DrawLoading ();
|
||||
Sbar_Draw ();
|
||||
}
|
||||
else if (scr_drawdialog)
|
||||
{
|
||||
Sbar_Draw ();
|
||||
Draw_FadeScreen ();
|
||||
SCR_DrawNotifyString ();
|
||||
scr_copyeverything = true;
|
||||
}
|
||||
else if (cl.intermission == 1 && key_dest == key_game)
|
||||
{
|
||||
Sbar_IntermissionOverlay ();
|
||||
}
|
||||
else if (cl.intermission == 2 && key_dest == key_game)
|
||||
{
|
||||
Sbar_FinaleOverlay ();
|
||||
SCR_CheckDrawCenterString ();
|
||||
}
|
||||
else
|
||||
{
|
||||
Draw_Crosshair();
|
||||
|
||||
SCR_DrawRam ();
|
||||
SCR_DrawNet ();
|
||||
SCR_DrawTurtle ();
|
||||
SCR_DrawPause ();
|
||||
SCR_DrawFPS ();
|
||||
SCR_CheckDrawCenterString ();
|
||||
Sbar_Draw ();
|
||||
#ifdef TEXTEDITOR
|
||||
if (editoractive)
|
||||
Editor_Draw();
|
||||
#endif
|
||||
SCR_DrawConsole (false);
|
||||
M_Draw (uimenu);
|
||||
}
|
||||
|
||||
|
||||
D_DisableBackBufferAccess (); // for adapters that can't stay mapped in
|
||||
// for linear writes all the time
|
||||
|
||||
SWV_UpdatePalette ();
|
||||
|
||||
//
|
||||
// update one of three areas
|
||||
//
|
||||
if (scr_copyeverything)
|
||||
{
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height;
|
||||
vrect.pnext = 0;
|
||||
|
||||
SWVID_Update (&vrect);
|
||||
}
|
||||
else if (scr_copytop)
|
||||
{
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height - sb_lines;
|
||||
vrect.pnext = 0;
|
||||
|
||||
SWVID_Update (&vrect);
|
||||
}
|
||||
else
|
||||
{
|
||||
vrect.x = scr_vrect.x;
|
||||
vrect.y = scr_vrect.y;
|
||||
vrect.width = scr_vrect.width;
|
||||
vrect.height = scr_vrect.height;
|
||||
vrect.pnext = 0;
|
||||
|
||||
SWVID_Update (&vrect);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_UpdateWholeScreen
|
||||
==================
|
||||
*/
|
||||
void SCR_UpdateWholeScreen (void)
|
||||
{
|
||||
scr_fullupdate = 0;
|
||||
SCR_UpdateScreen ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char *SWVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight)
|
||||
{ //returns a BZ_Malloced array
|
||||
qbyte *ret = BZ_Malloc(prepadbytes + vid.width*vid.height*3);
|
||||
|
||||
qbyte *dest, *src;
|
||||
int y, x;
|
||||
|
||||
extern unsigned char vid_curpal[256*3];
|
||||
|
||||
if (r_pixbytes == 4)
|
||||
{ //32 bit to 24
|
||||
dest = ret+prepadbytes + vid.width*3*(vid.height-1);
|
||||
|
||||
for (y=0 ; y<vid.height ; y++, dest -= vid.width*3)
|
||||
{
|
||||
src = vid.buffer + y*vid.rowbytes*4;
|
||||
for (x=0 ; x<vid.width*3 ; x+=3, src+=4)
|
||||
{
|
||||
dest[x] = src[2];
|
||||
dest[x+1] = src[1];
|
||||
dest[x+2] = src[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //8bit to 24 using palette lookups
|
||||
dest = ret+prepadbytes + vid.width*3*(vid.height-1);
|
||||
|
||||
for (y=0 ; y<vid.height ; y++, dest -= vid.width*3)
|
||||
{
|
||||
src = vid.buffer + y*vid.rowbytes;
|
||||
for (x=0 ; x<vid.width*3 ; x+=3, src++)
|
||||
{
|
||||
dest[x] = vid_curpal[*src*3];
|
||||
dest[x+1] = vid_curpal[*src*3+1];
|
||||
dest[x+2] = vid_curpal[*src*3+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*truewidth = vid.width;
|
||||
*trueheight = vid.height;
|
||||
|
||||
return ret;
|
||||
}
|
722
engine/sw/vid_ddraw.c
Normal file
722
engine/sw/vid_ddraw.c
Normal file
|
@ -0,0 +1,722 @@
|
|||
#include "quakedef.h"
|
||||
#include "winquake.h"
|
||||
|
||||
qboolean vid_palettized;
|
||||
#ifndef NODIRECTX
|
||||
|
||||
HMODULE hinstDDRAW;
|
||||
LPDIRECTDRAW lpDirectDraw;
|
||||
LPDIRECTDRAWSURFACE lpddsFrontBuffer, lpddsBackBuffer, lpddsOffScreenBuffer;
|
||||
LPDIRECTDRAWPALETTE lpddpPalette;
|
||||
extern qbyte vid_curpal[];
|
||||
|
||||
qboolean modex;
|
||||
qboolean vid_initialized;
|
||||
|
||||
|
||||
extern int redbits, redshift;
|
||||
extern int greenbits, greenshift;
|
||||
extern int bluebits, blueshift;
|
||||
|
||||
|
||||
//end
|
||||
|
||||
static const char *DDrawError (int code);
|
||||
|
||||
/*
|
||||
** DDRAW_SetPalette
|
||||
**
|
||||
** Sets the color table in our DIB section, and also sets the system palette
|
||||
** into an identity mode if we're running in an 8-bit palettized display mode.
|
||||
**
|
||||
** The palette is expected to be 1024 bytes, in the format:
|
||||
**
|
||||
** R = offset 0
|
||||
** G = offset 1
|
||||
** B = offset 2
|
||||
** A = offset 3
|
||||
*/
|
||||
void DDRAW_SetPalette( const unsigned char *pal )
|
||||
{
|
||||
static PALETTEENTRY palentries[256]; //does this help any drivers - being static?
|
||||
int i;
|
||||
|
||||
if (!lpddpPalette)
|
||||
return;
|
||||
|
||||
for ( i = 0; i < 256; i++, pal += 3 )
|
||||
{
|
||||
palentries[i].peRed = pal[0];
|
||||
palentries[i].peGreen = pal[1];
|
||||
palentries[i].peBlue = pal[2];
|
||||
palentries[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE;
|
||||
}
|
||||
if ( lpddpPalette->lpVtbl->SetEntries( lpddpPalette,
|
||||
0,
|
||||
0,
|
||||
256,
|
||||
palentries ) != DD_OK )
|
||||
{
|
||||
Con_Printf( "DDRAW_SetPalette() - SetEntries failed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DDRAW_Shutdown(void)
|
||||
{
|
||||
if ( lpddsOffScreenBuffer )
|
||||
{
|
||||
Con_SafePrintf( "...releasing offscreen buffer\n");
|
||||
lpddsOffScreenBuffer->lpVtbl->Unlock( lpddsOffScreenBuffer, vid.buffer );
|
||||
lpddsOffScreenBuffer->lpVtbl->Release( lpddsOffScreenBuffer );
|
||||
lpddsOffScreenBuffer = NULL;
|
||||
}
|
||||
if ( lpddsBackBuffer )
|
||||
{
|
||||
Con_SafePrintf( "...releasing back buffer\n");
|
||||
lpddsBackBuffer->lpVtbl->Release( lpddsBackBuffer );
|
||||
lpddsBackBuffer = NULL;
|
||||
}
|
||||
if ( lpddsFrontBuffer )
|
||||
{
|
||||
Con_SafePrintf( "...releasing front buffer\n");
|
||||
lpddsFrontBuffer->lpVtbl->Release( lpddsFrontBuffer );
|
||||
lpddsFrontBuffer = NULL;
|
||||
}
|
||||
if ( lpddpPalette)
|
||||
{
|
||||
Con_SafePrintf( "...releasing palette\n");
|
||||
lpddpPalette->lpVtbl->Release ( lpddpPalette );
|
||||
lpddpPalette = NULL;
|
||||
}
|
||||
if ( lpDirectDraw )
|
||||
{
|
||||
Con_SafePrintf( "...restoring display mode\n");
|
||||
lpDirectDraw->lpVtbl->RestoreDisplayMode( lpDirectDraw );
|
||||
Con_SafePrintf( "...restoring normal coop mode\n");
|
||||
lpDirectDraw->lpVtbl->SetCooperativeLevel( lpDirectDraw, mainwindow, DDSCL_NORMAL );
|
||||
Con_SafePrintf( "...releasing lpDirectDraw\n");
|
||||
lpDirectDraw->lpVtbl->Release( lpDirectDraw );
|
||||
lpDirectDraw = NULL;
|
||||
}
|
||||
if ( hinstDDRAW )
|
||||
{
|
||||
Con_SafePrintf( "...freeing library\n");
|
||||
FreeLibrary( hinstDDRAW );
|
||||
hinstDDRAW = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
unsigned short LowBitPos(DWORD dword)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
if (dword & (1<<i))
|
||||
return i;
|
||||
}
|
||||
return 32;
|
||||
}
|
||||
|
||||
unsigned short HighBitPos(DWORD dword)
|
||||
{
|
||||
int i;
|
||||
for (i = LowBitPos(dword); ; i++)
|
||||
{
|
||||
if (!(dword & (1<<i)))
|
||||
return i;
|
||||
}
|
||||
return 32;
|
||||
}
|
||||
|
||||
|
||||
qboolean DDRAW_Init(rendererstate_t *info, unsigned char **ppbuffer, int *ppitch )
|
||||
{
|
||||
int i;
|
||||
PALETTEENTRY palentries[256];
|
||||
DDSURFACEDESC ddsd;
|
||||
DDSCAPS ddscaps;
|
||||
|
||||
HRESULT ddrval;
|
||||
HRESULT (WINAPI *QDirectDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR * lplpDDRAW, IUnknown FAR * pUnkOuter );
|
||||
|
||||
hinstDDRAW = LoadLibrary( "ddraw.dll" );
|
||||
if (!hinstDDRAW)
|
||||
{
|
||||
Con_Printf( "Failed to load ddraw.dll");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( ( QDirectDrawCreate = ( HRESULT (WINAPI *)( GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR * ) ) GetProcAddress( hinstDDRAW, "DirectDrawCreate" ) ) == NULL )
|
||||
{
|
||||
Con_Printf( "*** DirectDrawCreate == NULL ***\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( ( ddrval = QDirectDrawCreate( NULL, &lpDirectDraw, NULL ) ) != DD_OK )
|
||||
{
|
||||
Con_Printf( "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/*
|
||||
** see if linear modes exist first
|
||||
*/
|
||||
modex = false;
|
||||
|
||||
Con_SafePrintf( "...setting exclusive mode: ");
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->SetCooperativeLevel( lpDirectDraw,
|
||||
mainwindow,
|
||||
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n",DDrawError (ddrval) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
/*
|
||||
** try changing the display mode normally
|
||||
*/
|
||||
Con_SafePrintf( "...finding display mode\n" );
|
||||
Con_SafePrintf( "...setting linear mode: " );
|
||||
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->SetDisplayMode( lpDirectDraw, vid.width, vid.height, r_pixbytes*8 ) ) == DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "ok\n" );
|
||||
}
|
||||
/*
|
||||
** if no linear mode found, go for modex if we're trying 320x240
|
||||
*/
|
||||
else if ( ( vid.width==320 && vid.height==240 ) && info->allow_modex )
|
||||
{
|
||||
Con_SafePrintf( "failed\n" );
|
||||
Con_SafePrintf( "...attempting ModeX 320x240: ");
|
||||
|
||||
/*
|
||||
** reset to normal cooperative level
|
||||
*/
|
||||
lpDirectDraw->lpVtbl->SetCooperativeLevel( lpDirectDraw,
|
||||
mainwindow,
|
||||
DDSCL_NORMAL );
|
||||
|
||||
/*
|
||||
** set exclusive mode
|
||||
*/
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->SetCooperativeLevel( lpDirectDraw,
|
||||
mainwindow,
|
||||
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES | DDSCL_ALLOWMODEX | DDSCL_ALLOWREBOOT) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed SCL - %s\n",DDrawError (ddrval) );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
** change our display mode
|
||||
*/
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->SetDisplayMode( lpDirectDraw, vid.width, vid.height, r_pixbytes*8 ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed SDM - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
modex = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_SafePrintf( "failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
** create our front buffer
|
||||
*/
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
|
||||
ddsd.dwBackBufferCount = 1;
|
||||
|
||||
Con_SafePrintf( "...creating front buffer: ");
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->CreateSurface( lpDirectDraw, &ddsd, &lpddsFrontBuffer, NULL ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
#else
|
||||
Con_SafePrintf( "...setting normal mode: ");
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->SetCooperativeLevel( lpDirectDraw,
|
||||
mainwindow,
|
||||
DDSCL_NORMAL ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n",DDrawError (ddrval) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
|
||||
i = r_pixbytes;
|
||||
if (vid_use32bit.value)
|
||||
r_pixbytes = 4;
|
||||
else
|
||||
r_pixbytes = 1;
|
||||
|
||||
if (r_pixbytes != i && cls.state)
|
||||
{
|
||||
Con_Printf("Cannot change bpp when connected\n");
|
||||
r_pixbytes = i;
|
||||
}
|
||||
|
||||
/*
|
||||
** try changing the display mode
|
||||
*/
|
||||
/* if ( ( ddrval = lpDirectDraw->lpVtbl->SetDisplayMode( lpDirectDraw, vid.width, vid.height, r_pixbytes*8 ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n",DDrawError (ddrval) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
*/
|
||||
|
||||
/*
|
||||
** create our front buffer
|
||||
*/
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
ddsd.dwFlags = /*DDSD_CAPS |*/ DDSD_BACKBUFFERCOUNT;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX;
|
||||
ddsd.dwBackBufferCount = 1;
|
||||
|
||||
Con_SafePrintf( "...creating front buffer: ");
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->CreateSurface( lpDirectDraw, &ddsd, &lpddsFrontBuffer, NULL ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
#endif
|
||||
|
||||
/*
|
||||
** see if we're a ModeX mode
|
||||
*/
|
||||
lpddsFrontBuffer->lpVtbl->GetCaps( lpddsFrontBuffer, &ddscaps );
|
||||
if ( ddscaps.dwCaps & DDSCAPS_MODEX )
|
||||
Con_SafePrintf( "...using ModeX\n" );
|
||||
|
||||
/*
|
||||
** create our back buffer
|
||||
*/
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||||
|
||||
Con_SafePrintf( "...creating back buffer: " );
|
||||
if ( ( ddrval = lpddsFrontBuffer->lpVtbl->GetAttachedSurface( lpddsFrontBuffer, &ddsd.ddsCaps, &lpddsBackBuffer ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
/*
|
||||
** create our rendering buffer
|
||||
*/
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||||
ddsd.dwHeight = vid.height;
|
||||
ddsd.dwWidth = vid.width;
|
||||
ddsd.dwRefreshRate = info->rate;
|
||||
if (ddsd.dwRefreshRate)
|
||||
ddsd.dwFlags |= DDSD_REFRESHRATE;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
|
||||
Con_SafePrintf( "...creating offscreen buffer: " );
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->CreateSurface( lpDirectDraw, &ddsd, &lpddsOffScreenBuffer, NULL ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
if (r_pixbytes == 1)
|
||||
{
|
||||
/*
|
||||
** create our DIRECTDRAWPALETTE
|
||||
*/
|
||||
Con_SafePrintf( "...creating palette: " );
|
||||
if ( ( ddrval = lpDirectDraw->lpVtbl->CreatePalette( lpDirectDraw,
|
||||
DDPCAPS_8BIT | DDPCAPS_ALLOW256,
|
||||
palentries,
|
||||
&lpddpPalette,
|
||||
NULL ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
Con_SafePrintf( "...setting palette: " );
|
||||
if ( ( ddrval = lpddsFrontBuffer->lpVtbl->SetPalette( lpddsFrontBuffer,
|
||||
lpddpPalette ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
DDRAW_SetPalette( ( const unsigned char * ) vid_curpal );
|
||||
|
||||
vid_palettized = true;
|
||||
}
|
||||
/*
|
||||
** lock the back buffer
|
||||
*/
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
|
||||
Con_SafePrintf( "...locking backbuffer: " );
|
||||
if ( ( ddrval = lpddsOffScreenBuffer->lpVtbl->Lock( lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL ) ) != DD_OK )
|
||||
{
|
||||
Con_SafePrintf( "failed - %s\n", DDrawError( ddrval ) );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
|
||||
if (r_pixbytes == 2)
|
||||
{
|
||||
DDPIXELFORMAT format;
|
||||
format.dwSize = sizeof(format);
|
||||
Con_SafePrintf( "...getting pixel format: " );
|
||||
if (lpddsFrontBuffer->lpVtbl->GetPixelFormat(lpddsFrontBuffer, &format) == DD_OK)
|
||||
{
|
||||
int hi, lo;
|
||||
lo = LowBitPos(format.dwRBitMask);
|
||||
hi = HighBitPos(format.dwRBitMask);
|
||||
Con_SafePrintf("Hi=%i, Low=%i\n", hi, lo);
|
||||
redshift = lo;
|
||||
redbits = hi-lo;
|
||||
|
||||
lo = LowBitPos(format.dwGBitMask);
|
||||
hi = HighBitPos(format.dwGBitMask);
|
||||
Con_SafePrintf("Hi=%i, Low=%i\n", hi, lo);
|
||||
greenshift = lo;
|
||||
greenbits = hi-lo;
|
||||
|
||||
lo = LowBitPos(format.dwBBitMask);
|
||||
hi = HighBitPos(format.dwBBitMask);
|
||||
Con_SafePrintf("Hi=%i, Low=%i\n", hi, lo);
|
||||
blueshift = lo;
|
||||
bluebits = hi-lo;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_SafePrintf( "failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
Con_SafePrintf( "ok\n" );
|
||||
}
|
||||
|
||||
*ppbuffer = ddsd.lpSurface;
|
||||
*ppitch = ddsd.lPitch/r_pixbytes;
|
||||
|
||||
for ( i = 0; i < vid.height; i++ )
|
||||
{
|
||||
memset( *ppbuffer + i * *ppitch, 0, *ppitch );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
Con_SafePrintf( "*** DDraw init failure ***\n" );
|
||||
DDRAW_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const char *DDrawError (int code)
|
||||
{
|
||||
switch(code) {
|
||||
case DD_OK:
|
||||
return "DD_OK";
|
||||
case DDERR_ALREADYINITIALIZED:
|
||||
return "DDERR_ALREADYINITIALIZED";
|
||||
case DDERR_BLTFASTCANTCLIP:
|
||||
return "DDERR_BLTFASTCANTCLIP";
|
||||
case DDERR_CANNOTATTACHSURFACE:
|
||||
return "DDER_CANNOTATTACHSURFACE";
|
||||
case DDERR_CANNOTDETACHSURFACE:
|
||||
return "DDERR_CANNOTDETACHSURFACE";
|
||||
case DDERR_CANTCREATEDC:
|
||||
return "DDERR_CANTCREATEDC";
|
||||
case DDERR_CANTDUPLICATE:
|
||||
return "DDER_CANTDUPLICATE";
|
||||
case DDERR_CLIPPERISUSINGHWND:
|
||||
return "DDER_CLIPPERUSINGHWND";
|
||||
case DDERR_COLORKEYNOTSET:
|
||||
return "DDERR_COLORKEYNOTSET";
|
||||
case DDERR_CURRENTLYNOTAVAIL:
|
||||
return "DDERR_CURRENTLYNOTAVAIL";
|
||||
case DDERR_DIRECTDRAWALREADYCREATED:
|
||||
return "DDERR_DIRECTDRAWALREADYCREATED";
|
||||
case DDERR_EXCEPTION:
|
||||
return "DDERR_EXCEPTION";
|
||||
case DDERR_EXCLUSIVEMODEALREADYSET:
|
||||
return "DDERR_EXCLUSIVEMODEALREADYSET";
|
||||
case DDERR_GENERIC:
|
||||
return "DDERR_GENERIC";
|
||||
case DDERR_HEIGHTALIGN:
|
||||
return "DDERR_HEIGHTALIGN";
|
||||
case DDERR_HWNDALREADYSET:
|
||||
return "DDERR_HWNDALREADYSET";
|
||||
case DDERR_HWNDSUBCLASSED:
|
||||
return "DDERR_HWNDSUBCLASSED";
|
||||
case DDERR_IMPLICITLYCREATED:
|
||||
return "DDERR_IMPLICITLYCREATED";
|
||||
case DDERR_INCOMPATIBLEPRIMARY:
|
||||
return "DDERR_INCOMPATIBLEPRIMARY";
|
||||
case DDERR_INVALIDCAPS:
|
||||
return "DDERR_INVALIDCAPS";
|
||||
case DDERR_INVALIDCLIPLIST:
|
||||
return "DDERR_INVALIDCLIPLIST";
|
||||
case DDERR_INVALIDDIRECTDRAWGUID:
|
||||
return "DDERR_INVALIDDIRECTDRAWGUID";
|
||||
case DDERR_INVALIDMODE:
|
||||
return "DDERR_INVALIDMODE";
|
||||
case DDERR_INVALIDOBJECT:
|
||||
return "DDERR_INVALIDOBJECT";
|
||||
case DDERR_INVALIDPARAMS:
|
||||
return "DDERR_INVALIDPARAMS";
|
||||
case DDERR_INVALIDPIXELFORMAT:
|
||||
return "DDERR_INVALIDPIXELFORMAT";
|
||||
case DDERR_INVALIDPOSITION:
|
||||
return "DDERR_INVALIDPOSITION";
|
||||
case DDERR_INVALIDRECT:
|
||||
return "DDERR_INVALIDRECT";
|
||||
case DDERR_LOCKEDSURFACES:
|
||||
return "DDERR_LOCKEDSURFACES";
|
||||
case DDERR_NO3D:
|
||||
return "DDERR_NO3D";
|
||||
case DDERR_NOALPHAHW:
|
||||
return "DDERR_NOALPHAHW";
|
||||
case DDERR_NOBLTHW:
|
||||
return "DDERR_NOBLTHW";
|
||||
case DDERR_NOCLIPLIST:
|
||||
return "DDERR_NOCLIPLIST";
|
||||
case DDERR_NOCLIPPERATTACHED:
|
||||
return "DDERR_NOCLIPPERATTACHED";
|
||||
case DDERR_NOCOLORCONVHW:
|
||||
return "DDERR_NOCOLORCONVHW";
|
||||
case DDERR_NOCOLORKEY:
|
||||
return "DDERR_NOCOLORKEY";
|
||||
case DDERR_NOCOLORKEYHW:
|
||||
return "DDERR_NOCOLORKEYHW";
|
||||
case DDERR_NOCOOPERATIVELEVELSET:
|
||||
return "DDERR_NOCOOPERATIVELEVELSET";
|
||||
case DDERR_NODC:
|
||||
return "DDERR_NODC";
|
||||
case DDERR_NODDROPSHW:
|
||||
return "DDERR_NODDROPSHW";
|
||||
case DDERR_NODIRECTDRAWHW:
|
||||
return "DDERR_NODIRECTDRAWHW";
|
||||
case DDERR_NOEMULATION:
|
||||
return "DDERR_NOEMULATION";
|
||||
case DDERR_NOEXCLUSIVEMODE:
|
||||
return "DDERR_NOEXCLUSIVEMODE";
|
||||
case DDERR_NOFLIPHW:
|
||||
return "DDERR_NOFLIPHW";
|
||||
case DDERR_NOGDI:
|
||||
return "DDERR_NOGDI";
|
||||
case DDERR_NOHWND:
|
||||
return "DDERR_NOHWND";
|
||||
case DDERR_NOMIRRORHW:
|
||||
return "DDERR_NOMIRRORHW";
|
||||
case DDERR_NOOVERLAYDEST:
|
||||
return "DDERR_NOOVERLAYDEST";
|
||||
case DDERR_NOOVERLAYHW:
|
||||
return "DDERR_NOOVERLAYHW";
|
||||
case DDERR_NOPALETTEATTACHED:
|
||||
return "DDERR_NOPALETTEATTACHED";
|
||||
case DDERR_NOPALETTEHW:
|
||||
return "DDERR_NOPALETTEHW";
|
||||
case DDERR_NORASTEROPHW:
|
||||
return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
|
||||
case DDERR_NOROTATIONHW:
|
||||
return "Operation could not be carried out because there is no rotation hardware present or available.\0";
|
||||
case DDERR_NOSTRETCHHW:
|
||||
return "Operation could not be carried out because there is no hardware support for stretching.\0";
|
||||
case DDERR_NOT4BITCOLOR:
|
||||
return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
|
||||
case DDERR_NOT4BITCOLORINDEX:
|
||||
return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
|
||||
case DDERR_NOT8BITCOLOR:
|
||||
return "DDERR_NOT8BITCOLOR";
|
||||
case DDERR_NOTAOVERLAYSURFACE:
|
||||
return "Returned when an overlay member is called for a non-overlay surface.\0";
|
||||
case DDERR_NOTEXTUREHW:
|
||||
return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
|
||||
case DDERR_NOTFLIPPABLE:
|
||||
return "DDERR_NOTFLIPPABLE";
|
||||
case DDERR_NOTFOUND:
|
||||
return "DDERR_NOTFOUND";
|
||||
case DDERR_NOTLOCKED:
|
||||
return "DDERR_NOTLOCKED";
|
||||
case DDERR_NOTPALETTIZED:
|
||||
return "DDERR_NOTPALETTIZED";
|
||||
case DDERR_NOVSYNCHW:
|
||||
return "DDERR_NOVSYNCHW";
|
||||
case DDERR_NOZBUFFERHW:
|
||||
return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
|
||||
case DDERR_NOZOVERLAYHW:
|
||||
return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
|
||||
case DDERR_OUTOFCAPS:
|
||||
return "The hardware needed for the requested operation has already been allocated.\0";
|
||||
case DDERR_OUTOFMEMORY:
|
||||
return "DDERR_OUTOFMEMORY";
|
||||
case DDERR_OUTOFVIDEOMEMORY:
|
||||
return "DDERR_OUTOFVIDEOMEMORY";
|
||||
case DDERR_OVERLAYCANTCLIP:
|
||||
return "The hardware does not support clipped overlays.\0";
|
||||
case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
|
||||
return "Can only have ony color key active at one time for overlays.\0";
|
||||
case DDERR_OVERLAYNOTVISIBLE:
|
||||
return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
|
||||
case DDERR_PALETTEBUSY:
|
||||
return "DDERR_PALETTEBUSY";
|
||||
case DDERR_PRIMARYSURFACEALREADYEXISTS:
|
||||
return "DDERR_PRIMARYSURFACEALREADYEXISTS";
|
||||
case DDERR_REGIONTOOSMALL:
|
||||
return "Region passed to Clipper::GetClipList is too small.\0";
|
||||
case DDERR_SURFACEALREADYATTACHED:
|
||||
return "DDERR_SURFACEALREADYATTACHED";
|
||||
case DDERR_SURFACEALREADYDEPENDENT:
|
||||
return "DDERR_SURFACEALREADYDEPENDENT";
|
||||
case DDERR_SURFACEBUSY:
|
||||
return "DDERR_SURFACEBUSY";
|
||||
case DDERR_SURFACEISOBSCURED:
|
||||
return "Access to surface refused because the surface is obscured.\0";
|
||||
case DDERR_SURFACELOST:
|
||||
return "DDERR_SURFACELOST";
|
||||
case DDERR_SURFACENOTATTACHED:
|
||||
return "DDERR_SURFACENOTATTACHED";
|
||||
case DDERR_TOOBIGHEIGHT:
|
||||
return "Height requested by DirectDraw is too large.\0";
|
||||
case DDERR_TOOBIGSIZE:
|
||||
return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
|
||||
case DDERR_TOOBIGWIDTH:
|
||||
return "Width requested by DirectDraw is too large.\0";
|
||||
case DDERR_UNSUPPORTED:
|
||||
return "DDERR_UNSUPPORTED";
|
||||
case DDERR_UNSUPPORTEDFORMAT:
|
||||
return "FOURCC format requested is unsupported by DirectDraw.\0";
|
||||
case DDERR_UNSUPPORTEDMASK:
|
||||
return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
|
||||
case DDERR_VERTICALBLANKINPROGRESS:
|
||||
return "Vertical blank is in progress.\0";
|
||||
case DDERR_WASSTILLDRAWING:
|
||||
return "DDERR_WASSTILLDRAWING";
|
||||
case DDERR_WRONGMODE:
|
||||
return "This surface can not be restored because it was created in a different mode.\0";
|
||||
case DDERR_XALIGN:
|
||||
return "Rectangle provided was not horizontally aligned on required boundary.\0";
|
||||
default:
|
||||
return "UNKNOWN\0";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DDRAW_SwapBuffers (void)
|
||||
{
|
||||
RECT r;
|
||||
HRESULT rval;
|
||||
DDSURFACEDESC ddsd;
|
||||
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = vid.width;
|
||||
r.bottom = vid.height;
|
||||
|
||||
lpddsOffScreenBuffer->lpVtbl->Unlock( lpddsOffScreenBuffer, vid.buffer );
|
||||
|
||||
if ( modex )
|
||||
{
|
||||
if ( ( rval = lpddsBackBuffer->lpVtbl->BltFast( lpddsBackBuffer,
|
||||
0, 0,
|
||||
lpddsOffScreenBuffer,
|
||||
&r,
|
||||
DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
|
||||
{
|
||||
lpddsBackBuffer->lpVtbl->Restore( lpddsBackBuffer );
|
||||
lpddsBackBuffer->lpVtbl->BltFast( lpddsBackBuffer,
|
||||
0, 0,
|
||||
lpddsOffScreenBuffer,
|
||||
&r,
|
||||
DDBLTFAST_WAIT );
|
||||
|
||||
Con_DPrintf("surface lost\n");
|
||||
}
|
||||
|
||||
if ( ( rval = lpddsFrontBuffer->lpVtbl->Flip( lpddsFrontBuffer,
|
||||
NULL, DDFLIP_WAIT ) ) == DDERR_SURFACELOST )
|
||||
{
|
||||
lpddsFrontBuffer->lpVtbl->Restore( lpddsFrontBuffer );
|
||||
lpddsFrontBuffer->lpVtbl->Flip( lpddsFrontBuffer, NULL, DDFLIP_WAIT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ( rval = lpddsBackBuffer->lpVtbl->BltFast( lpddsFrontBuffer,
|
||||
0, 0,
|
||||
lpddsOffScreenBuffer,
|
||||
&r,
|
||||
DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
|
||||
{
|
||||
lpddsBackBuffer->lpVtbl->Restore( lpddsFrontBuffer );
|
||||
lpddsBackBuffer->lpVtbl->BltFast( lpddsFrontBuffer,
|
||||
0, 0,
|
||||
lpddsOffScreenBuffer,
|
||||
&r,
|
||||
DDBLTFAST_WAIT );
|
||||
|
||||
Con_DPrintf("surface lost\n");
|
||||
}
|
||||
}
|
||||
|
||||
memset( &ddsd, 0, sizeof( ddsd ) );
|
||||
ddsd.dwSize = sizeof( ddsd );
|
||||
|
||||
if (lpddsOffScreenBuffer->lpVtbl->Lock( lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL ))
|
||||
Sys_Error("Failed to lock ddraw");
|
||||
vid.conbuffer = vid.buffer = ddsd.lpSurface;
|
||||
vid.conrowbytes = vid.rowbytes = ddsd.lPitch/r_pixbytes;
|
||||
}
|
||||
#else
|
||||
qboolean DDRAW_Init(rendererstate_t *info, unsigned char **ppbuffer, int *ppitch )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void DDRAW_SwapBuffers (void)
|
||||
{
|
||||
}
|
||||
void DDRAW_Shutdown(void)
|
||||
{
|
||||
}
|
||||
void DDRAW_SetPalette( const unsigned char *pal )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
412
engine/sw/vid_dib.c
Normal file
412
engine/sw/vid_dib.c
Normal file
|
@ -0,0 +1,412 @@
|
|||
|
||||
/*
|
||||
** This handles DIB section management under Windows.
|
||||
*/
|
||||
#include "quakedef.h"
|
||||
#include "winquake.h"
|
||||
#include "r_local.h"
|
||||
|
||||
void DIB_Shutdown( void );
|
||||
|
||||
#ifndef _WIN32
|
||||
# error You should not be trying to compile this file on this platform
|
||||
#endif
|
||||
|
||||
HDC mainhDC, hdcDIBSection;
|
||||
HBITMAP hDIBSection;
|
||||
HPALETTE hPal, hpalOld;
|
||||
qbyte *pDIBBase;
|
||||
extern qboolean vid_palettized;
|
||||
extern cvar_t vid_use32bit;
|
||||
|
||||
static qboolean s_systemcolors_saved;
|
||||
|
||||
extern int redbits, redshift;
|
||||
extern int greenbits, greenshift;
|
||||
extern int bluebits, blueshift;
|
||||
|
||||
static HGDIOBJ previously_selected_GDI_obj;
|
||||
|
||||
static int s_syspalindices[] =
|
||||
{
|
||||
COLOR_ACTIVEBORDER,
|
||||
COLOR_ACTIVECAPTION,
|
||||
COLOR_APPWORKSPACE,
|
||||
COLOR_BACKGROUND,
|
||||
COLOR_BTNFACE,
|
||||
COLOR_BTNSHADOW,
|
||||
COLOR_BTNTEXT,
|
||||
COLOR_CAPTIONTEXT,
|
||||
COLOR_GRAYTEXT,
|
||||
COLOR_HIGHLIGHT,
|
||||
COLOR_HIGHLIGHTTEXT,
|
||||
COLOR_INACTIVEBORDER,
|
||||
|
||||
COLOR_INACTIVECAPTION,
|
||||
COLOR_MENU,
|
||||
COLOR_MENUTEXT,
|
||||
COLOR_SCROLLBAR,
|
||||
COLOR_WINDOW,
|
||||
COLOR_WINDOWFRAME,
|
||||
COLOR_WINDOWTEXT
|
||||
};
|
||||
|
||||
#define NUM_SYS_COLORS ( sizeof( s_syspalindices ) / sizeof( int ) )
|
||||
|
||||
static COLORREF s_oldsyscolors[NUM_SYS_COLORS];
|
||||
|
||||
typedef struct dibinfo
|
||||
{
|
||||
BITMAPINFOHEADER header;
|
||||
RGBQUAD acolors[256];
|
||||
} dibinfo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD palVersion;
|
||||
WORD palNumEntries;
|
||||
PALETTEENTRY palEntries[256];
|
||||
} identitypalette_t;
|
||||
|
||||
static identitypalette_t s_ipal;
|
||||
|
||||
static void DIB_SaveSystemColors( void );
|
||||
static void DIB_RestoreSystemColors( void );
|
||||
|
||||
/*
|
||||
** DIB_Init
|
||||
**
|
||||
** Builds our DIB section
|
||||
*/
|
||||
qboolean DIB_Init( unsigned char **ppbuffer, int *ppitch )
|
||||
{
|
||||
dibinfo_t dibheader;
|
||||
BITMAPINFO *pbmiDIB = ( BITMAPINFO * ) &dibheader;
|
||||
int i;
|
||||
|
||||
memset( &dibheader, 0, sizeof( dibheader ) );
|
||||
|
||||
/*
|
||||
** grab a DC
|
||||
*/
|
||||
if ( !mainhDC )
|
||||
{
|
||||
if ( ( mainhDC = GetDC( mainwindow ) ) == NULL )
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
** figure out if we're running in an 8-bit display mode
|
||||
*/
|
||||
if ( GetDeviceCaps( mainhDC, RASTERCAPS ) & RC_PALETTE )
|
||||
{
|
||||
vid_palettized = true;
|
||||
|
||||
// save system colors
|
||||
if ( !s_systemcolors_saved )
|
||||
{
|
||||
DIB_SaveSystemColors();
|
||||
s_systemcolors_saved = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vid_palettized = false;
|
||||
}
|
||||
|
||||
/*
|
||||
** fill in the BITMAPINFO struct
|
||||
*/
|
||||
pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
pbmiDIB->bmiHeader.biWidth = vid.width;
|
||||
pbmiDIB->bmiHeader.biHeight = vid.height;
|
||||
pbmiDIB->bmiHeader.biPlanes = 1;
|
||||
pbmiDIB->bmiHeader.biBitCount = r_pixbytes*8;
|
||||
pbmiDIB->bmiHeader.biCompression = BI_RGB;
|
||||
pbmiDIB->bmiHeader.biSizeImage = 0;
|
||||
pbmiDIB->bmiHeader.biXPelsPerMeter = 0;
|
||||
pbmiDIB->bmiHeader.biYPelsPerMeter = 0;
|
||||
pbmiDIB->bmiHeader.biClrUsed = 0;
|
||||
pbmiDIB->bmiHeader.biClrImportant = 0;
|
||||
|
||||
/*
|
||||
** fill in the palette
|
||||
*/
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
dibheader.acolors[i].rgbRed = ( d_8to24rgbtable[i] >> 0 ) & 0xff;
|
||||
dibheader.acolors[i].rgbGreen = ( d_8to24rgbtable[i] >> 8 ) & 0xff;
|
||||
dibheader.acolors[i].rgbBlue = ( d_8to24rgbtable[i] >> 16 ) & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
** create the DIB section
|
||||
*/
|
||||
hDIBSection = CreateDIBSection( mainhDC,
|
||||
pbmiDIB,
|
||||
DIB_RGB_COLORS,
|
||||
(void**)&pDIBBase,
|
||||
NULL,
|
||||
0 );
|
||||
|
||||
if ( hDIBSection == NULL )
|
||||
{
|
||||
Con_Printf( "DIB_Init() - CreateDIBSection failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( pbmiDIB->bmiHeader.biHeight > 0 )
|
||||
{
|
||||
// bottom up
|
||||
*ppbuffer = pDIBBase + ( vid.height - 1 ) * vid.width * r_pixbytes;
|
||||
*ppitch = -(int)vid.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
// top down
|
||||
*ppbuffer = pDIBBase;
|
||||
*ppitch = vid.width;
|
||||
}
|
||||
|
||||
/*
|
||||
** clear the DIB memory buffer
|
||||
*/
|
||||
memset( pDIBBase, 0xff, vid.width * vid.height * r_pixbytes);
|
||||
|
||||
if ( ( hdcDIBSection = CreateCompatibleDC( mainhDC ) ) == NULL )
|
||||
{
|
||||
Con_Printf( "DIB_Init() - CreateCompatibleDC failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
if ( ( previously_selected_GDI_obj = SelectObject( hdcDIBSection, hDIBSection ) ) == NULL )
|
||||
{
|
||||
Con_Printf( "DIB_Init() - SelectObject failed\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
redbits = 5; redshift=10;
|
||||
greenbits = 5; greenshift=5;
|
||||
bluebits = 5; blueshift=0;
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
DIB_Shutdown();
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void DIB_Resized(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
** DIB_SetPalette
|
||||
**
|
||||
** Sets the color table in our DIB section, and also sets the system palette
|
||||
** into an identity mode if we're running in an 8-bit palettized display mode.
|
||||
**
|
||||
** The palette is expected to be 1024 bytes, in the format:
|
||||
**
|
||||
** R = offset 0
|
||||
** G = offset 1
|
||||
** B = offset 2
|
||||
** A = offset 3
|
||||
*/
|
||||
void DIB_SetPalette( const unsigned char *_pal )
|
||||
{
|
||||
const unsigned char *pal = _pal;
|
||||
LOGPALETTE *pLogPal = ( LOGPALETTE * ) &s_ipal;
|
||||
RGBQUAD colors[256];
|
||||
int i;
|
||||
int ret;
|
||||
HDC hDC = mainhDC;
|
||||
|
||||
/*
|
||||
** set the DIB color table
|
||||
*/
|
||||
if (r_pixbytes == 1 && hdcDIBSection )
|
||||
{
|
||||
for ( i = 0; i < 256; i++, pal += 3 )
|
||||
{
|
||||
colors[i].rgbRed = pal[0];
|
||||
colors[i].rgbGreen = pal[1];
|
||||
colors[i].rgbBlue = pal[2];
|
||||
colors[i].rgbReserved = 0;
|
||||
}
|
||||
|
||||
colors[0].rgbRed = 0;
|
||||
colors[0].rgbGreen = 0;
|
||||
colors[0].rgbBlue = 0;
|
||||
|
||||
colors[255].rgbRed = 0xff;
|
||||
colors[255].rgbGreen = 0xff;
|
||||
colors[255].rgbBlue = 0xff;
|
||||
|
||||
if ( SetDIBColorTable( hdcDIBSection, 0, 256, colors ) == 0 )
|
||||
{
|
||||
Con_Printf( "DIB_SetPalette() - SetDIBColorTable failed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** for 8-bit color desktop modes we set up the palette for maximum
|
||||
** speed by going into an identity palette mode.
|
||||
*/
|
||||
if ( vid_palettized )
|
||||
{
|
||||
int i;
|
||||
HPALETTE hpalOld;
|
||||
|
||||
if ( SetSystemPaletteUse( hDC, SYSPAL_NOSTATIC ) == SYSPAL_ERROR )
|
||||
{
|
||||
Sys_Error( "DIB_SetPalette() - SetSystemPaletteUse() failed\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
** destroy our old palette
|
||||
*/
|
||||
if ( hPal )
|
||||
{
|
||||
DeleteObject( hPal );
|
||||
hPal = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** take up all physical palette entries to flush out anything that's currently
|
||||
** in the palette
|
||||
*/
|
||||
pLogPal->palVersion = 0x300;
|
||||
pLogPal->palNumEntries = 256;
|
||||
|
||||
for ( i = 0, pal = _pal; i < 256; i++, pal += 3 )
|
||||
{
|
||||
pLogPal->palPalEntry[i].peRed = pal[0];
|
||||
pLogPal->palPalEntry[i].peGreen = pal[1];
|
||||
pLogPal->palPalEntry[i].peBlue = pal[2];
|
||||
pLogPal->palPalEntry[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE;
|
||||
}
|
||||
pLogPal->palPalEntry[0].peRed = 0;
|
||||
pLogPal->palPalEntry[0].peGreen = 0;
|
||||
pLogPal->palPalEntry[0].peBlue = 0;
|
||||
pLogPal->palPalEntry[0].peFlags = 0;
|
||||
pLogPal->palPalEntry[255].peRed = 0xff;
|
||||
pLogPal->palPalEntry[255].peGreen = 0xff;
|
||||
pLogPal->palPalEntry[255].peBlue = 0xff;
|
||||
pLogPal->palPalEntry[255].peFlags = 0;
|
||||
|
||||
if ( ( hPal = CreatePalette( pLogPal ) ) == NULL )
|
||||
{
|
||||
Sys_Error( "DIB_SetPalette() - CreatePalette failed(%x)\n", GetLastError() );
|
||||
}
|
||||
|
||||
if ( ( hpalOld = SelectPalette( hDC, hPal, FALSE ) ) == NULL )
|
||||
{
|
||||
Sys_Error( "DIB_SetPalette() - SelectPalette failed(%x)\n",GetLastError() );
|
||||
}
|
||||
|
||||
if ( hpalOld == NULL )
|
||||
hpalOld = hpalOld;
|
||||
|
||||
if ( ( ret = RealizePalette( hDC ) ) != pLogPal->palNumEntries )
|
||||
{
|
||||
Sys_Error( "DIB_SetPalette() - RealizePalette set %d entries\n", ret );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** DIB_Shutdown
|
||||
*/
|
||||
void DIB_Shutdown( void )
|
||||
{
|
||||
if ( vid_palettized && s_systemcolors_saved )
|
||||
DIB_RestoreSystemColors();
|
||||
|
||||
if ( hPal )
|
||||
{
|
||||
DeleteObject( hPal );
|
||||
hPal = NULL;
|
||||
}
|
||||
|
||||
if ( hpalOld )
|
||||
{
|
||||
SelectPalette( mainhDC, hpalOld, FALSE );
|
||||
RealizePalette( mainhDC );
|
||||
hpalOld = NULL;
|
||||
}
|
||||
|
||||
if ( hdcDIBSection )
|
||||
{
|
||||
SelectObject( hdcDIBSection, previously_selected_GDI_obj );
|
||||
DeleteDC( hdcDIBSection );
|
||||
hdcDIBSection = NULL;
|
||||
}
|
||||
|
||||
if ( hDIBSection )
|
||||
{
|
||||
DeleteObject( hDIBSection );
|
||||
hDIBSection = NULL;
|
||||
pDIBBase = NULL;
|
||||
}
|
||||
|
||||
if ( mainhDC )
|
||||
{
|
||||
ReleaseDC( mainwindow, mainhDC );
|
||||
mainhDC = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** DIB_Save/RestoreSystemColors
|
||||
*/
|
||||
static void DIB_RestoreSystemColors( void )
|
||||
{
|
||||
SetSystemPaletteUse( mainhDC, SYSPAL_STATIC );
|
||||
SetSysColors( NUM_SYS_COLORS, s_syspalindices, s_oldsyscolors );
|
||||
}
|
||||
|
||||
static void DIB_SaveSystemColors( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < NUM_SYS_COLORS; i++ )
|
||||
s_oldsyscolors[i] = GetSysColor( s_syspalindices[i] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DIB_SwapBuffers(void)
|
||||
{
|
||||
extern float usingstretch;
|
||||
if ( vid_palettized )
|
||||
{
|
||||
// holdpal = SelectPalette(hdcScreen, hpalDIB, FALSE);
|
||||
// RealizePalette(hdcScreen);
|
||||
}
|
||||
|
||||
if (usingstretch == 1)
|
||||
BitBlt( mainhDC,
|
||||
0, 0,
|
||||
vid.width,
|
||||
vid.height,
|
||||
hdcDIBSection,
|
||||
0, 0,
|
||||
SRCCOPY );
|
||||
else
|
||||
StretchBlt( mainhDC, //Why is StretchBlt not optimised for a scale of 2? Surly that would be a frequently used quantity?
|
||||
0, 0,
|
||||
vid.width*usingstretch,
|
||||
vid.height*usingstretch,
|
||||
hdcDIBSection,
|
||||
0, 0,
|
||||
vid.width, vid.height,
|
||||
SRCCOPY );
|
||||
|
||||
if ( vid_palettized )
|
||||
{
|
||||
// SelectPalette(hdcScreen, holdpal, FALSE);
|
||||
}
|
||||
}
|
||||
|
1066
engine/sw/vid_win2.c
Normal file
1066
engine/sw/vid_win2.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue