mirror of
https://github.com/id-Software/Quake-2.git
synced 2026-03-19 16:39:43 +01:00
The original Quake 2 sources as originally released under the GPL license on December 21, 2001.
This commit is contained in:
1077
ref_soft/adivtab.h
Normal file
1077
ref_soft/adivtab.h
Normal file
File diff suppressed because it is too large
Load Diff
181
ref_soft/anorms.h
Normal file
181
ref_soft/anorms.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
{-0.525731, 0.000000, 0.850651},
|
||||
{-0.442863, 0.238856, 0.864188},
|
||||
{-0.295242, 0.000000, 0.955423},
|
||||
{-0.309017, 0.500000, 0.809017},
|
||||
{-0.162460, 0.262866, 0.951056},
|
||||
{0.000000, 0.000000, 1.000000},
|
||||
{0.000000, 0.850651, 0.525731},
|
||||
{-0.147621, 0.716567, 0.681718},
|
||||
{0.147621, 0.716567, 0.681718},
|
||||
{0.000000, 0.525731, 0.850651},
|
||||
{0.309017, 0.500000, 0.809017},
|
||||
{0.525731, 0.000000, 0.850651},
|
||||
{0.295242, 0.000000, 0.955423},
|
||||
{0.442863, 0.238856, 0.864188},
|
||||
{0.162460, 0.262866, 0.951056},
|
||||
{-0.681718, 0.147621, 0.716567},
|
||||
{-0.809017, 0.309017, 0.500000},
|
||||
{-0.587785, 0.425325, 0.688191},
|
||||
{-0.850651, 0.525731, 0.000000},
|
||||
{-0.864188, 0.442863, 0.238856},
|
||||
{-0.716567, 0.681718, 0.147621},
|
||||
{-0.688191, 0.587785, 0.425325},
|
||||
{-0.500000, 0.809017, 0.309017},
|
||||
{-0.238856, 0.864188, 0.442863},
|
||||
{-0.425325, 0.688191, 0.587785},
|
||||
{-0.716567, 0.681718, -0.147621},
|
||||
{-0.500000, 0.809017, -0.309017},
|
||||
{-0.525731, 0.850651, 0.000000},
|
||||
{0.000000, 0.850651, -0.525731},
|
||||
{-0.238856, 0.864188, -0.442863},
|
||||
{0.000000, 0.955423, -0.295242},
|
||||
{-0.262866, 0.951056, -0.162460},
|
||||
{0.000000, 1.000000, 0.000000},
|
||||
{0.000000, 0.955423, 0.295242},
|
||||
{-0.262866, 0.951056, 0.162460},
|
||||
{0.238856, 0.864188, 0.442863},
|
||||
{0.262866, 0.951056, 0.162460},
|
||||
{0.500000, 0.809017, 0.309017},
|
||||
{0.238856, 0.864188, -0.442863},
|
||||
{0.262866, 0.951056, -0.162460},
|
||||
{0.500000, 0.809017, -0.309017},
|
||||
{0.850651, 0.525731, 0.000000},
|
||||
{0.716567, 0.681718, 0.147621},
|
||||
{0.716567, 0.681718, -0.147621},
|
||||
{0.525731, 0.850651, 0.000000},
|
||||
{0.425325, 0.688191, 0.587785},
|
||||
{0.864188, 0.442863, 0.238856},
|
||||
{0.688191, 0.587785, 0.425325},
|
||||
{0.809017, 0.309017, 0.500000},
|
||||
{0.681718, 0.147621, 0.716567},
|
||||
{0.587785, 0.425325, 0.688191},
|
||||
{0.955423, 0.295242, 0.000000},
|
||||
{1.000000, 0.000000, 0.000000},
|
||||
{0.951056, 0.162460, 0.262866},
|
||||
{0.850651, -0.525731, 0.000000},
|
||||
{0.955423, -0.295242, 0.000000},
|
||||
{0.864188, -0.442863, 0.238856},
|
||||
{0.951056, -0.162460, 0.262866},
|
||||
{0.809017, -0.309017, 0.500000},
|
||||
{0.681718, -0.147621, 0.716567},
|
||||
{0.850651, 0.000000, 0.525731},
|
||||
{0.864188, 0.442863, -0.238856},
|
||||
{0.809017, 0.309017, -0.500000},
|
||||
{0.951056, 0.162460, -0.262866},
|
||||
{0.525731, 0.000000, -0.850651},
|
||||
{0.681718, 0.147621, -0.716567},
|
||||
{0.681718, -0.147621, -0.716567},
|
||||
{0.850651, 0.000000, -0.525731},
|
||||
{0.809017, -0.309017, -0.500000},
|
||||
{0.864188, -0.442863, -0.238856},
|
||||
{0.951056, -0.162460, -0.262866},
|
||||
{0.147621, 0.716567, -0.681718},
|
||||
{0.309017, 0.500000, -0.809017},
|
||||
{0.425325, 0.688191, -0.587785},
|
||||
{0.442863, 0.238856, -0.864188},
|
||||
{0.587785, 0.425325, -0.688191},
|
||||
{0.688191, 0.587785, -0.425325},
|
||||
{-0.147621, 0.716567, -0.681718},
|
||||
{-0.309017, 0.500000, -0.809017},
|
||||
{0.000000, 0.525731, -0.850651},
|
||||
{-0.525731, 0.000000, -0.850651},
|
||||
{-0.442863, 0.238856, -0.864188},
|
||||
{-0.295242, 0.000000, -0.955423},
|
||||
{-0.162460, 0.262866, -0.951056},
|
||||
{0.000000, 0.000000, -1.000000},
|
||||
{0.295242, 0.000000, -0.955423},
|
||||
{0.162460, 0.262866, -0.951056},
|
||||
{-0.442863, -0.238856, -0.864188},
|
||||
{-0.309017, -0.500000, -0.809017},
|
||||
{-0.162460, -0.262866, -0.951056},
|
||||
{0.000000, -0.850651, -0.525731},
|
||||
{-0.147621, -0.716567, -0.681718},
|
||||
{0.147621, -0.716567, -0.681718},
|
||||
{0.000000, -0.525731, -0.850651},
|
||||
{0.309017, -0.500000, -0.809017},
|
||||
{0.442863, -0.238856, -0.864188},
|
||||
{0.162460, -0.262866, -0.951056},
|
||||
{0.238856, -0.864188, -0.442863},
|
||||
{0.500000, -0.809017, -0.309017},
|
||||
{0.425325, -0.688191, -0.587785},
|
||||
{0.716567, -0.681718, -0.147621},
|
||||
{0.688191, -0.587785, -0.425325},
|
||||
{0.587785, -0.425325, -0.688191},
|
||||
{0.000000, -0.955423, -0.295242},
|
||||
{0.000000, -1.000000, 0.000000},
|
||||
{0.262866, -0.951056, -0.162460},
|
||||
{0.000000, -0.850651, 0.525731},
|
||||
{0.000000, -0.955423, 0.295242},
|
||||
{0.238856, -0.864188, 0.442863},
|
||||
{0.262866, -0.951056, 0.162460},
|
||||
{0.500000, -0.809017, 0.309017},
|
||||
{0.716567, -0.681718, 0.147621},
|
||||
{0.525731, -0.850651, 0.000000},
|
||||
{-0.238856, -0.864188, -0.442863},
|
||||
{-0.500000, -0.809017, -0.309017},
|
||||
{-0.262866, -0.951056, -0.162460},
|
||||
{-0.850651, -0.525731, 0.000000},
|
||||
{-0.716567, -0.681718, -0.147621},
|
||||
{-0.716567, -0.681718, 0.147621},
|
||||
{-0.525731, -0.850651, 0.000000},
|
||||
{-0.500000, -0.809017, 0.309017},
|
||||
{-0.238856, -0.864188, 0.442863},
|
||||
{-0.262866, -0.951056, 0.162460},
|
||||
{-0.864188, -0.442863, 0.238856},
|
||||
{-0.809017, -0.309017, 0.500000},
|
||||
{-0.688191, -0.587785, 0.425325},
|
||||
{-0.681718, -0.147621, 0.716567},
|
||||
{-0.442863, -0.238856, 0.864188},
|
||||
{-0.587785, -0.425325, 0.688191},
|
||||
{-0.309017, -0.500000, 0.809017},
|
||||
{-0.147621, -0.716567, 0.681718},
|
||||
{-0.425325, -0.688191, 0.587785},
|
||||
{-0.162460, -0.262866, 0.951056},
|
||||
{0.442863, -0.238856, 0.864188},
|
||||
{0.162460, -0.262866, 0.951056},
|
||||
{0.309017, -0.500000, 0.809017},
|
||||
{0.147621, -0.716567, 0.681718},
|
||||
{0.000000, -0.525731, 0.850651},
|
||||
{0.425325, -0.688191, 0.587785},
|
||||
{0.587785, -0.425325, 0.688191},
|
||||
{0.688191, -0.587785, 0.425325},
|
||||
{-0.955423, 0.295242, 0.000000},
|
||||
{-0.951056, 0.162460, 0.262866},
|
||||
{-1.000000, 0.000000, 0.000000},
|
||||
{-0.850651, 0.000000, 0.525731},
|
||||
{-0.955423, -0.295242, 0.000000},
|
||||
{-0.951056, -0.162460, 0.262866},
|
||||
{-0.864188, 0.442863, -0.238856},
|
||||
{-0.951056, 0.162460, -0.262866},
|
||||
{-0.809017, 0.309017, -0.500000},
|
||||
{-0.864188, -0.442863, -0.238856},
|
||||
{-0.951056, -0.162460, -0.262866},
|
||||
{-0.809017, -0.309017, -0.500000},
|
||||
{-0.681718, 0.147621, -0.716567},
|
||||
{-0.681718, -0.147621, -0.716567},
|
||||
{-0.850651, 0.000000, -0.525731},
|
||||
{-0.688191, 0.587785, -0.425325},
|
||||
{-0.587785, 0.425325, -0.688191},
|
||||
{-0.425325, 0.688191, -0.587785},
|
||||
{-0.425325, -0.688191, -0.587785},
|
||||
{-0.587785, -0.425325, -0.688191},
|
||||
{-0.688191, -0.587785, -0.425325},
|
||||
121
ref_soft/asm_draw.h
Normal file
121
ref_soft/asm_draw.h
Normal file
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// 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_pnext 12
|
||||
#define sspan_t_size 16
|
||||
|
||||
// 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_size 140
|
||||
|
||||
// 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_size 16 // !!! if this changes, array indexing in !!!
|
||||
// !!! d_polysa.s must be changed to match !!!
|
||||
#define mtri_shift 4
|
||||
|
||||
116
ref_soft/block16.inc
Normal file
116
ref_soft/block16.inc
Normal file
@@ -0,0 +1,116 @@
|
||||
LEnter16_16:
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch0:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch1:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch2:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch3:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch4:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch5:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch6:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch7:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
LEnter8_16:
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch8:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch9:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch10:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch11:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
LEnter4_16:
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch12:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch13:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
LEnter2_16:
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch14:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch15:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
116
ref_soft/block8.inc
Normal file
116
ref_soft/block8.inc
Normal file
@@ -0,0 +1,116 @@
|
||||
LEnter16_16:
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch0:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch1:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch2:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch3:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch4:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch5:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch6:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch7:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
LEnter8_16:
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch8:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch9:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch10:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch11:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
LEnter4_16:
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch12:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch13:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
LEnter2_16:
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov cl,ds:byte ptr[esi+ebx]
|
||||
mov ah,dh
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
lea esi,ds:dword ptr[esi+ebx*2]
|
||||
mov ax,ds:word ptr[12345678h+eax*2]
|
||||
LBPatch14:
|
||||
add edx,ebp
|
||||
mov ds:word ptr[edi],ax
|
||||
mov cx,ds:word ptr[12345678h+ecx*2]
|
||||
LBPatch15:
|
||||
mov ds:word ptr[2+edi],cx
|
||||
add edi,04h
|
||||
81
ref_soft/d_if.inc
Normal file
81
ref_soft/d_if.inc
Normal file
@@ -0,0 +1,81 @@
|
||||
;
|
||||
; 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 !!!
|
||||
ALIAS_ONSEAM equ 00020h
|
||||
|
||||
; !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
TURB_TEX_SIZE equ 64
|
||||
|
||||
; !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
CYCLE equ 128
|
||||
|
||||
; !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
MAXHEIGHT equ 1024
|
||||
|
||||
; !!! if this is changed, it must be changed in quakedef.h too !!!
|
||||
CACHE_SIZE equ 32
|
||||
|
||||
; particle_t structure
|
||||
; !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
; driver-usable fields
|
||||
pt_org equ 0
|
||||
pt_color equ 12
|
||||
; drivers never touch the following fields
|
||||
pt_next equ 16
|
||||
pt_vel equ 20
|
||||
pt_ramp equ 32
|
||||
pt_die equ 36
|
||||
pt_type equ 40
|
||||
pt_size equ 44
|
||||
|
||||
PARTICLE_Z_CLIP equ 8.0
|
||||
|
||||
; finalvert_t structure
|
||||
; !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
fv_v equ 0 ; !!! if this is moved, cases where the !!!
|
||||
; !!! address of this field is pushed in !!!
|
||||
; !!! d_polysa.s must be changed !!!
|
||||
fv_flags equ 24
|
||||
fv_reserved equ 28
|
||||
fv_size equ 32
|
||||
fv_shift equ 5
|
||||
|
||||
|
||||
; stvert_t structure
|
||||
; !!! if this is changed, it must be changed in modelgen.h too !!!
|
||||
stv_onseam equ 0
|
||||
stv_s equ 4
|
||||
stv_t equ 8
|
||||
stv_size equ 12
|
||||
|
||||
|
||||
; trivertx_t structure
|
||||
; !!! if this is changed, it must be changed in modelgen.h too !!!
|
||||
tv_v equ 0
|
||||
tv_lightnormalindex equ 3
|
||||
tv_size equ 4
|
||||
|
||||
; affinetridesc_t structure
|
||||
; !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||
atd_pskin equ 0
|
||||
atd_pskindesc equ 4
|
||||
atd_skinwidth equ 8
|
||||
atd_skinheight equ 12
|
||||
atd_ptriangles equ 16
|
||||
atd_pfinalverts equ 20
|
||||
atd_numtriangles equ 24
|
||||
atd_drawtype equ 28
|
||||
atd_seamfixupX16 equ 32
|
||||
atd_do_vis_thresh equ 36
|
||||
atd_vis_thresh equ 40
|
||||
atd_size equ 44
|
||||
|
||||
76
ref_soft/d_ifacea.h
Normal file
76
ref_soft/d_ifacea.h
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// 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 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 1200
|
||||
|
||||
// !!! if this is changed, it must be changed in qcommon.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_onseam 0
|
||||
#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
|
||||
|
||||
435
ref_soft/qasm.inc
Normal file
435
ref_soft/qasm.inc
Normal file
@@ -0,0 +1,435 @@
|
||||
;
|
||||
; qasm.inc
|
||||
;
|
||||
; Include file for asm routines.
|
||||
;
|
||||
|
||||
;
|
||||
; !!! note that this file must match the corresponding C structures at all
|
||||
; times !!!
|
||||
;
|
||||
|
||||
; set to 0 to skip all asm code
|
||||
id386 equ 1
|
||||
|
||||
; !!! must be kept the same as in d_iface.h !!!
|
||||
TRANSPARENT_COLOR equ 255
|
||||
|
||||
ifndef GLQUAKE
|
||||
externdef _d_zistepu:dword
|
||||
externdef _d_pzbuffer:dword
|
||||
externdef _d_zistepv:dword
|
||||
externdef _d_zrowbytes:dword
|
||||
externdef _d_ziorigin:dword
|
||||
externdef _r_turb_s:dword
|
||||
externdef _r_turb_t:dword
|
||||
externdef _r_turb_pdest:dword
|
||||
externdef _r_turb_spancount:dword
|
||||
externdef _r_turb_turb:dword
|
||||
externdef _r_turb_pbase:dword
|
||||
externdef _r_turb_sstep:dword
|
||||
externdef _r_turb_tstep:dword
|
||||
externdef _r_bmodelactive:dword
|
||||
externdef _d_sdivzstepu:dword
|
||||
externdef _d_tdivzstepu:dword
|
||||
externdef _d_sdivzstepv:dword
|
||||
externdef _d_tdivzstepv:dword
|
||||
externdef _d_sdivzorigin:dword
|
||||
externdef _d_tdivzorigin:dword
|
||||
externdef _sadjust:dword
|
||||
externdef _tadjust:dword
|
||||
externdef _bbextents:dword
|
||||
externdef _bbextentt:dword
|
||||
externdef _cacheblock:dword
|
||||
externdef _d_viewbuffer:dword
|
||||
externdef _cachewidth:dword
|
||||
externdef _d_pzbuffer:dword
|
||||
externdef _d_zrowbytes:dword
|
||||
externdef _d_zwidth:dword
|
||||
externdef _d_scantable:dword
|
||||
externdef _r_lightptr:dword
|
||||
externdef _r_numvblocks:dword
|
||||
externdef _prowdestbase:dword
|
||||
externdef _pbasesource:dword
|
||||
externdef _r_lightwidth:dword
|
||||
externdef _lightright:dword
|
||||
externdef _lightrightstep:dword
|
||||
externdef _lightdeltastep:dword
|
||||
externdef _lightdelta:dword
|
||||
externdef _lightright:dword
|
||||
externdef _lightdelta:dword
|
||||
externdef _sourcetstep:dword
|
||||
externdef _surfrowbytes:dword
|
||||
externdef _lightrightstep:dword
|
||||
externdef _lightdeltastep:dword
|
||||
externdef _r_sourcemax:dword
|
||||
externdef _r_stepback:dword
|
||||
externdef _colormap:dword
|
||||
externdef _blocksize:dword
|
||||
externdef _sourcesstep:dword
|
||||
externdef _lightleft:dword
|
||||
externdef _blockdivshift:dword
|
||||
externdef _blockdivmask:dword
|
||||
externdef _lightleftstep:dword
|
||||
externdef _r_origin:dword
|
||||
externdef _r_ppn:dword
|
||||
externdef _r_pup:dword
|
||||
externdef _r_pright:dword
|
||||
externdef _ycenter:dword
|
||||
externdef _xcenter:dword
|
||||
externdef _d_vrectbottom_particle:dword
|
||||
externdef _d_vrectright_particle:dword
|
||||
externdef _d_vrecty:dword
|
||||
externdef _d_vrectx:dword
|
||||
externdef _d_pix_shift:dword
|
||||
externdef _d_pix_min:dword
|
||||
externdef _d_pix_max:dword
|
||||
externdef _d_y_aspect_shift:dword
|
||||
externdef _screenwidth:dword
|
||||
externdef _r_leftclipped:dword
|
||||
externdef _r_leftenter:dword
|
||||
externdef _r_rightclipped:dword
|
||||
externdef _r_rightenter:dword
|
||||
externdef _modelorg:dword
|
||||
externdef _xscale:dword
|
||||
externdef _r_refdef:dword
|
||||
externdef _yscale:dword
|
||||
externdef _r_leftexit:dword
|
||||
externdef _r_rightexit:dword
|
||||
externdef _r_lastvertvalid:dword
|
||||
externdef _cacheoffset:dword
|
||||
externdef _newedges:dword
|
||||
externdef _removeedges:dword
|
||||
externdef _r_pedge:dword
|
||||
externdef _r_framecount:dword
|
||||
externdef _r_u1:dword
|
||||
externdef _r_emitted:dword
|
||||
externdef _edge_p:dword
|
||||
externdef _surface_p:dword
|
||||
externdef _surfaces:dword
|
||||
externdef _r_lzi1:dword
|
||||
externdef _r_v1:dword
|
||||
externdef _r_ceilv1:dword
|
||||
externdef _r_nearzi:dword
|
||||
externdef _r_nearzionly:dword
|
||||
externdef _edge_aftertail:dword
|
||||
externdef _edge_tail:dword
|
||||
externdef _current_iv:dword
|
||||
externdef _edge_head_u_shift20:dword
|
||||
externdef _span_p:dword
|
||||
externdef _edge_head:dword
|
||||
externdef _fv:dword
|
||||
externdef _edge_tail_u_shift20:dword
|
||||
externdef _r_apverts:dword
|
||||
externdef _r_anumverts:dword
|
||||
externdef _aliastransform:dword
|
||||
externdef _r_avertexnormals:dword
|
||||
externdef _r_plightvec:dword
|
||||
externdef _r_ambientlight:dword
|
||||
externdef _r_shadelight:dword
|
||||
externdef _aliasxcenter:dword
|
||||
externdef _aliasycenter:dword
|
||||
externdef _a_sstepxfrac:dword
|
||||
externdef _r_affinetridesc:dword
|
||||
externdef _acolormap:dword
|
||||
externdef _d_pcolormap:dword
|
||||
externdef _r_affinetridesc:dword
|
||||
externdef _d_sfrac:dword
|
||||
externdef _d_ptex:dword
|
||||
externdef _d_pedgespanpackage:dword
|
||||
externdef _d_tfrac:dword
|
||||
externdef _d_light:dword
|
||||
externdef _d_zi:dword
|
||||
externdef _d_pdest:dword
|
||||
externdef _d_pz:dword
|
||||
externdef _d_aspancount:dword
|
||||
externdef _erroradjustup:dword
|
||||
externdef _errorterm:dword
|
||||
externdef _d_xdenom:dword
|
||||
externdef _r_p0:dword
|
||||
externdef _r_p1:dword
|
||||
externdef _r_p2:dword
|
||||
externdef _a_tstepxfrac:dword
|
||||
externdef _r_sstepx:dword
|
||||
externdef _r_tstepx:dword
|
||||
externdef _a_ststepxwhole:dword
|
||||
externdef _zspantable:dword
|
||||
externdef _skintable:dword
|
||||
externdef _r_zistepx:dword
|
||||
externdef _erroradjustdown:dword
|
||||
externdef _d_countextrastep:dword
|
||||
externdef _ubasestep:dword
|
||||
externdef _a_ststepxwhole:dword
|
||||
externdef _a_tstepxfrac:dword
|
||||
externdef _r_lstepx:dword
|
||||
externdef _a_spans:dword
|
||||
externdef _erroradjustdown:dword
|
||||
externdef _d_pdestextrastep:dword
|
||||
externdef _d_pzextrastep:dword
|
||||
externdef _d_sfracextrastep:dword
|
||||
externdef _d_ptexextrastep:dword
|
||||
externdef _d_countextrastep:dword
|
||||
externdef _d_tfracextrastep:dword
|
||||
externdef _d_lightextrastep:dword
|
||||
externdef _d_ziextrastep:dword
|
||||
externdef _d_pdestbasestep:dword
|
||||
externdef _d_pzbasestep:dword
|
||||
externdef _d_sfracbasestep:dword
|
||||
externdef _d_ptexbasestep:dword
|
||||
externdef _ubasestep:dword
|
||||
externdef _d_tfracbasestep:dword
|
||||
externdef _d_lightbasestep:dword
|
||||
externdef _d_zibasestep:dword
|
||||
externdef _zspantable:dword
|
||||
externdef _r_lstepy:dword
|
||||
externdef _r_sstepy:dword
|
||||
externdef _r_tstepy:dword
|
||||
externdef _r_zistepy:dword
|
||||
externdef _D_PolysetSetEdgeTable:dword
|
||||
externdef _D_RasterizeAliasPolySmooth:dword
|
||||
|
||||
externdef float_point5:dword
|
||||
externdef Float2ToThe31nd:dword
|
||||
externdef izistep:dword
|
||||
externdef izi:dword
|
||||
externdef FloatMinus2ToThe31nd:dword
|
||||
externdef float_1:dword
|
||||
externdef float_particle_z_clip:dword
|
||||
externdef float_minus_1:dword
|
||||
externdef float_0:dword
|
||||
externdef fp_16:dword
|
||||
externdef fp_64k:dword
|
||||
externdef fp_1m:dword
|
||||
externdef fp_1m_minus_1:dword
|
||||
externdef fp_8 :dword
|
||||
externdef entryvec_table:dword
|
||||
externdef advancetable:dword
|
||||
externdef sstep:dword
|
||||
externdef tstep:dword
|
||||
externdef pspantemp:dword
|
||||
externdef counttemp:dword
|
||||
externdef jumptemp:dword
|
||||
externdef reciprocal_table:dword
|
||||
externdef DP_Count:dword
|
||||
externdef DP_u:dword
|
||||
externdef DP_v:dword
|
||||
externdef DP_32768:dword
|
||||
externdef DP_Color:dword
|
||||
externdef DP_Pix:dword
|
||||
externdef DP_EntryTable:dword
|
||||
externdef pbase:dword
|
||||
externdef s:dword
|
||||
externdef t:dword
|
||||
externdef sfracf:dword
|
||||
externdef tfracf:dword
|
||||
externdef snext:dword
|
||||
externdef tnext:dword
|
||||
externdef spancountminus1:dword
|
||||
externdef zi16stepu:dword
|
||||
externdef sdivz16stepu:dword
|
||||
externdef tdivz16stepu:dword
|
||||
externdef zi8stepu:dword
|
||||
externdef sdivz8stepu:dword
|
||||
externdef tdivz8stepu:dword
|
||||
externdef reciprocal_table_16:dword
|
||||
externdef entryvec_table_16:dword
|
||||
externdef fp_64kx64k:dword
|
||||
externdef pz:dword
|
||||
externdef spr8entryvec_table:dword
|
||||
endif
|
||||
|
||||
externdef _fpu_ceil_cw:dword
|
||||
externdef _fpu_chop_cw:dword
|
||||
externdef _snd_scaletable:dword
|
||||
externdef _paintbuffer:dword
|
||||
externdef _snd_linear_count:dword
|
||||
externdef _snd_p:dword
|
||||
externdef _snd_vol:dword
|
||||
externdef _snd_out:dword
|
||||
externdef _vright:dword
|
||||
externdef _vup:dword
|
||||
externdef _vpn:dword
|
||||
externdef _BOPS_Error:dword
|
||||
|
||||
; plane_t structure
|
||||
; !!! if this is changed, it must be changed in model.h too !!!
|
||||
; !!! if the size of this is changed, the array lookup in SV_HullPointContents
|
||||
; must be changed too !!!
|
||||
pl_normal equ 0
|
||||
pl_dist equ 12
|
||||
pl_type equ 16
|
||||
pl_signbits equ 17
|
||||
pl_pad equ 18
|
||||
pl_size equ 20
|
||||
|
||||
; hull_t structure
|
||||
; !!! if this is changed, it must be changed in model.h too !!!
|
||||
hu_clipnodes equ 0
|
||||
hu_planes equ 4
|
||||
hu_firstclipnode equ 8
|
||||
hu_lastclipnode equ 12
|
||||
hu_clip_mins equ 16
|
||||
hu_clip_maxs equ 28
|
||||
hu_size equ 40
|
||||
|
||||
; dnode_t structure
|
||||
; !!! if this is changed, it must be changed in bspfile.h too !!!
|
||||
nd_planenum equ 0
|
||||
nd_children equ 4
|
||||
nd_mins equ 8
|
||||
nd_maxs equ 20
|
||||
nd_firstface equ 32
|
||||
nd_numfaces equ 36
|
||||
nd_size equ 40
|
||||
|
||||
; sfxcache_t structure
|
||||
; !!! if this is changed, it much be changed in sound.h too !!!
|
||||
sfxc_length equ 0
|
||||
sfxc_loopstart equ 4
|
||||
sfxc_speed equ 8
|
||||
sfxc_width equ 12
|
||||
sfxc_stereo equ 16
|
||||
sfxc_data equ 20
|
||||
|
||||
; channel_t structure
|
||||
; !!! if this is changed, it much be changed in sound.h too !!!
|
||||
ch_sfx equ 0
|
||||
ch_leftvol equ 4
|
||||
ch_rightvol equ 8
|
||||
ch_end equ 12
|
||||
ch_pos equ 16
|
||||
ch_looping equ 20
|
||||
ch_entnum equ 24
|
||||
ch_entchannel equ 28
|
||||
ch_origin equ 32
|
||||
ch_dist_mult equ 44
|
||||
ch_master_vol equ 48
|
||||
ch_size equ 52
|
||||
|
||||
; portable_samplepair_t structure
|
||||
; !!! if this is changed, it much be changed in sound.h too !!!
|
||||
psp_left equ 0
|
||||
psp_right equ 4
|
||||
psp_size equ 8
|
||||
|
||||
; !!! if this is changed, it must be changed in r_local.h too !!!
|
||||
NEAR_CLIP equ 0.01
|
||||
|
||||
; !!! if this is changed, it must be changed in r_local.h too !!!
|
||||
CYCLE equ 128
|
||||
|
||||
; espan_t structure
|
||||
; !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
espan_t_u equ 0
|
||||
espan_t_v equ 4
|
||||
espan_t_count equ 8
|
||||
espan_t_pnext equ 12
|
||||
espan_t_size equ 16
|
||||
|
||||
; sspan_t structure
|
||||
; !!! if this is changed, it must be changed in d_local.h too !!!
|
||||
sspan_t_u equ 0
|
||||
sspan_t_v equ 4
|
||||
sspan_t_count equ 8
|
||||
sspan_t_size equ 12
|
||||
|
||||
; spanpackage_t structure
|
||||
; !!! if this is changed, it must be changed in d_polyset.c too !!!
|
||||
spanpackage_t_pdest equ 0
|
||||
spanpackage_t_pz equ 4
|
||||
spanpackage_t_count equ 8
|
||||
spanpackage_t_ptex equ 12
|
||||
spanpackage_t_sfrac equ 16
|
||||
spanpackage_t_tfrac equ 20
|
||||
spanpackage_t_light equ 24
|
||||
spanpackage_t_zi equ 28
|
||||
spanpackage_t_size equ 32
|
||||
|
||||
; edge_t structure
|
||||
; !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
et_u equ 0
|
||||
et_u_step equ 4
|
||||
et_prev equ 8
|
||||
et_next equ 12
|
||||
et_surfs equ 16
|
||||
et_nextremove equ 20
|
||||
et_nearzi equ 24
|
||||
et_owner equ 28
|
||||
et_size equ 32
|
||||
|
||||
; surf_t structure
|
||||
; !!! if this is changed, it must be changed in r_shared.h too !!!
|
||||
SURF_T_SHIFT equ 6
|
||||
st_next equ 0
|
||||
st_prev equ 4
|
||||
st_spans equ 8
|
||||
st_key equ 12
|
||||
st_last_u equ 16
|
||||
st_spanstate equ 20
|
||||
st_flags equ 24
|
||||
st_data equ 28
|
||||
st_entity equ 32
|
||||
st_nearzi equ 36
|
||||
st_insubmodel equ 40
|
||||
st_d_ziorigin equ 44
|
||||
st_d_zistepu equ 48
|
||||
st_d_zistepv equ 52
|
||||
st_pad equ 56
|
||||
st_size equ 64
|
||||
|
||||
; clipplane_t structure
|
||||
; !!! if this is changed, it must be changed in r_local.h too !!!
|
||||
cp_normal equ 0
|
||||
cp_dist equ 12
|
||||
cp_next equ 16
|
||||
cp_leftedge equ 20
|
||||
cp_rightedge equ 21
|
||||
cp_reserved equ 22
|
||||
cp_size equ 24
|
||||
|
||||
; medge_t structure
|
||||
; !!! if this is changed, it must be changed in model.h too !!!
|
||||
me_v equ 0
|
||||
me_cachededgeoffset equ 4
|
||||
me_size equ 8
|
||||
|
||||
; mvertex_t structure
|
||||
; !!! if this is changed, it must be changed in model.h too !!!
|
||||
mv_position equ 0
|
||||
mv_size equ 12
|
||||
|
||||
; refdef_t structure
|
||||
; !!! if this is changed, it must be changed in render.h too !!!
|
||||
rd_vrect equ 0
|
||||
rd_aliasvrect equ 20
|
||||
rd_vrectright equ 40
|
||||
rd_vrectbottom equ 44
|
||||
rd_aliasvrectright equ 48
|
||||
rd_aliasvrectbottom equ 52
|
||||
rd_vrectrightedge equ 56
|
||||
rd_fvrectx equ 60
|
||||
rd_fvrecty equ 64
|
||||
rd_fvrectx_adj equ 68
|
||||
rd_fvrecty_adj equ 72
|
||||
rd_vrect_x_adj_shift20 equ 76
|
||||
rd_vrectright_adj_shift20 equ 80
|
||||
rd_fvrectright_adj equ 84
|
||||
rd_fvrectbottom_adj equ 88
|
||||
rd_fvrectright equ 92
|
||||
rd_fvrectbottom equ 96
|
||||
rd_horizontalFieldOfView equ 100
|
||||
rd_xOrigin equ 104
|
||||
rd_yOrigin equ 108
|
||||
rd_vieworg equ 112
|
||||
rd_viewangles equ 124
|
||||
rd_ambientlight equ 136
|
||||
rd_size equ 140
|
||||
|
||||
; mtriangle_t structure
|
||||
; !!! if this is changed, it must be changed in model.h too !!!
|
||||
mtri_facesfront equ 0
|
||||
mtri_vertindex equ 4
|
||||
mtri_size equ 16 ; !!! if this changes, array indexing in !!!
|
||||
; !!! d_polysa.s must be changed to match !!!
|
||||
mtri_shift equ 4
|
||||
|
||||
323
ref_soft/r_aclip.c
Normal file
323
ref_soft/r_aclip.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// r_aclip.c: clip routines for drawing Alias models directly to the screen
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
static finalvert_t fv[2][8];
|
||||
|
||||
void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
|
||||
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;
|
||||
|
||||
scale = (ALIAS_Z_CLIP_PLANE - pfv0->xyz[2]) /
|
||||
(pfv1->xyz[2] - pfv0->xyz[2]);
|
||||
|
||||
out->xyz[0] = pfv0->xyz[0] + (pfv1->xyz[0] - pfv0->xyz[0]) * scale;
|
||||
out->xyz[1] = pfv0->xyz[1] + (pfv1->xyz[1] - pfv0->xyz[1]) * scale;
|
||||
out->xyz[2] = ALIAS_Z_CLIP_PLANE;
|
||||
|
||||
out->s = pfv0->s + (pfv1->s - pfv0->s) * scale;
|
||||
out->t = pfv0->t + (pfv1->t - pfv0->t) * scale;
|
||||
out->l = pfv0->l + (pfv1->l - pfv0->l) * scale;
|
||||
|
||||
R_AliasProjectAndClipTestFinalVert (out);
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
|
||||
if (pfv0->v >= pfv1->v )
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrect.x - pfv0->u) /
|
||||
(pfv1->u - pfv0->u);
|
||||
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
|
||||
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
|
||||
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
|
||||
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
|
||||
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
|
||||
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrect.x - pfv1->u) /
|
||||
(pfv0->u - pfv1->u);
|
||||
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
|
||||
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
|
||||
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
|
||||
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
|
||||
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
|
||||
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
|
||||
if ( pfv0->v >= pfv1->v )
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrectright - pfv0->u ) /
|
||||
(pfv1->u - pfv0->u );
|
||||
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
|
||||
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
|
||||
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
|
||||
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
|
||||
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
|
||||
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrectright - pfv1->u ) /
|
||||
(pfv0->u - pfv1->u );
|
||||
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
|
||||
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
|
||||
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
|
||||
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
|
||||
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
|
||||
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
|
||||
if (pfv0->v >= pfv1->v)
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrect.y - pfv0->v) /
|
||||
(pfv1->v - pfv0->v);
|
||||
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
|
||||
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
|
||||
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
|
||||
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
|
||||
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
|
||||
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrect.y - pfv1->v) /
|
||||
(pfv0->v - pfv1->v);
|
||||
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
|
||||
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
|
||||
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
|
||||
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
|
||||
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
|
||||
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
|
||||
finalvert_t *out)
|
||||
{
|
||||
float scale;
|
||||
|
||||
if (pfv0->v >= pfv1->v)
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrectbottom - pfv0->v) /
|
||||
(pfv1->v - pfv0->v);
|
||||
|
||||
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
|
||||
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
|
||||
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
|
||||
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
|
||||
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
|
||||
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = (float)(r_refdef.aliasvrectbottom - pfv1->v) /
|
||||
(pfv0->v - pfv1->v);
|
||||
|
||||
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
|
||||
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
|
||||
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
|
||||
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
|
||||
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
|
||||
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * 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].u < r_refdef.aliasvrect.x)
|
||||
out[k].flags |= ALIAS_LEFT_CLIP;
|
||||
if (out[k].v < r_refdef.aliasvrect.y)
|
||||
out[k].flags |= ALIAS_TOP_CLIP;
|
||||
if (out[k].u > r_refdef.aliasvrectright)
|
||||
out[k].flags |= ALIAS_RIGHT_CLIP;
|
||||
if (out[k].v > r_refdef.aliasvrectbottom)
|
||||
out[k].flags |= ALIAS_BOTTOM_CLIP;
|
||||
k++;
|
||||
}
|
||||
if (!flags)
|
||||
{
|
||||
out[k] = in[i];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_AliasClipTriangle
|
||||
================
|
||||
*/
|
||||
void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2)
|
||||
{
|
||||
int i, k, pingpong;
|
||||
unsigned clipflags;
|
||||
|
||||
// copy vertexes and fix seam texture coordinates
|
||||
fv[0][0] = *index0;
|
||||
fv[0][1] = *index1;
|
||||
fv[0][2] = *index2;
|
||||
|
||||
// clip
|
||||
clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
|
||||
|
||||
if (clipflags & ALIAS_Z_CLIP)
|
||||
{
|
||||
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].u < r_refdef.aliasvrect.x)
|
||||
fv[pingpong][i].u = r_refdef.aliasvrect.x;
|
||||
else if (fv[pingpong][i].u > r_refdef.aliasvrectright)
|
||||
fv[pingpong][i].u = r_refdef.aliasvrectright;
|
||||
|
||||
if (fv[pingpong][i].v < r_refdef.aliasvrect.y)
|
||||
fv[pingpong][i].v = r_refdef.aliasvrect.y;
|
||||
else if (fv[pingpong][i].v > r_refdef.aliasvrectbottom)
|
||||
fv[pingpong][i].v = r_refdef.aliasvrectbottom;
|
||||
|
||||
fv[pingpong][i].flags = 0;
|
||||
}
|
||||
|
||||
// draw triangles
|
||||
for (i=1 ; i<k-1 ; i++)
|
||||
{
|
||||
aliastriangleparms.a = &fv[pingpong][0];
|
||||
aliastriangleparms.b = &fv[pingpong][i];
|
||||
aliastriangleparms.c = &fv[pingpong][i+1];
|
||||
R_DrawTriangle();
|
||||
}
|
||||
}
|
||||
|
||||
200
ref_soft/r_aclipa.asm
Normal file
200
ref_soft/r_aclipa.asm
Normal file
@@ -0,0 +1,200 @@
|
||||
.386P
|
||||
.model FLAT
|
||||
;
|
||||
; r_aliasa.s
|
||||
; x86 assembly-language Alias model transform and project code.
|
||||
;
|
||||
|
||||
include qasm.inc
|
||||
include d_if.inc
|
||||
|
||||
if id386
|
||||
|
||||
_DATA SEGMENT
|
||||
Ltemp0 dd 0
|
||||
Ltemp1 dd 0
|
||||
|
||||
_DATA ENDS
|
||||
_TEXT SEGMENT
|
||||
|
||||
pfv0 equ 8+4
|
||||
pfv1 equ 8+8
|
||||
outparm equ 8+12
|
||||
|
||||
public _R_Alias_clip_bottom
|
||||
_R_Alias_clip_bottom:
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi,ds:dword ptr[pfv0+esp]
|
||||
mov edi,ds:dword ptr[pfv1+esp]
|
||||
|
||||
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrectbottom]
|
||||
|
||||
LDoForwardOrBackward:
|
||||
|
||||
mov edx,ds:dword ptr[fv_v+4+esi]
|
||||
mov ecx,ds:dword ptr[fv_v+4+edi]
|
||||
|
||||
cmp edx,ecx
|
||||
jl LDoForward
|
||||
|
||||
mov ecx,ds:dword ptr[fv_v+4+esi]
|
||||
mov edx,ds:dword ptr[fv_v+4+edi]
|
||||
mov edi,ds:dword ptr[pfv0+esp]
|
||||
mov esi,ds:dword ptr[pfv1+esp]
|
||||
|
||||
LDoForward:
|
||||
|
||||
sub ecx,edx
|
||||
sub eax,edx
|
||||
mov ds:dword ptr[Ltemp1],ecx
|
||||
mov ds:dword ptr[Ltemp0],eax
|
||||
fild ds:dword ptr[Ltemp1]
|
||||
fild ds:dword ptr[Ltemp0]
|
||||
mov edx,ds:dword ptr[outparm+esp]
|
||||
mov eax,2
|
||||
|
||||
fdivrp st(1),st(0) ; scale
|
||||
|
||||
LDo3Forward:
|
||||
fild ds:dword ptr[fv_v+0+esi] ; fv0v0 | scale
|
||||
fild ds:dword ptr[fv_v+0+edi] ; fv1v0 | fv0v0 | scale
|
||||
fild ds:dword ptr[fv_v+4+esi] ; fv0v1 | fv1v0 | fv0v0 | scale
|
||||
fild ds:dword ptr[fv_v+4+edi] ; fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
|
||||
fild ds:dword ptr[fv_v+8+esi] ; fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
|
||||
fild ds:dword ptr[fv_v+8+edi] ; fv1v2 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 |
|
||||
; scale
|
||||
fxch st(5) ; fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv1v2 |
|
||||
; scale
|
||||
fsub st(4),st(0) ; fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0-fv0v0 |
|
||||
; fv1v2 | scale
|
||||
fxch st(3) ; fv0v1 | fv0v2 | fv1v1 | fv0v0 | fv1v0-fv0v0 |
|
||||
; fv1v2 | scale
|
||||
fsub st(2),st(0) ; fv0v1 | fv0v2 | fv1v1-fv0v1 | fv0v0 |
|
||||
; fv1v0-fv0v0 | fv1v2 | scale
|
||||
fxch st(1) ; fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
|
||||
; fv1v0-fv0v0 | fv1v2 | scale
|
||||
fsub st(5),st(0) ; 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(4),st(0) ; scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
|
||||
; (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
|
||||
add edi,12
|
||||
fmul st(2),st(0) ; scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
|
||||
; (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
|
||||
add esi,12
|
||||
add edx,12
|
||||
fmul st(5),st(0) ; 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(4),st(0) ; fv0v1 | (fv1v1-fv0v1)*scale | scale |
|
||||
; fv0v0+(fv1v0-fv0v0)*scale |
|
||||
; (fv1v2-fv0v2)*scale | fv0v2
|
||||
faddp st(1),st(0) ; 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(3),st(0) ; 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
|
||||
fadd ds:dword ptr[float_point5]
|
||||
fxch st(3) ; fv0v1+(fv1v1-fv0v1)*scale | scale |
|
||||
; fv0v2+(fv1v2-fv0v2)*scale |
|
||||
; fv0v0+(fv1v0-fv0v0)*scale
|
||||
fadd ds:dword ptr[float_point5]
|
||||
fxch st(2) ; fv0v2+(fv1v2-fv0v2)*scale | scale |
|
||||
; fv0v1+(fv1v1-fv0v1)*scale |
|
||||
; fv0v0+(fv1v0-fv0v0)*scale
|
||||
fadd ds:dword ptr[float_point5]
|
||||
fxch st(3) ; fv0v0+(fv1v0-fv0v0)*scale | scale |
|
||||
; fv0v1+(fv1v1-fv0v1)*scale |
|
||||
; fv0v2+(fv1v2-fv0v2)*scale
|
||||
fistp ds:dword ptr[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
|
||||
fistp ds:dword ptr[fv_v+4-12+edx] ; scale | fv0v2+(fv1v2-fv0v2)*scale
|
||||
fxch st(1) ; fv0v2+(fv1v2-fv0v2)*sc | scale
|
||||
fistp ds:dword ptr[fv_v+8-12+edx] ; scale
|
||||
|
||||
dec eax
|
||||
jnz LDo3Forward
|
||||
|
||||
fstp st(0)
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
|
||||
ret
|
||||
|
||||
|
||||
public _R_Alias_clip_top
|
||||
_R_Alias_clip_top:
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi,ds:dword ptr[pfv0+esp]
|
||||
mov edi,ds:dword ptr[pfv1+esp]
|
||||
|
||||
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrect+4]
|
||||
jmp LDoForwardOrBackward
|
||||
|
||||
|
||||
|
||||
public _R_Alias_clip_right
|
||||
_R_Alias_clip_right:
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi,ds:dword ptr[pfv0+esp]
|
||||
mov edi,ds:dword ptr[pfv1+esp]
|
||||
|
||||
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrectright]
|
||||
|
||||
LRightLeftEntry:
|
||||
|
||||
|
||||
mov edx,ds:dword ptr[fv_v+4+esi]
|
||||
mov ecx,ds:dword ptr[fv_v+4+edi]
|
||||
|
||||
cmp edx,ecx
|
||||
mov edx,ds:dword ptr[fv_v+0+esi]
|
||||
|
||||
mov ecx,ds:dword ptr[fv_v+0+edi]
|
||||
jl LDoForward2
|
||||
|
||||
mov ecx,ds:dword ptr[fv_v+0+esi]
|
||||
mov edx,ds:dword ptr[fv_v+0+edi]
|
||||
mov edi,ds:dword ptr[pfv0+esp]
|
||||
mov esi,ds:dword ptr[pfv1+esp]
|
||||
|
||||
LDoForward2:
|
||||
|
||||
jmp LDoForward
|
||||
|
||||
|
||||
public _R_Alias_clip_left
|
||||
_R_Alias_clip_left:
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi,ds:dword ptr[pfv0+esp]
|
||||
mov edi,ds:dword ptr[pfv1+esp]
|
||||
|
||||
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrect+0]
|
||||
jmp LRightLeftEntry
|
||||
|
||||
|
||||
|
||||
_TEXT ENDS
|
||||
endif ;id386
|
||||
END
|
||||
1198
ref_soft/r_alias.c
Normal file
1198
ref_soft/r_alias.c
Normal file
File diff suppressed because it is too large
Load Diff
637
ref_soft/r_bsp.c
Normal file
637
ref_soft/r_bsp.c
Normal file
@@ -0,0 +1,637 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// r_bsp.c
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
//
|
||||
// current entity info
|
||||
//
|
||||
qboolean insubmodel;
|
||||
entity_t *currententity;
|
||||
vec3_t 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];
|
||||
|
||||
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
|
||||
|
||||
Clip a bmodel poly down the world bsp tree
|
||||
================
|
||||
*/
|
||||
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;
|
||||
int area;
|
||||
|
||||
psideedges[0] = psideedges[1] = NULL;
|
||||
|
||||
makeclippededge = false;
|
||||
|
||||
// transform the BSP plane into model space
|
||||
// FIXME: cache these?
|
||||
splitplane = pnode->plane;
|
||||
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))
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL,"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))
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL,"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 (pn->contents != CONTENTS_NODE)
|
||||
{
|
||||
if (pn->contents != CONTENTS_SOLID)
|
||||
{
|
||||
if (r_newrefdef.areabits)
|
||||
{
|
||||
area = ((mleaf_t *)pn)->area;
|
||||
if (! (r_newrefdef.areabits[area>>3] & (1<<(area&7)) ) )
|
||||
continue; // not visible
|
||||
}
|
||||
|
||||
r_currentbkey = ((mleaf_t *)pn)->key;
|
||||
R_RenderBmodelFace (psideedges[i], psurf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
|
||||
psurf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSolidClippedSubmodelPolygons
|
||||
|
||||
Bmodel crosses multiple leafs
|
||||
================
|
||||
*/
|
||||
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode)
|
||||
{
|
||||
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)))
|
||||
continue;
|
||||
|
||||
// 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;
|
||||
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
|
||||
|
||||
if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) )
|
||||
R_RecursiveClipBPoly (pbedge, topnode, psurf);
|
||||
else
|
||||
R_RenderBmodelFace( pbedge, psurf );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSubmodelPolygons
|
||||
|
||||
All in one leaf
|
||||
================
|
||||
*/
|
||||
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode)
|
||||
{
|
||||
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 *)topnode)->key;
|
||||
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
R_RenderFace (psurf, clipflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int c_drawnode;
|
||||
|
||||
/*
|
||||
================
|
||||
R_RecursiveWorldNode
|
||||
================
|
||||
*/
|
||||
void R_RecursiveWorldNode (mnode_t *node, int clipflags)
|
||||
{
|
||||
int i, c, side, *pindex;
|
||||
vec3_t acceptpt, rejectpt;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf, **mark;
|
||||
float d, dot;
|
||||
mleaf_t *pleaf;
|
||||
|
||||
if (node->contents == CONTENTS_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
|
||||
}
|
||||
}
|
||||
|
||||
c_drawnode++;
|
||||
|
||||
// if a leaf node, draw stuff
|
||||
if (node->contents != -1)
|
||||
{
|
||||
pleaf = (mleaf_t *)node;
|
||||
|
||||
// check for door connected areas
|
||||
if (r_newrefdef.areabits)
|
||||
{
|
||||
if (! (r_newrefdef.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
|
||||
R_RecursiveWorldNode (node->children[side], clipflags);
|
||||
|
||||
// draw stuff
|
||||
c = node->numsurfaces;
|
||||
|
||||
if (c)
|
||||
{
|
||||
surf = r_worldmodel->surfaces + node->firstsurface;
|
||||
|
||||
if (dot < -BACKFACE_EPSILON)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((surf->flags & SURF_PLANEBACK) &&
|
||||
(surf->visframe == r_framecount))
|
||||
{
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
|
||||
surf++;
|
||||
} while (--c);
|
||||
}
|
||||
else if (dot > BACKFACE_EPSILON)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!(surf->flags & SURF_PLANEBACK) &&
|
||||
(surf->visframe == r_framecount))
|
||||
{
|
||||
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
|
||||
R_RecursiveWorldNode (node->children[!side], clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderWorld
|
||||
================
|
||||
*/
|
||||
void R_RenderWorld (void)
|
||||
{
|
||||
|
||||
if (!r_drawworld->value)
|
||||
return;
|
||||
if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
|
||||
return;
|
||||
|
||||
c_drawnode=0;
|
||||
|
||||
// auto cycle the world frame for texture animation
|
||||
r_worldentity.frame = (int)(r_newrefdef.time*2);
|
||||
currententity = &r_worldentity;
|
||||
|
||||
VectorCopy (r_origin, modelorg);
|
||||
currentmodel = r_worldmodel;
|
||||
r_pcurrentvertbase = currentmodel->vertexes;
|
||||
|
||||
R_RecursiveWorldNode (currentmodel->nodes, 15);
|
||||
}
|
||||
|
||||
|
||||
445
ref_soft/r_draw.c
Normal file
445
ref_soft/r_draw.c
Normal file
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
// draw.c
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
|
||||
image_t *draw_chars; // 8*8 graphic characters
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_FindPic
|
||||
================
|
||||
*/
|
||||
image_t *Draw_FindPic (char *name)
|
||||
{
|
||||
image_t *image;
|
||||
char fullname[MAX_QPATH];
|
||||
|
||||
if (name[0] != '/' && name[0] != '\\')
|
||||
{
|
||||
Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
|
||||
image = R_FindImage (fullname, it_pic);
|
||||
}
|
||||
else
|
||||
image = R_FindImage (name+1, it_pic);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Draw_InitLocal
|
||||
===============
|
||||
*/
|
||||
void Draw_InitLocal (void)
|
||||
{
|
||||
draw_chars = Draw_FindPic ("conchars");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_Char
|
||||
|
||||
Draws one 8*8 graphics character
|
||||
It can be clipped to the top of the screen to allow the console to be
|
||||
smoothly scrolled off.
|
||||
================
|
||||
*/
|
||||
void Draw_Char (int x, int y, int num)
|
||||
{
|
||||
byte *dest;
|
||||
byte *source;
|
||||
int drawline;
|
||||
int row, col;
|
||||
|
||||
num &= 255;
|
||||
|
||||
if (num == 32 || num == 32+128)
|
||||
return;
|
||||
|
||||
if (y <= -8)
|
||||
return; // totally off screen
|
||||
|
||||
// if ( ( y + 8 ) >= vid.height )
|
||||
if ( ( y + 8 ) > vid.height ) // PGM - status text was missing in sw...
|
||||
return;
|
||||
|
||||
#ifdef PARANOID
|
||||
if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
|
||||
ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: (%i, %i)", x, y);
|
||||
if (num < 0 || num > 255)
|
||||
ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: char %i", num);
|
||||
#endif
|
||||
|
||||
row = num>>4;
|
||||
col = num&15;
|
||||
source = draw_chars->pixels[0] + (row<<10) + (col<<3);
|
||||
|
||||
if (y < 0)
|
||||
{ // clipped
|
||||
drawline = 8 + y;
|
||||
source -= 128*y;
|
||||
y = 0;
|
||||
}
|
||||
else
|
||||
drawline = 8;
|
||||
|
||||
|
||||
dest = vid.buffer + y*vid.rowbytes + x;
|
||||
|
||||
while (drawline--)
|
||||
{
|
||||
if (source[0] != TRANSPARENT_COLOR)
|
||||
dest[0] = source[0];
|
||||
if (source[1] != TRANSPARENT_COLOR)
|
||||
dest[1] = source[1];
|
||||
if (source[2] != TRANSPARENT_COLOR)
|
||||
dest[2] = source[2];
|
||||
if (source[3] != TRANSPARENT_COLOR)
|
||||
dest[3] = source[3];
|
||||
if (source[4] != TRANSPARENT_COLOR)
|
||||
dest[4] = source[4];
|
||||
if (source[5] != TRANSPARENT_COLOR)
|
||||
dest[5] = source[5];
|
||||
if (source[6] != TRANSPARENT_COLOR)
|
||||
dest[6] = source[6];
|
||||
if (source[7] != TRANSPARENT_COLOR)
|
||||
dest[7] = source[7];
|
||||
source += 128;
|
||||
dest += vid.rowbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_GetPicSize
|
||||
=============
|
||||
*/
|
||||
void Draw_GetPicSize (int *w, int *h, char *pic)
|
||||
{
|
||||
image_t *gl;
|
||||
|
||||
gl = Draw_FindPic (pic);
|
||||
if (!gl)
|
||||
{
|
||||
*w = *h = -1;
|
||||
return;
|
||||
}
|
||||
*w = gl->width;
|
||||
*h = gl->height;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_StretchPicImplementation
|
||||
=============
|
||||
*/
|
||||
void Draw_StretchPicImplementation (int x, int y, int w, int h, image_t *pic)
|
||||
{
|
||||
byte *dest, *source;
|
||||
int v, u, sv;
|
||||
int height;
|
||||
int f, fstep;
|
||||
int skip;
|
||||
|
||||
if ((x < 0) ||
|
||||
(x + w > vid.width) ||
|
||||
(y + h > vid.height))
|
||||
{
|
||||
ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
|
||||
}
|
||||
|
||||
height = h;
|
||||
if (y < 0)
|
||||
{
|
||||
skip = -y;
|
||||
height += y;
|
||||
y = 0;
|
||||
}
|
||||
else
|
||||
skip = 0;
|
||||
|
||||
dest = vid.buffer + y * vid.rowbytes + x;
|
||||
|
||||
for (v=0 ; v<height ; v++, dest += vid.rowbytes)
|
||||
{
|
||||
sv = (skip + v)*pic->height/h;
|
||||
source = pic->pixels[0] + sv*pic->width;
|
||||
if (w == pic->width)
|
||||
memcpy (dest, source, w);
|
||||
else
|
||||
{
|
||||
f = 0;
|
||||
fstep = pic->width*0x10000/w;
|
||||
for (u=0 ; u<w ; u+=4)
|
||||
{
|
||||
dest[u] = source[f>>16];
|
||||
f += fstep;
|
||||
dest[u+1] = source[f>>16];
|
||||
f += fstep;
|
||||
dest[u+2] = source[f>>16];
|
||||
f += fstep;
|
||||
dest[u+3] = source[f>>16];
|
||||
f += fstep;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_StretchPic
|
||||
=============
|
||||
*/
|
||||
void Draw_StretchPic (int x, int y, int w, int h, char *name)
|
||||
{
|
||||
image_t *pic;
|
||||
|
||||
pic = Draw_FindPic (name);
|
||||
if (!pic)
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
|
||||
return;
|
||||
}
|
||||
Draw_StretchPicImplementation (x, y, w, h, pic);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_StretchRaw
|
||||
=============
|
||||
*/
|
||||
void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
|
||||
{
|
||||
image_t pic;
|
||||
|
||||
pic.pixels[0] = data;
|
||||
pic.width = cols;
|
||||
pic.height = rows;
|
||||
Draw_StretchPicImplementation (x, y, w, h, &pic);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_Pic
|
||||
=============
|
||||
*/
|
||||
void Draw_Pic (int x, int y, char *name)
|
||||
{
|
||||
image_t *pic;
|
||||
byte *dest, *source;
|
||||
int v, u;
|
||||
int tbyte;
|
||||
int height;
|
||||
|
||||
pic = Draw_FindPic (name);
|
||||
if (!pic)
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((x < 0) ||
|
||||
(x + pic->width > vid.width) ||
|
||||
(y + pic->height > vid.height))
|
||||
return; // ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
|
||||
|
||||
height = pic->height;
|
||||
source = pic->pixels[0];
|
||||
if (y < 0)
|
||||
{
|
||||
height += y;
|
||||
source += pic->width*-y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
dest = vid.buffer + y * vid.rowbytes + x;
|
||||
|
||||
if (!pic->transparent)
|
||||
{
|
||||
for (v=0 ; v<height ; v++)
|
||||
{
|
||||
memcpy (dest, source, pic->width);
|
||||
dest += vid.rowbytes;
|
||||
source += pic->width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pic->width & 7)
|
||||
{ // general
|
||||
for (v=0 ; v<height ; v++)
|
||||
{
|
||||
for (u=0 ; u<pic->width ; u++)
|
||||
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
|
||||
dest[u] = tbyte;
|
||||
|
||||
dest += vid.rowbytes;
|
||||
source += pic->width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // unwound
|
||||
for (v=0 ; v<height ; v++)
|
||||
{
|
||||
for (u=0 ; u<pic->width ; u+=8)
|
||||
{
|
||||
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
|
||||
dest[u] = tbyte;
|
||||
if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
|
||||
dest[u+1] = tbyte;
|
||||
if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
|
||||
dest[u+2] = tbyte;
|
||||
if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
|
||||
dest[u+3] = tbyte;
|
||||
if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
|
||||
dest[u+4] = tbyte;
|
||||
if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
|
||||
dest[u+5] = tbyte;
|
||||
if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
|
||||
dest[u+6] = tbyte;
|
||||
if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
|
||||
dest[u+7] = tbyte;
|
||||
}
|
||||
dest += vid.rowbytes;
|
||||
source += pic->width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_TileClear
|
||||
|
||||
This repeats a 64*64 tile graphic to fill the screen around a sized down
|
||||
refresh window.
|
||||
=============
|
||||
*/
|
||||
void Draw_TileClear (int x, int y, int w, int h, char *name)
|
||||
{
|
||||
int i, j;
|
||||
byte *psrc;
|
||||
byte *pdest;
|
||||
image_t *pic;
|
||||
int x2;
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + w > vid.width)
|
||||
w = vid.width - x;
|
||||
if (y + h > vid.height)
|
||||
h = vid.height - y;
|
||||
if (w <= 0 || h <= 0)
|
||||
return;
|
||||
|
||||
pic = Draw_FindPic (name);
|
||||
if (!pic)
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
|
||||
return;
|
||||
}
|
||||
x2 = x + w;
|
||||
pdest = vid.buffer + y*vid.rowbytes;
|
||||
for (i=0 ; i<h ; i++, pdest += vid.rowbytes)
|
||||
{
|
||||
psrc = pic->pixels[0] + pic->width * ((i+y)&63);
|
||||
for (j=x ; j<x2 ; j++)
|
||||
pdest[j] = psrc[j&63];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_Fill
|
||||
|
||||
Fills a box of pixels with a single color
|
||||
=============
|
||||
*/
|
||||
void Draw_Fill (int x, int y, int w, int h, int c)
|
||||
{
|
||||
byte *dest;
|
||||
int u, v;
|
||||
|
||||
if (x+w > vid.width)
|
||||
w = vid.width - x;
|
||||
if (y+h > vid.height)
|
||||
h = vid.height - y;
|
||||
if (x < 0)
|
||||
{
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if (w < 0 || h < 0)
|
||||
return;
|
||||
dest = vid.buffer + y*vid.rowbytes + x;
|
||||
for (v=0 ; v<h ; v++, dest += vid.rowbytes)
|
||||
for (u=0 ; u<w ; u++)
|
||||
dest[u] = c;
|
||||
}
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_FadeScreen
|
||||
|
||||
================
|
||||
*/
|
||||
void Draw_FadeScreen (void)
|
||||
{
|
||||
int x,y;
|
||||
byte *pbuf;
|
||||
int t;
|
||||
|
||||
for (y=0 ; y<vid.height ; y++)
|
||||
{
|
||||
pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
|
||||
t = (y & 1) << 1;
|
||||
|
||||
for (x=0 ; x<vid.width ; x++)
|
||||
{
|
||||
if ((x & 3) != t)
|
||||
pbuf[x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
1234
ref_soft/r_draw16.asm
Normal file
1234
ref_soft/r_draw16.asm
Normal file
File diff suppressed because it is too large
Load Diff
822
ref_soft/r_drawa.asm
Normal file
822
ref_soft/r_drawa.asm
Normal file
@@ -0,0 +1,822 @@
|
||||
.386P
|
||||
.model FLAT
|
||||
;
|
||||
; r_drawa.s
|
||||
; x86 assembly-language edge clipping and emission code
|
||||
;
|
||||
|
||||
include qasm.inc
|
||||
include d_if.inc
|
||||
|
||||
if id386
|
||||
|
||||
; !!! if these are changed, they must be changed in r_draw.c too !!!
|
||||
FULLY_CLIPPED_CACHED equ 080000000h
|
||||
FRAMECOUNT_MASK equ 07FFFFFFFh
|
||||
|
||||
_DATA SEGMENT
|
||||
|
||||
Ld0 dd 0.0
|
||||
Ld1 dd 0.0
|
||||
Lstack dd 0
|
||||
Lfp_near_clip dd NEAR_CLIP
|
||||
Lceilv0 dd 0
|
||||
Lv dd 0
|
||||
Lu0 dd 0
|
||||
Lv0 dd 0
|
||||
Lzi0 dd 0
|
||||
|
||||
_DATA ENDS
|
||||
_TEXT SEGMENT
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; edge clipping code
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
pv0 equ 4+12
|
||||
pv1 equ 8+12
|
||||
clip equ 12+12
|
||||
|
||||
align 4
|
||||
public _R_ClipEdge
|
||||
_R_ClipEdge:
|
||||
push esi ; preserve register variables
|
||||
push edi
|
||||
push ebx
|
||||
mov ds:dword ptr[Lstack],esp ; for clearing the stack later
|
||||
|
||||
; float d0, d1, f;
|
||||
; mvertex_t clipvert;
|
||||
|
||||
mov ebx,ds:dword ptr[clip+esp]
|
||||
mov esi,ds:dword ptr[pv0+esp]
|
||||
mov edx,ds:dword ptr[pv1+esp]
|
||||
|
||||
; if (clip)
|
||||
; {
|
||||
test ebx,ebx
|
||||
jz Lemit
|
||||
|
||||
; do
|
||||
; {
|
||||
|
||||
Lcliploop:
|
||||
|
||||
; d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
|
||||
; d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
|
||||
fld ds:dword ptr[mv_position+0+esi]
|
||||
fmul ds:dword ptr[cp_normal+0+ebx]
|
||||
fld ds:dword ptr[mv_position+4+esi]
|
||||
fmul ds:dword ptr[cp_normal+4+ebx]
|
||||
fld ds:dword ptr[mv_position+8+esi]
|
||||
fmul ds:dword ptr[cp_normal+8+ebx]
|
||||
fxch st(1)
|
||||
faddp st(2),st(0) ; d0mul2 | d0add0
|
||||
|
||||
fld ds:dword ptr[mv_position+0+edx]
|
||||
fmul ds:dword ptr[cp_normal+0+ebx]
|
||||
fld ds:dword ptr[mv_position+4+edx]
|
||||
fmul ds:dword ptr[cp_normal+4+ebx]
|
||||
fld ds:dword ptr[mv_position+8+edx]
|
||||
fmul ds:dword ptr[cp_normal+8+ebx]
|
||||
fxch st(1)
|
||||
faddp st(2),st(0) ; d1mul2 | d1add0 | d0mul2 | d0add0
|
||||
fxch st(3) ; d0add0 | d1add0 | d0mul2 | d1mul2
|
||||
|
||||
faddp st(2),st(0) ; d1add0 | dot0 | d1mul2
|
||||
faddp st(2),st(0) ; dot0 | dot1
|
||||
|
||||
fsub ds:dword ptr[cp_dist+ebx] ; d0 | dot1
|
||||
fxch st(1) ; dot1 | d0
|
||||
fsub ds:dword ptr[cp_dist+ebx] ; d1 | d0
|
||||
fxch st(1)
|
||||
fstp ds:dword ptr[Ld0]
|
||||
fstp ds:dword ptr[Ld1]
|
||||
|
||||
; if (d0 >= 0)
|
||||
; {
|
||||
mov eax,ds:dword ptr[Ld0]
|
||||
mov ecx,ds:dword ptr[Ld1]
|
||||
or ecx,eax
|
||||
js Lp2
|
||||
|
||||
; both points are unclipped
|
||||
|
||||
Lcontinue:
|
||||
|
||||
;
|
||||
; R_ClipEdge (&clipvert, pv1, clip->next);
|
||||
; return;
|
||||
; }
|
||||
; } while ((clip = clip->next) != NULL);
|
||||
mov ebx,ds:dword ptr[cp_next+ebx]
|
||||
test ebx,ebx
|
||||
jnz Lcliploop
|
||||
|
||||
; }
|
||||
|
||||
;// add the edge
|
||||
; R_EmitEdge (pv0, pv1);
|
||||
Lemit:
|
||||
|
||||
;
|
||||
; set integer rounding to ceil mode, set to single precision
|
||||
;
|
||||
; FIXME: do away with by manually extracting integers from floats?
|
||||
; FIXME: set less often
|
||||
fldcw ds:word ptr[_fpu_ceil_cw]
|
||||
|
||||
; edge_t *edge, *pcheck;
|
||||
; int u_check;
|
||||
; float u, u_step;
|
||||
; vec3_t local, transformed;
|
||||
; float *world;
|
||||
; int v, v2, ceilv0;
|
||||
; float scale, lzi0, u0, v0;
|
||||
; int side;
|
||||
|
||||
; if (r_lastvertvalid)
|
||||
; {
|
||||
cmp ds:dword ptr[_r_lastvertvalid],0
|
||||
jz LCalcFirst
|
||||
|
||||
; u0 = r_u1;
|
||||
; v0 = r_v1;
|
||||
; lzi0 = r_lzi1;
|
||||
; ceilv0 = r_ceilv1;
|
||||
mov eax,ds:dword ptr[_r_lzi1]
|
||||
mov ecx,ds:dword ptr[_r_u1]
|
||||
mov ds:dword ptr[Lzi0],eax
|
||||
mov ds:dword ptr[Lu0],ecx
|
||||
mov ecx,ds:dword ptr[_r_v1]
|
||||
mov eax,ds:dword ptr[_r_ceilv1]
|
||||
mov ds:dword ptr[Lv0],ecx
|
||||
mov ds:dword ptr[Lceilv0],eax
|
||||
jmp LCalcSecond
|
||||
|
||||
; }
|
||||
|
||||
LCalcFirst:
|
||||
|
||||
; else
|
||||
; {
|
||||
; world = &pv0->position[0];
|
||||
|
||||
call near ptr LTransformAndProject ; v0 | lzi0 | u0
|
||||
|
||||
fst ds:dword ptr[Lv0]
|
||||
fxch st(2) ; u0 | lzi0 | v0
|
||||
fstp ds:dword ptr[Lu0] ; lzi0 | v0
|
||||
fstp ds:dword ptr[Lzi0] ; v0
|
||||
|
||||
; ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
|
||||
fistp ds:dword ptr[Lceilv0]
|
||||
|
||||
; }
|
||||
|
||||
LCalcSecond:
|
||||
|
||||
; world = &pv1->position[0];
|
||||
mov esi,edx
|
||||
|
||||
call near ptr LTransformAndProject ; v1 | lzi1 | u1
|
||||
|
||||
fld ds:dword ptr[Lu0] ; u0 | v1 | lzi1 | u1
|
||||
fxch st(3) ; u1 | v1 | lzi1 | u0
|
||||
fld ds:dword ptr[Lzi0] ; lzi0 | u1 | v1 | lzi1 | u0
|
||||
fxch st(3) ; lzi1 | u1 | v1 | lzi0 | u0
|
||||
fld ds:dword ptr[Lv0] ; v0 | lzi1 | u1 | v1 | lzi0 | u0
|
||||
fxch st(3) ; v1 | lzi1 | u1 | v0 | lzi0 | u0
|
||||
|
||||
; r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
|
||||
fist ds:dword ptr[_r_ceilv1]
|
||||
|
||||
fldcw ds:word ptr[_fpu_chop_cw] ; put back normal floating-point state
|
||||
|
||||
fst ds:dword ptr[_r_v1]
|
||||
fxch st(4) ; lzi0 | lzi1 | u1 | v0 | v1 | u0
|
||||
|
||||
; if (r_lzi1 > lzi0)
|
||||
; lzi0 = r_lzi1;
|
||||
fcom st(1)
|
||||
fnstsw ax
|
||||
test ah,1
|
||||
jz LP0
|
||||
fstp st(0)
|
||||
fld st(0)
|
||||
LP0:
|
||||
|
||||
fxch st(1) ; lzi1 | lzi0 | u1 | v0 | v1 | u0
|
||||
fstp ds:dword ptr[_r_lzi1] ; lzi0 | u1 | v0 | v1 | u0
|
||||
fxch st(1)
|
||||
fst ds:dword ptr[_r_u1]
|
||||
fxch st(1)
|
||||
|
||||
; if (lzi0 > r_nearzi) // for mipmap finding
|
||||
; r_nearzi = lzi0;
|
||||
fcom ds:dword ptr[_r_nearzi]
|
||||
fnstsw ax
|
||||
test ah,045h
|
||||
jnz LP1
|
||||
fst ds:dword ptr[_r_nearzi]
|
||||
LP1:
|
||||
|
||||
; // for right edges, all we want is the effect on 1/z
|
||||
; if (r_nearzionly)
|
||||
; return;
|
||||
mov eax,ds:dword ptr[_r_nearzionly]
|
||||
test eax,eax
|
||||
jz LP2
|
||||
LPop5AndDone:
|
||||
mov eax,ds:dword ptr[_cacheoffset]
|
||||
mov edx,ds:dword ptr[_r_framecount]
|
||||
cmp eax,07FFFFFFFh
|
||||
jz LDoPop
|
||||
and edx,offset FRAMECOUNT_MASK
|
||||
or edx,offset FULLY_CLIPPED_CACHED
|
||||
mov ds:dword ptr[_cacheoffset],edx
|
||||
|
||||
LDoPop:
|
||||
fstp st(0) ; u1 | v0 | v1 | u0
|
||||
fstp st(0) ; v0 | v1 | u0
|
||||
fstp st(0) ; v1 | u0
|
||||
fstp st(0) ; u0
|
||||
fstp st(0)
|
||||
jmp Ldone
|
||||
|
||||
LP2:
|
||||
|
||||
; // create the edge
|
||||
; if (ceilv0 == r_ceilv1)
|
||||
; return; // horizontal edge
|
||||
mov ebx,ds:dword ptr[Lceilv0]
|
||||
mov edi,ds:dword ptr[_edge_p]
|
||||
mov ecx,ds:dword ptr[_r_ceilv1]
|
||||
mov edx,edi
|
||||
mov esi,ds:dword ptr[_r_pedge]
|
||||
add edx,offset et_size
|
||||
cmp ebx,ecx
|
||||
jz LPop5AndDone
|
||||
|
||||
mov eax,ds:dword ptr[_r_pedge]
|
||||
mov ds:dword ptr[et_owner+edi],eax
|
||||
|
||||
; side = ceilv0 > r_ceilv1;
|
||||
;
|
||||
; edge->nearzi = lzi0;
|
||||
fstp ds:dword ptr[et_nearzi+edi] ; u1 | v0 | v1 | u0
|
||||
|
||||
; if (side == 1)
|
||||
; {
|
||||
jc LSide0
|
||||
|
||||
LSide1:
|
||||
|
||||
; // leading edge (go from p2 to p1)
|
||||
|
||||
; u_step = ((u0 - r_u1) / (v0 - r_v1));
|
||||
fsubp st(3),st(0) ; v0 | v1 | u0-u1
|
||||
fsub st(0),st(1) ; v0-v1 | v1 | u0-u1
|
||||
fdivp st(2),st(0) ; v1 | ustep
|
||||
|
||||
; r_emitted = 1;
|
||||
mov ds:dword ptr[_r_emitted],1
|
||||
|
||||
; edge = edge_p++;
|
||||
mov ds:dword ptr[_edge_p],edx
|
||||
|
||||
; pretouch next edge
|
||||
mov eax,ds:dword ptr[edx]
|
||||
|
||||
; v2 = ceilv0 - 1;
|
||||
; v = r_ceilv1;
|
||||
mov eax,ecx
|
||||
lea ecx,ds:dword ptr[-1+ebx]
|
||||
mov ebx,eax
|
||||
|
||||
; edge->surfs[0] = 0;
|
||||
; edge->surfs[1] = surface_p - surfaces;
|
||||
mov eax,ds:dword ptr[_surface_p]
|
||||
mov esi,ds:dword ptr[_surfaces]
|
||||
sub edx,edx
|
||||
sub eax,esi
|
||||
shr eax,offset SURF_T_SHIFT
|
||||
mov ds:dword ptr[et_surfs+edi],edx
|
||||
mov ds:dword ptr[et_surfs+2+edi],eax
|
||||
|
||||
sub esi,esi
|
||||
|
||||
; u = r_u1 + ((float)v - r_v1) * u_step;
|
||||
mov ds:dword ptr[Lv],ebx
|
||||
fild ds:dword ptr[Lv] ; v | v1 | ustep
|
||||
fsubrp st(1),st(0) ; v-v1 | ustep
|
||||
fmul st(0),st(1) ; (v-v1)*ustep | ustep
|
||||
fadd ds:dword ptr[_r_u1] ; u | ustep
|
||||
|
||||
jmp LSideDone
|
||||
|
||||
; }
|
||||
|
||||
LSide0:
|
||||
|
||||
; else
|
||||
; {
|
||||
; // trailing edge (go from p1 to p2)
|
||||
|
||||
; u_step = ((r_u1 - u0) / (r_v1 - v0));
|
||||
fsub st(0),st(3) ; u1-u0 | v0 | v1 | u0
|
||||
fxch st(2) ; v1 | v0 | u1-u0 | u0
|
||||
fsub st(0),st(1) ; v1-v0 | v0 | u1-u0 | u0
|
||||
fdivp st(2),st(0) ; v0 | ustep | u0
|
||||
|
||||
; r_emitted = 1;
|
||||
mov ds:dword ptr[_r_emitted],1
|
||||
|
||||
; edge = edge_p++;
|
||||
mov ds:dword ptr[_edge_p],edx
|
||||
|
||||
; pretouch next edge
|
||||
mov eax,ds:dword ptr[edx]
|
||||
|
||||
; v = ceilv0;
|
||||
; v2 = r_ceilv1 - 1;
|
||||
dec ecx
|
||||
|
||||
; edge->surfs[0] = surface_p - surfaces;
|
||||
; edge->surfs[1] = 0;
|
||||
mov eax,ds:dword ptr[_surface_p]
|
||||
mov esi,ds:dword ptr[_surfaces]
|
||||
sub edx,edx
|
||||
sub eax,esi
|
||||
shr eax,offset SURF_T_SHIFT
|
||||
mov ds:dword ptr[et_surfs+2+edi],edx
|
||||
mov ds:dword ptr[et_surfs+edi],eax
|
||||
|
||||
mov esi,1
|
||||
|
||||
; u = u0 + ((float)v - v0) * u_step;
|
||||
mov ds:dword ptr[Lv],ebx
|
||||
fild ds:dword ptr[Lv] ; v | v0 | ustep | u0
|
||||
fsubrp st(1),st(0) ; v-v0 | ustep | u0
|
||||
fmul st(0),st(1) ; (v-v0)*ustep | ustep | u0
|
||||
faddp st(2),st(0) ; ustep | u
|
||||
fxch st(1) ; u | ustep
|
||||
|
||||
; }
|
||||
|
||||
LSideDone:
|
||||
|
||||
; edge->u_step = u_step*0x100000;
|
||||
; edge->u = u*0x100000 + 0xFFFFF;
|
||||
|
||||
fmul ds:dword ptr[fp_1m] ; u*0x100000 | ustep
|
||||
fxch st(1) ; ustep | u*0x100000
|
||||
fmul ds:dword ptr[fp_1m] ; ustep*0x100000 | u*0x100000
|
||||
fxch st(1) ; u*0x100000 | ustep*0x100000
|
||||
fadd ds:dword ptr[fp_1m_minus_1] ; u*0x100000 + 0xFFFFF | ustep*0x100000
|
||||
fxch st(1) ; ustep*0x100000 | u*0x100000 + 0xFFFFF
|
||||
fistp ds:dword ptr[et_u_step+edi] ; u*0x100000 + 0xFFFFF
|
||||
fistp ds:dword ptr[et_u+edi]
|
||||
|
||||
; // we need to do this to avoid stepping off the edges if a very nearly
|
||||
; // horizontal edge is less than epsilon above a scan, and numeric error
|
||||
; // causes it to incorrectly extend to the scan, and the extension of the
|
||||
; // line goes off the edge of the screen
|
||||
; // FIXME: is this actually needed?
|
||||
; if (edge->u < r_refdef.vrect_x_adj_shift20)
|
||||
; edge->u = r_refdef.vrect_x_adj_shift20;
|
||||
; if (edge->u > r_refdef.vrectright_adj_shift20)
|
||||
; edge->u = r_refdef.vrectright_adj_shift20;
|
||||
mov eax,ds:dword ptr[et_u+edi]
|
||||
mov edx,ds:dword ptr[_r_refdef+rd_vrect_x_adj_shift20]
|
||||
cmp eax,edx
|
||||
jl LP4
|
||||
mov edx,ds:dword ptr[_r_refdef+rd_vrectright_adj_shift20]
|
||||
cmp eax,edx
|
||||
jng LP5
|
||||
LP4:
|
||||
mov ds:dword ptr[et_u+edi],edx
|
||||
mov eax,edx
|
||||
LP5:
|
||||
|
||||
; // sort the edge in normally
|
||||
; u_check = edge->u;
|
||||
;
|
||||
; if (edge->surfs[0])
|
||||
; u_check++; // sort trailers after leaders
|
||||
add eax,esi
|
||||
|
||||
; if (!newedges[v] || newedges[v]->u >= u_check)
|
||||
; {
|
||||
mov esi,ds:dword ptr[_newedges+ebx*4]
|
||||
test esi,esi
|
||||
jz LDoFirst
|
||||
cmp ds:dword ptr[et_u+esi],eax
|
||||
jl LNotFirst
|
||||
LDoFirst:
|
||||
|
||||
; edge->next = newedges[v];
|
||||
; newedges[v] = edge;
|
||||
mov ds:dword ptr[et_next+edi],esi
|
||||
mov ds:dword ptr[_newedges+ebx*4],edi
|
||||
|
||||
jmp LSetRemove
|
||||
|
||||
; }
|
||||
|
||||
LNotFirst:
|
||||
|
||||
; else
|
||||
; {
|
||||
; pcheck = newedges[v];
|
||||
;
|
||||
; while (pcheck->next && pcheck->next->u < u_check)
|
||||
; pcheck = pcheck->next;
|
||||
LFindInsertLoop:
|
||||
mov edx,esi
|
||||
mov esi,ds:dword ptr[et_next+esi]
|
||||
test esi,esi
|
||||
jz LInsertFound
|
||||
cmp ds:dword ptr[et_u+esi],eax
|
||||
jl LFindInsertLoop
|
||||
|
||||
LInsertFound:
|
||||
|
||||
; edge->next = pcheck->next;
|
||||
; pcheck->next = edge;
|
||||
mov ds:dword ptr[et_next+edi],esi
|
||||
mov ds:dword ptr[et_next+edx],edi
|
||||
|
||||
; }
|
||||
|
||||
LSetRemove:
|
||||
|
||||
; edge->nextremove = removeedges[v2];
|
||||
; removeedges[v2] = edge;
|
||||
mov eax,ds:dword ptr[_removeedges+ecx*4]
|
||||
mov ds:dword ptr[_removeedges+ecx*4],edi
|
||||
mov ds:dword ptr[et_nextremove+edi],eax
|
||||
|
||||
Ldone:
|
||||
mov esp,ds:dword ptr[Lstack] ; clear temporary variables from stack
|
||||
|
||||
pop ebx ; restore register variables
|
||||
pop edi
|
||||
pop esi
|
||||
ret
|
||||
|
||||
; at least one point is clipped
|
||||
|
||||
Lp2:
|
||||
test eax,eax
|
||||
jns Lp1
|
||||
|
||||
; else
|
||||
; {
|
||||
; // point 0 is clipped
|
||||
|
||||
; if (d1 < 0)
|
||||
; {
|
||||
mov eax,ds:dword ptr[Ld1]
|
||||
test eax,eax
|
||||
jns Lp3
|
||||
|
||||
; // both points are clipped
|
||||
; // we do cache fully clipped edges
|
||||
; if (!leftclipped)
|
||||
mov eax,ds:dword ptr[_r_leftclipped]
|
||||
mov ecx,ds:dword ptr[_r_pedge]
|
||||
test eax,eax
|
||||
jnz Ldone
|
||||
|
||||
; r_pedge->framecount = r_framecount;
|
||||
mov eax,ds:dword ptr[_r_framecount]
|
||||
and eax,offset FRAMECOUNT_MASK
|
||||
or eax,offset FULLY_CLIPPED_CACHED
|
||||
mov ds:dword ptr[_cacheoffset],eax
|
||||
|
||||
; 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);
|
||||
fld ds:dword ptr[Ld0]
|
||||
fld ds:dword ptr[Ld1]
|
||||
fsubr st(0),st(1)
|
||||
|
||||
; // we don't cache partially clipped edges
|
||||
mov ds:dword ptr[_cacheoffset],07FFFFFFFh
|
||||
|
||||
fdivp st(1),st(0)
|
||||
|
||||
sub esp,offset mv_size ; 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]);
|
||||
fld ds:dword ptr[mv_position+8+edx]
|
||||
fsub ds:dword ptr[mv_position+8+esi]
|
||||
fld ds:dword ptr[mv_position+4+edx]
|
||||
fsub ds:dword ptr[mv_position+4+esi]
|
||||
fld ds:dword ptr[mv_position+0+edx]
|
||||
fsub ds:dword ptr[mv_position+0+esi] ; 0 | 1 | 2
|
||||
|
||||
; replace pv1 with the clip point
|
||||
mov edx,esp
|
||||
mov eax,ds:dword ptr[cp_leftedge+ebx]
|
||||
test al,al
|
||||
|
||||
fmul st(0),st(3)
|
||||
fxch st(1) ; 1 | 0 | 2
|
||||
fmul st(0),st(3)
|
||||
fxch st(2) ; 2 | 0 | 1
|
||||
fmulp st(3),st(0) ; 0 | 1 | 2
|
||||
fadd ds:dword ptr[mv_position+0+esi]
|
||||
fxch st(1) ; 1 | 0 | 2
|
||||
fadd ds:dword ptr[mv_position+4+esi]
|
||||
fxch st(2) ; 2 | 0 | 1
|
||||
fadd ds:dword ptr[mv_position+8+esi]
|
||||
fxch st(1) ; 0 | 2 | 1
|
||||
fstp ds:dword ptr[mv_position+0+esp] ; 2 | 1
|
||||
fstp ds:dword ptr[mv_position+8+esp] ; 1
|
||||
fstp ds:dword ptr[mv_position+4+esp]
|
||||
|
||||
; if (clip->leftedge)
|
||||
; {
|
||||
jz Ltestright
|
||||
|
||||
; r_leftclipped = true;
|
||||
; r_leftexit = clipvert;
|
||||
mov ds:dword ptr[_r_leftclipped],1
|
||||
mov eax,ds:dword ptr[mv_position+0+esp]
|
||||
mov ds:dword ptr[_r_leftexit+mv_position+0],eax
|
||||
mov eax,ds:dword ptr[mv_position+4+esp]
|
||||
mov ds:dword ptr[_r_leftexit+mv_position+4],eax
|
||||
mov eax,ds:dword ptr[mv_position+8+esp]
|
||||
mov ds:dword ptr[_r_leftexit+mv_position+8],eax
|
||||
|
||||
jmp Lcontinue
|
||||
|
||||
; }
|
||||
|
||||
Ltestright:
|
||||
; else if (clip->rightedge)
|
||||
; {
|
||||
test ah,ah
|
||||
jz Lcontinue
|
||||
|
||||
; r_rightclipped = true;
|
||||
; r_rightexit = clipvert;
|
||||
mov ds:dword ptr[_r_rightclipped],1
|
||||
mov eax,ds:dword ptr[mv_position+0+esp]
|
||||
mov ds:dword ptr[_r_rightexit+mv_position+0],eax
|
||||
mov eax,ds:dword ptr[mv_position+4+esp]
|
||||
mov ds:dword ptr[_r_rightexit+mv_position+4],eax
|
||||
mov eax,ds:dword ptr[mv_position+8+esp]
|
||||
mov ds:dword ptr[_r_rightexit+mv_position+8],eax
|
||||
|
||||
; }
|
||||
;
|
||||
; R_ClipEdge (pv0, &clipvert, clip->next);
|
||||
; return;
|
||||
; }
|
||||
jmp Lcontinue
|
||||
|
||||
; }
|
||||
|
||||
Lp3:
|
||||
|
||||
; // only point 0 is clipped
|
||||
; r_lastvertvalid = false;
|
||||
|
||||
mov ds:dword ptr[_r_lastvertvalid],0
|
||||
|
||||
; f = d0 / (d0 - d1);
|
||||
fld ds:dword ptr[Ld0]
|
||||
fld ds:dword ptr[Ld1]
|
||||
fsubr st(0),st(1)
|
||||
|
||||
; // we don't cache partially clipped edges
|
||||
mov ds:dword ptr[_cacheoffset],07FFFFFFFh
|
||||
|
||||
fdivp st(1),st(0)
|
||||
|
||||
sub esp,offset mv_size ; 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]);
|
||||
fld ds:dword ptr[mv_position+8+edx]
|
||||
fsub ds:dword ptr[mv_position+8+esi]
|
||||
fld ds:dword ptr[mv_position+4+edx]
|
||||
fsub ds:dword ptr[mv_position+4+esi]
|
||||
fld ds:dword ptr[mv_position+0+edx]
|
||||
fsub ds:dword ptr[mv_position+0+esi] ; 0 | 1 | 2
|
||||
|
||||
mov eax,ds:dword ptr[cp_leftedge+ebx]
|
||||
test al,al
|
||||
|
||||
fmul st(0),st(3)
|
||||
fxch st(1) ; 1 | 0 | 2
|
||||
fmul st(0),st(3)
|
||||
fxch st(2) ; 2 | 0 | 1
|
||||
fmulp st(3),st(0) ; 0 | 1 | 2
|
||||
fadd ds:dword ptr[mv_position+0+esi]
|
||||
fxch st(1) ; 1 | 0 | 2
|
||||
fadd ds:dword ptr[mv_position+4+esi]
|
||||
fxch st(2) ; 2 | 0 | 1
|
||||
fadd ds:dword ptr[mv_position+8+esi]
|
||||
fxch st(1) ; 0 | 2 | 1
|
||||
fstp ds:dword ptr[mv_position+0+esp] ; 2 | 1
|
||||
fstp ds:dword ptr[mv_position+8+esp] ; 1
|
||||
fstp ds:dword ptr[mv_position+4+esp]
|
||||
|
||||
; replace pv0 with the clip point
|
||||
mov esi,esp
|
||||
|
||||
; if (clip->leftedge)
|
||||
; {
|
||||
jz Ltestright2
|
||||
|
||||
; r_leftclipped = true;
|
||||
; r_leftenter = clipvert;
|
||||
mov ds:dword ptr[_r_leftclipped],1
|
||||
mov eax,ds:dword ptr[mv_position+0+esp]
|
||||
mov ds:dword ptr[_r_leftenter+mv_position+0],eax
|
||||
mov eax,ds:dword ptr[mv_position+4+esp]
|
||||
mov ds:dword ptr[_r_leftenter+mv_position+4],eax
|
||||
mov eax,ds:dword ptr[mv_position+8+esp]
|
||||
mov ds:dword ptr[_r_leftenter+mv_position+8],eax
|
||||
|
||||
jmp Lcontinue
|
||||
|
||||
; }
|
||||
|
||||
Ltestright2:
|
||||
; else if (clip->rightedge)
|
||||
; {
|
||||
test ah,ah
|
||||
jz Lcontinue
|
||||
|
||||
; r_rightclipped = true;
|
||||
; r_rightenter = clipvert;
|
||||
mov ds:dword ptr[_r_rightclipped],1
|
||||
mov eax,ds:dword ptr[mv_position+0+esp]
|
||||
mov ds:dword ptr[_r_rightenter+mv_position+0],eax
|
||||
mov eax,ds:dword ptr[mv_position+4+esp]
|
||||
mov ds:dword ptr[_r_rightenter+mv_position+4],eax
|
||||
mov eax,ds:dword ptr[mv_position+8+esp]
|
||||
mov ds:dword ptr[_r_rightenter+mv_position+8],eax
|
||||
|
||||
; }
|
||||
jmp Lcontinue
|
||||
|
||||
; %esi = vec3_t point to transform and project
|
||||
; %edx preserved
|
||||
LTransformAndProject:
|
||||
|
||||
; // transform and project
|
||||
; VectorSubtract (world, modelorg, local);
|
||||
fld ds:dword ptr[mv_position+0+esi]
|
||||
fsub ds:dword ptr[_modelorg+0]
|
||||
fld ds:dword ptr[mv_position+4+esi]
|
||||
fsub ds:dword ptr[_modelorg+4]
|
||||
fld ds:dword ptr[mv_position+8+esi]
|
||||
fsub ds:dword ptr[_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]
|
||||
fmul ds:dword ptr[_vpn+0] ; zm0 | local[0] | local[1] | local[2]
|
||||
fld st(1) ; local[0] | zm0 | local[0] | local[1] |
|
||||
; local[2]
|
||||
fmul ds:dword ptr[_vright+0] ; xm0 | zm0 | local[0] | local[1] | local[2]
|
||||
fxch st(2) ; local[0] | zm0 | xm0 | local[1] | local[2]
|
||||
fmul ds:dword ptr[_vup+0] ; ym0 | zm0 | xm0 | local[1] | local[2]
|
||||
fld st(3) ; local[1] | ym0 | zm0 | xm0 | local[1] |
|
||||
; local[2]
|
||||
fmul ds:dword ptr[_vpn+4] ; zm1 | ym0 | zm0 | xm0 | local[1] |
|
||||
; local[2]
|
||||
fld st(4) ; local[1] | zm1 | ym0 | zm0 | xm0 |
|
||||
; local[1] | local[2]
|
||||
fmul ds:dword ptr[_vright+4] ; xm1 | zm1 | ym0 | zm0 | xm0 |
|
||||
; local[1] | local[2]
|
||||
fxch st(5) ; local[1] | zm1 | ym0 | zm0 | xm0 |
|
||||
; xm1 | local[2]
|
||||
fmul ds:dword ptr[_vup+4] ; ym1 | zm1 | ym0 | zm0 | xm0 |
|
||||
; xm1 | local[2]
|
||||
fxch st(1) ; zm1 | ym1 | ym0 | zm0 | xm0 |
|
||||
; xm1 | local[2]
|
||||
faddp st(3),st(0) ; ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
|
||||
fxch st(3) ; xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
|
||||
faddp st(4),st(0) ; ym0 | zm2 | ym1 | xm2 | local[2]
|
||||
faddp st(2),st(0) ; zm2 | ym2 | xm2 | local[2]
|
||||
fld st(3) ; local[2] | zm2 | ym2 | xm2 | local[2]
|
||||
fmul ds:dword ptr[_vpn+8] ; zm3 | zm2 | ym2 | xm2 | local[2]
|
||||
fld st(4) ; local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
|
||||
fmul ds:dword ptr[_vright+8] ; xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
|
||||
fxch st(5) ; local[2] | zm3 | zm2 | ym2 | xm2 | xm3
|
||||
fmul ds:dword ptr[_vup+8] ; ym3 | zm3 | zm2 | ym2 | xm2 | xm3
|
||||
fxch st(1) ; zm3 | ym3 | zm2 | ym2 | xm2 | xm3
|
||||
faddp st(2),st(0) ; ym3 | zm4 | ym2 | xm2 | xm3
|
||||
fxch st(4) ; xm3 | zm4 | ym2 | xm2 | ym3
|
||||
faddp st(3),st(0) ; zm4 | ym2 | xm4 | ym3
|
||||
fxch st(1) ; ym2 | zm4 | xm4 | ym3
|
||||
faddp st(3),st(0) ; zm4 | xm4 | ym4
|
||||
|
||||
fcom ds:dword ptr[Lfp_near_clip]
|
||||
fnstsw ax
|
||||
test ah,1
|
||||
jz LNoClip
|
||||
fstp st(0)
|
||||
fld ds:dword ptr[Lfp_near_clip]
|
||||
|
||||
LNoClip:
|
||||
|
||||
fdivr ds:dword ptr[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]);
|
||||
fld ds:dword ptr[_xscale] ; xscale | x | lzi0 | y
|
||||
fmul st(0),st(2) ; scale | x | lzi0 | y
|
||||
fmulp st(1),st(0) ; scale*x | lzi0 | y
|
||||
fadd ds:dword ptr[_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?
|
||||
fcom ds:dword ptr[_r_refdef+rd_fvrectx_adj]
|
||||
fnstsw ax
|
||||
test ah,1
|
||||
jz LClampP0
|
||||
fstp st(0)
|
||||
fld ds:dword ptr[_r_refdef+rd_fvrectx_adj]
|
||||
LClampP0:
|
||||
fcom ds:dword ptr[_r_refdef+rd_fvrectright_adj]
|
||||
fnstsw ax
|
||||
test ah,045h
|
||||
jnz LClampP1
|
||||
fstp st(0)
|
||||
fld ds:dword ptr[_r_refdef+rd_fvrectright_adj]
|
||||
LClampP1:
|
||||
|
||||
fld st(1) ; lzi0 | u0 | lzi0 | y
|
||||
|
||||
; scale = yscale * lzi0;
|
||||
; v0 = (ycenter - scale*transformed[1]);
|
||||
fmul ds:dword ptr[_yscale] ; scale | u0 | lzi0 | y
|
||||
fmulp st(3),st(0) ; u0 | lzi0 | scale*y
|
||||
fxch st(2) ; scale*y | lzi0 | u0
|
||||
fsubr ds:dword ptr[_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?
|
||||
fcom ds:dword ptr[_r_refdef+rd_fvrecty_adj]
|
||||
fnstsw ax
|
||||
test ah,1
|
||||
jz LClampP2
|
||||
fstp st(0)
|
||||
fld ds:dword ptr[_r_refdef+rd_fvrecty_adj]
|
||||
LClampP2:
|
||||
fcom ds:dword ptr[_r_refdef+rd_fvrectbottom_adj]
|
||||
fnstsw ax
|
||||
test ah,045h
|
||||
jnz LClampP3
|
||||
fstp st(0)
|
||||
fld ds:dword ptr[_r_refdef+rd_fvrectbottom_adj]
|
||||
LClampP3:
|
||||
ret
|
||||
|
||||
|
||||
_TEXT ENDS
|
||||
endif ;id386
|
||||
END
|
||||
1125
ref_soft/r_edge.c
Normal file
1125
ref_soft/r_edge.c
Normal file
File diff suppressed because it is too large
Load Diff
733
ref_soft/r_edgea.asm
Normal file
733
ref_soft/r_edgea.asm
Normal file
@@ -0,0 +1,733 @@
|
||||
.386P
|
||||
.model FLAT
|
||||
;
|
||||
; r_edgea.s
|
||||
; x86 assembly-language edge-processing code.
|
||||
;
|
||||
|
||||
include qasm.inc
|
||||
|
||||
if id386
|
||||
|
||||
_DATA SEGMENT
|
||||
Ltemp dd 0
|
||||
float_1_div_0100000h dd 035800000h ; 1.0/(float)0x100000
|
||||
float_point_999 dd 0.999
|
||||
float_1_point_001 dd 1.001
|
||||
|
||||
_DATA ENDS
|
||||
_TEXT SEGMENT
|
||||
|
||||
;--------------------------------------------------------------------
|
||||
|
||||
edgestoadd equ 4+8 ; note odd stack offsets because of interleaving
|
||||
edgelist equ 8+12 ; with pushes
|
||||
|
||||
public _R_EdgeCodeStart
|
||||
_R_EdgeCodeStart:
|
||||
|
||||
public _R_InsertNewEdges
|
||||
_R_InsertNewEdges:
|
||||
push edi
|
||||
push esi ; preserve register variables
|
||||
mov edx,ds:dword ptr[edgestoadd+esp]
|
||||
push ebx
|
||||
mov ecx,ds:dword ptr[edgelist+esp]
|
||||
|
||||
LDoNextEdge:
|
||||
mov eax,ds:dword ptr[et_u+edx]
|
||||
mov edi,edx
|
||||
|
||||
LContinueSearch:
|
||||
mov ebx,ds:dword ptr[et_u+ecx]
|
||||
mov esi,ds:dword ptr[et_next+ecx]
|
||||
cmp eax,ebx
|
||||
jle LAddedge
|
||||
mov ebx,ds:dword ptr[et_u+esi]
|
||||
mov ecx,ds:dword ptr[et_next+esi]
|
||||
cmp eax,ebx
|
||||
jle LAddedge2
|
||||
mov ebx,ds:dword ptr[et_u+ecx]
|
||||
mov esi,ds:dword ptr[et_next+ecx]
|
||||
cmp eax,ebx
|
||||
jle LAddedge
|
||||
mov ebx,ds:dword ptr[et_u+esi]
|
||||
mov ecx,ds:dword ptr[et_next+esi]
|
||||
cmp eax,ebx
|
||||
jg LContinueSearch
|
||||
|
||||
LAddedge2:
|
||||
mov edx,ds:dword ptr[et_next+edx]
|
||||
mov ebx,ds:dword ptr[et_prev+esi]
|
||||
mov ds:dword ptr[et_next+edi],esi
|
||||
mov ds:dword ptr[et_prev+edi],ebx
|
||||
mov ds:dword ptr[et_next+ebx],edi
|
||||
mov ds:dword ptr[et_prev+esi],edi
|
||||
mov ecx,esi
|
||||
|
||||
cmp edx,0
|
||||
jnz LDoNextEdge
|
||||
jmp LDone
|
||||
|
||||
align 4
|
||||
LAddedge:
|
||||
mov edx,ds:dword ptr[et_next+edx]
|
||||
mov ebx,ds:dword ptr[et_prev+ecx]
|
||||
mov ds:dword ptr[et_next+edi],ecx
|
||||
mov ds:dword ptr[et_prev+edi],ebx
|
||||
mov ds:dword ptr[et_next+ebx],edi
|
||||
mov ds:dword ptr[et_prev+ecx],edi
|
||||
|
||||
cmp edx,0
|
||||
jnz LDoNextEdge
|
||||
|
||||
LDone:
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
pop edi
|
||||
|
||||
ret
|
||||
|
||||
;--------------------------------------------------------------------
|
||||
|
||||
predge equ 4+4
|
||||
|
||||
public _R_RemoveEdges
|
||||
_R_RemoveEdges:
|
||||
push ebx
|
||||
mov eax,ds:dword ptr[predge+esp]
|
||||
|
||||
Lre_loop:
|
||||
mov ecx,ds:dword ptr[et_next+eax]
|
||||
mov ebx,ds:dword ptr[et_nextremove+eax]
|
||||
mov edx,ds:dword ptr[et_prev+eax]
|
||||
test ebx,ebx
|
||||
mov ds:dword ptr[et_prev+ecx],edx
|
||||
jz Lre_done
|
||||
mov ds:dword ptr[et_next+edx],ecx
|
||||
|
||||
mov ecx,ds:dword ptr[et_next+ebx]
|
||||
mov edx,ds:dword ptr[et_prev+ebx]
|
||||
mov eax,ds:dword ptr[et_nextremove+ebx]
|
||||
mov ds:dword ptr[et_prev+ecx],edx
|
||||
test eax,eax
|
||||
mov ds:dword ptr[et_next+edx],ecx
|
||||
jnz Lre_loop
|
||||
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
Lre_done:
|
||||
mov ds:dword ptr[et_next+edx],ecx
|
||||
pop ebx
|
||||
|
||||
ret
|
||||
|
||||
;--------------------------------------------------------------------
|
||||
|
||||
pedgelist equ 4+4 ; note odd stack offset because of interleaving
|
||||
; with pushes
|
||||
|
||||
public _R_StepActiveU
|
||||
_R_StepActiveU:
|
||||
push edi
|
||||
mov edx,ds:dword ptr[pedgelist+esp]
|
||||
push esi ; preserve register variables
|
||||
push ebx
|
||||
|
||||
mov esi,ds:dword ptr[et_prev+edx]
|
||||
|
||||
LNewEdge:
|
||||
mov edi,ds:dword ptr[et_u+esi]
|
||||
|
||||
LNextEdge:
|
||||
mov eax,ds:dword ptr[et_u+edx]
|
||||
mov ebx,ds:dword ptr[et_u_step+edx]
|
||||
add eax,ebx
|
||||
mov esi,ds:dword ptr[et_next+edx]
|
||||
mov ds:dword ptr[et_u+edx],eax
|
||||
cmp eax,edi
|
||||
jl LPushBack
|
||||
|
||||
mov edi,ds:dword ptr[et_u+esi]
|
||||
mov ebx,ds:dword ptr[et_u_step+esi]
|
||||
add edi,ebx
|
||||
mov edx,ds:dword ptr[et_next+esi]
|
||||
mov ds:dword ptr[et_u+esi],edi
|
||||
cmp edi,eax
|
||||
jl LPushBack2
|
||||
|
||||
mov eax,ds:dword ptr[et_u+edx]
|
||||
mov ebx,ds:dword ptr[et_u_step+edx]
|
||||
add eax,ebx
|
||||
mov esi,ds:dword ptr[et_next+edx]
|
||||
mov ds:dword ptr[et_u+edx],eax
|
||||
cmp eax,edi
|
||||
jl LPushBack
|
||||
|
||||
mov edi,ds:dword ptr[et_u+esi]
|
||||
mov ebx,ds:dword ptr[et_u_step+esi]
|
||||
add edi,ebx
|
||||
mov edx,ds:dword ptr[et_next+esi]
|
||||
mov ds:dword ptr[et_u+esi],edi
|
||||
cmp edi,eax
|
||||
jnl LNextEdge
|
||||
|
||||
LPushBack2:
|
||||
mov ebx,edx
|
||||
mov eax,edi
|
||||
mov edx,esi
|
||||
mov esi,ebx
|
||||
|
||||
LPushBack:
|
||||
; push it back to keep it sorted
|
||||
mov ecx,ds:dword ptr[et_prev+edx]
|
||||
mov ebx,ds:dword ptr[et_next+edx]
|
||||
|
||||
; done if the -1 in edge_aftertail triggered this
|
||||
cmp edx,offset _edge_aftertail
|
||||
jz LUDone
|
||||
|
||||
; pull the edge out of the edge list
|
||||
mov edi,ds:dword ptr[et_prev+ecx]
|
||||
mov ds:dword ptr[et_prev+esi],ecx
|
||||
mov ds:dword ptr[et_next+ecx],ebx
|
||||
|
||||
; find out where the edge goes in the edge list
|
||||
LPushBackLoop:
|
||||
mov ecx,ds:dword ptr[et_prev+edi]
|
||||
mov ebx,ds:dword ptr[et_u+edi]
|
||||
cmp eax,ebx
|
||||
jnl LPushBackFound
|
||||
|
||||
mov edi,ds:dword ptr[et_prev+ecx]
|
||||
mov ebx,ds:dword ptr[et_u+ecx]
|
||||
cmp eax,ebx
|
||||
jl LPushBackLoop
|
||||
|
||||
mov edi,ecx
|
||||
|
||||
; put the edge back into the edge list
|
||||
LPushBackFound:
|
||||
mov ebx,ds:dword ptr[et_next+edi]
|
||||
mov ds:dword ptr[et_prev+edx],edi
|
||||
mov ds:dword ptr[et_next+edx],ebx
|
||||
mov ds:dword ptr[et_next+edi],edx
|
||||
mov ds:dword ptr[et_prev+ebx],edx
|
||||
|
||||
mov edx,esi
|
||||
mov esi,ds:dword ptr[et_prev+esi]
|
||||
|
||||
cmp edx,offset _edge_tail
|
||||
jnz LNewEdge
|
||||
|
||||
LUDone:
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
pop edi
|
||||
|
||||
ret
|
||||
|
||||
;--------------------------------------------------------------------
|
||||
|
||||
surf equ 4 ; note this is loaded before any pushes
|
||||
|
||||
align 4
|
||||
TrailingEdge:
|
||||
mov eax,ds:dword ptr[st_spanstate+esi] ; check for edge inversion
|
||||
dec eax
|
||||
jnz LInverted
|
||||
|
||||
mov ds:dword ptr[st_spanstate+esi],eax
|
||||
mov ecx,ds:dword ptr[st_insubmodel+esi]
|
||||
mov edx,ds:dword ptr[12345678h] ; surfaces[1].st_next
|
||||
LPatch0:
|
||||
mov eax,ds:dword ptr[_r_bmodelactive]
|
||||
sub eax,ecx
|
||||
cmp edx,esi
|
||||
mov ds:dword ptr[_r_bmodelactive],eax
|
||||
jnz LNoEmit ; surface isn't on top, just remove
|
||||
|
||||
; emit a span (current top going away)
|
||||
mov eax,ds:dword ptr[et_u+ebx]
|
||||
shr eax,20 ; iu = integral pixel u
|
||||
mov edx,ds:dword ptr[st_last_u+esi]
|
||||
mov ecx,ds:dword ptr[st_next+esi]
|
||||
cmp eax,edx
|
||||
jle LNoEmit2 ; iu <= surf->last_u, so nothing to emit
|
||||
|
||||
mov ds:dword ptr[st_last_u+ecx],eax ; surf->next->last_u = iu;
|
||||
sub eax,edx
|
||||
mov ds:dword ptr[espan_t_u+ebp],edx ; span->u = surf->last_u;
|
||||
|
||||
mov ds:dword ptr[espan_t_count+ebp],eax ; span->count = iu - span->u;
|
||||
mov eax,ds:dword ptr[_current_iv]
|
||||
mov ds:dword ptr[espan_t_v+ebp],eax ; span->v = current_iv;
|
||||
mov eax,ds:dword ptr[st_spans+esi]
|
||||
mov ds:dword ptr[espan_t_pnext+ebp],eax ; span->pnext = surf->spans;
|
||||
mov ds:dword ptr[st_spans+esi],ebp ; surf->spans = span;
|
||||
add ebp,offset espan_t_size
|
||||
|
||||
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
|
||||
mov esi,ds:dword ptr[st_prev+esi] ; stack
|
||||
|
||||
mov ds:dword ptr[st_next+esi],edx
|
||||
mov ds:dword ptr[st_prev+edx],esi
|
||||
ret
|
||||
|
||||
LNoEmit2:
|
||||
mov ds:dword ptr[st_last_u+ecx],eax ; surf->next->last_u = iu;
|
||||
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
|
||||
mov esi,ds:dword ptr[st_prev+esi] ; stack
|
||||
|
||||
mov ds:dword ptr[st_next+esi],edx
|
||||
mov ds:dword ptr[st_prev+edx],esi
|
||||
ret
|
||||
|
||||
LNoEmit:
|
||||
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
|
||||
mov esi,ds:dword ptr[st_prev+esi] ; stack
|
||||
|
||||
mov ds:dword ptr[st_next+esi],edx
|
||||
mov ds:dword ptr[st_prev+edx],esi
|
||||
ret
|
||||
|
||||
LInverted:
|
||||
mov ds:dword ptr[st_spanstate+esi],eax
|
||||
ret
|
||||
|
||||
;--------------------------------------------------------------------
|
||||
|
||||
; trailing edge only
|
||||
Lgs_trailing:
|
||||
push offset Lgs_nextedge
|
||||
jmp TrailingEdge
|
||||
|
||||
|
||||
public _R_GenerateSpans
|
||||
_R_GenerateSpans:
|
||||
push ebp ; preserve caller's stack frame
|
||||
push edi
|
||||
push esi ; preserve register variables
|
||||
push ebx
|
||||
|
||||
; clear active surfaces to just the background surface
|
||||
mov eax,ds:dword ptr[_surfaces]
|
||||
mov edx,ds:dword ptr[_edge_head_u_shift20]
|
||||
add eax,offset st_size
|
||||
; %ebp = span_p throughout
|
||||
mov ebp,ds:dword ptr[_span_p]
|
||||
|
||||
mov ds:dword ptr[_r_bmodelactive],0
|
||||
|
||||
mov ds:dword ptr[st_next+eax],eax
|
||||
mov ds:dword ptr[st_prev+eax],eax
|
||||
mov ds:dword ptr[st_last_u+eax],edx
|
||||
mov ebx,ds:dword ptr[_edge_head+et_next] ; edge=edge_head.next
|
||||
|
||||
; generate spans
|
||||
cmp ebx,offset _edge_tail ; done if empty list
|
||||
jz Lgs_lastspan
|
||||
|
||||
Lgs_edgeloop:
|
||||
|
||||
mov edi,ds:dword ptr[et_surfs+ebx]
|
||||
mov eax,ds:dword ptr[_surfaces]
|
||||
mov esi,edi
|
||||
and edi,0FFFF0000h
|
||||
and esi,0FFFFh
|
||||
jz Lgs_leading ; not a trailing edge
|
||||
|
||||
; it has a left surface, so a surface is going away for this span
|
||||
shl esi,offset SURF_T_SHIFT
|
||||
add esi,eax
|
||||
test edi,edi
|
||||
jz Lgs_trailing
|
||||
|
||||
; both leading and trailing
|
||||
call near ptr TrailingEdge
|
||||
mov eax,ds:dword ptr[_surfaces]
|
||||
|
||||
; ---------------------------------------------------------------
|
||||
; handle a leading edge
|
||||
; ---------------------------------------------------------------
|
||||
|
||||
Lgs_leading:
|
||||
shr edi,16-SURF_T_SHIFT
|
||||
mov eax,ds:dword ptr[_surfaces]
|
||||
add edi,eax
|
||||
mov esi,ds:dword ptr[12345678h] ; surf2 = surfaces[1].next;
|
||||
LPatch2:
|
||||
mov edx,ds:dword ptr[st_spanstate+edi]
|
||||
mov eax,ds:dword ptr[st_insubmodel+edi]
|
||||
test 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)
|
||||
test edx,edx
|
||||
jnz Lxl_done
|
||||
|
||||
|
||||
; if (surf->key < surf2->key)
|
||||
; goto newtop;
|
||||
inc edx
|
||||
mov eax,ds:dword ptr[st_key+edi]
|
||||
mov ds:dword ptr[st_spanstate+edi],edx
|
||||
mov ecx,ds:dword ptr[st_key+esi]
|
||||
cmp eax,ecx
|
||||
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:
|
||||
mov esi,ds:dword ptr[st_next+esi]
|
||||
mov ecx,ds:dword ptr[st_key+esi]
|
||||
cmp eax,ecx
|
||||
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)
|
||||
test edx,edx
|
||||
jnz Lxl_done
|
||||
|
||||
mov ecx,ds:dword ptr[_r_bmodelactive]
|
||||
inc edx
|
||||
inc ecx
|
||||
mov ds:dword ptr[st_spanstate+edi],edx
|
||||
mov ds:dword ptr[_r_bmodelactive],ecx
|
||||
|
||||
; if (surf->key < surf2->key)
|
||||
; goto newtop;
|
||||
mov eax,ds:dword ptr[st_key+edi]
|
||||
mov ecx,ds:dword ptr[st_key+esi]
|
||||
cmp eax,ecx
|
||||
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:
|
||||
mov esi,ds:dword ptr[st_next+esi]
|
||||
mov ecx,ds:dword ptr[st_key+esi]
|
||||
cmp eax,ecx
|
||||
jg Lsortloop
|
||||
|
||||
jne LInsertAndExit
|
||||
|
||||
; Do 1/z sorting to see if we've arrived in the right position
|
||||
mov eax,ds:dword ptr[et_u+ebx]
|
||||
sub eax,0FFFFFh
|
||||
mov ds:dword ptr[Ltemp],eax
|
||||
fild ds:dword ptr[Ltemp]
|
||||
|
||||
fmul ds:dword ptr[float_1_div_0100000h] ; fu = (float)(edge->u - 0xFFFFF) *
|
||||
; (1.0 / 0x100000);
|
||||
|
||||
fld st(0) ; fu | fu
|
||||
fmul ds:dword ptr[st_d_zistepu+edi] ; fu*surf->d_zistepu | fu
|
||||
fld ds:dword ptr[_fv] ; fv | fu*surf->d_zistepu | fu
|
||||
fmul ds:dword ptr[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
|
||||
fadd ds:dword ptr[st_d_ziorigin+edi] ; fu*surf->d_zistepu + surf->d_ziorigin |
|
||||
; fv*surf->d_zistepv | fu
|
||||
|
||||
fld ds:dword ptr[st_d_zistepu+esi] ; surf2->d_zistepu |
|
||||
; fu*surf->d_zistepu + surf->d_ziorigin |
|
||||
; fv*surf->d_zistepv | fu
|
||||
fmul st(0),st(3) ; 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(2),st(0) ; fu*surf2->d_zistepu | newzi | fu
|
||||
|
||||
fld ds:dword ptr[_fv] ; fv | fu*surf2->d_zistepu | newzi | fu
|
||||
fmul ds:dword ptr[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
|
||||
fmul ds:dword ptr[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
|
||||
fadd ds:dword ptr[st_d_ziorigin+esi] ; fu*surf2->d_zistepu + surf2->d_ziorigin |
|
||||
; fv*surf2->d_zistepv | newzibottom | newzi |
|
||||
; fu
|
||||
faddp st(1),st(0) ; 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
|
||||
fmul ds:dword ptr[float_1_point_001] ; newzitop | testzi | fu
|
||||
fxch st(1) ; testzi | newzitop | fu
|
||||
|
||||
fnstsw ax
|
||||
test ah,001h
|
||||
jz Lgotposition_fpop3
|
||||
|
||||
; if (newzitop >= testzi)
|
||||
; {
|
||||
|
||||
fcomp st(1) ; newzitop | fu
|
||||
fnstsw ax
|
||||
test ah,045h
|
||||
jz Lsortloop_fpop2
|
||||
|
||||
; if (surf->d_zistepu >= surf2->d_zistepu)
|
||||
; goto newtop;
|
||||
|
||||
fld ds:dword ptr[st_d_zistepu+edi] ; surf->d_zistepu | newzitop| fu
|
||||
fcomp ds:dword ptr[st_d_zistepu+esi] ; newzitop | fu
|
||||
fnstsw ax
|
||||
test ah,001h
|
||||
jz Lgotposition_fpop2
|
||||
|
||||
fstp st(0) ; clear the FPstack
|
||||
fstp st(0)
|
||||
mov eax,ds:dword ptr[st_key+edi]
|
||||
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)
|
||||
mov eax,ds:dword ptr[st_key+edi] ; reload the sorting key
|
||||
|
||||
Lnewtop:
|
||||
mov eax,ds:dword ptr[et_u+ebx]
|
||||
mov edx,ds:dword ptr[st_last_u+esi]
|
||||
shr eax,20 ; iu = integral pixel u
|
||||
mov ds:dword ptr[st_last_u+edi],eax ; surf->last_u = iu;
|
||||
cmp eax,edx
|
||||
jle LInsertAndExit ; iu <= surf->last_u, so nothing to emit
|
||||
|
||||
sub eax,edx
|
||||
mov ds:dword ptr[espan_t_u+ebp],edx ; span->u = surf->last_u;
|
||||
|
||||
mov ds:dword ptr[espan_t_count+ebp],eax ; span->count = iu - span->u;
|
||||
mov eax,ds:dword ptr[_current_iv]
|
||||
mov ds:dword ptr[espan_t_v+ebp],eax ; span->v = current_iv;
|
||||
mov eax,ds:dword ptr[st_spans+esi]
|
||||
mov ds:dword ptr[espan_t_pnext+ebp],eax ; span->pnext = surf->spans;
|
||||
mov ds:dword ptr[st_spans+esi],ebp ; surf->spans = span;
|
||||
add ebp,offset espan_t_size
|
||||
|
||||
LInsertAndExit:
|
||||
; insert before surf2
|
||||
mov ds:dword ptr[st_next+edi],esi ; surf->next = surf2;
|
||||
mov eax,ds:dword ptr[st_prev+esi]
|
||||
mov ds:dword ptr[st_prev+edi],eax ; surf->prev = surf2->prev;
|
||||
mov ds:dword ptr[st_prev+esi],edi ; surf2->prev = surf;
|
||||
mov ds:dword ptr[st_next+eax],edi ; surf2->prev->next = surf;
|
||||
|
||||
; ---------------------------------------------------------------
|
||||
; leading edge done
|
||||
; ---------------------------------------------------------------
|
||||
|
||||
; ---------------------------------------------------------------
|
||||
; see if there are any more edges
|
||||
; ---------------------------------------------------------------
|
||||
|
||||
Lgs_nextedge:
|
||||
mov ebx,ds:dword ptr[et_next+ebx]
|
||||
cmp ebx,offset _edge_tail
|
||||
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
|
||||
mov esi,ds:dword ptr[12345678h] ; surfaces[1].st_next
|
||||
LPatch3:
|
||||
mov eax,ds:dword ptr[_edge_tail_u_shift20]
|
||||
xor ecx,ecx
|
||||
mov edx,ds:dword ptr[st_last_u+esi]
|
||||
sub eax,edx
|
||||
jle Lgs_resetspanstate
|
||||
|
||||
mov ds:dword ptr[espan_t_u+ebp],edx
|
||||
mov ds:dword ptr[espan_t_count+ebp],eax
|
||||
mov eax,ds:dword ptr[_current_iv]
|
||||
mov ds:dword ptr[espan_t_v+ebp],eax
|
||||
mov eax,ds:dword ptr[st_spans+esi]
|
||||
mov ds:dword ptr[espan_t_pnext+ebp],eax
|
||||
mov ds:dword ptr[st_spans+esi],ebp
|
||||
add ebp,offset espan_t_size
|
||||
|
||||
; reset spanstate for all surfaces in the surface stack
|
||||
Lgs_resetspanstate:
|
||||
mov ds:dword ptr[st_spanstate+esi],ecx
|
||||
mov esi,ds:dword ptr[st_next+esi]
|
||||
cmp esi,012345678h ; &surfaces[1]
|
||||
LPatch4:
|
||||
jnz Lgs_resetspanstate
|
||||
|
||||
; store the final span_p
|
||||
mov ds:dword ptr[_span_p],ebp
|
||||
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp ; restore the caller's stack frame
|
||||
ret
|
||||
|
||||
|
||||
; ---------------------------------------------------------------
|
||||
; 1/z sorting for bmodels in the same leaf
|
||||
; ---------------------------------------------------------------
|
||||
align 4
|
||||
Lxl_done:
|
||||
inc edx
|
||||
mov ds:dword ptr[st_spanstate+edi],edx
|
||||
|
||||
jmp Lgs_nextedge
|
||||
|
||||
|
||||
align 4
|
||||
Lzcheck_for_newtop:
|
||||
mov eax,ds:dword ptr[et_u+ebx]
|
||||
sub eax,0FFFFFh
|
||||
mov ds:dword ptr[Ltemp],eax
|
||||
fild ds:dword ptr[Ltemp]
|
||||
|
||||
fmul ds:dword ptr[float_1_div_0100000h] ; fu = (float)(edge->u - 0xFFFFF) *
|
||||
; (1.0 / 0x100000);
|
||||
|
||||
fld st(0) ; fu | fu
|
||||
fmul ds:dword ptr[st_d_zistepu+edi] ; fu*surf->d_zistepu | fu
|
||||
fld ds:dword ptr[_fv] ; fv | fu*surf->d_zistepu | fu
|
||||
fmul ds:dword ptr[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
|
||||
fadd ds:dword ptr[st_d_ziorigin+edi] ; fu*surf->d_zistepu + surf->d_ziorigin |
|
||||
; fv*surf->d_zistepv | fu
|
||||
|
||||
fld ds:dword ptr[st_d_zistepu+esi] ; surf2->d_zistepu |
|
||||
; fu*surf->d_zistepu + surf->d_ziorigin |
|
||||
; fv*surf->d_zistepv | fu
|
||||
fmul st(0),st(3) ; 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(2),st(0) ; fu*surf2->d_zistepu | newzi | fu
|
||||
|
||||
fld ds:dword ptr[_fv] ; fv | fu*surf2->d_zistepu | newzi | fu
|
||||
fmul ds:dword ptr[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
|
||||
fmul ds:dword ptr[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
|
||||
fadd ds:dword ptr[st_d_ziorigin+esi] ; fu*surf2->d_zistepu + surf2->d_ziorigin |
|
||||
; fv*surf2->d_zistepv | newzibottom | newzi |
|
||||
; fu
|
||||
faddp st(1),st(0) ; 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
|
||||
fmul ds:dword ptr[float_1_point_001] ; newzitop | testzi | fu
|
||||
fxch st(1) ; testzi | newzitop | fu
|
||||
|
||||
fnstsw ax
|
||||
test ah,001h
|
||||
jz Lnewtop_fpop3
|
||||
|
||||
; if (newzitop >= testzi)
|
||||
; {
|
||||
|
||||
fcomp st(1) ; newzitop | fu
|
||||
fnstsw ax
|
||||
test ah,045h
|
||||
jz Lsortloop_fpop2
|
||||
|
||||
; if (surf->d_zistepu >= surf2->d_zistepu)
|
||||
; goto newtop;
|
||||
|
||||
fld ds:dword ptr[st_d_zistepu+edi] ; surf->d_zistepu | newzitop | fu
|
||||
fcomp ds:dword ptr[st_d_zistepu+esi] ; newzitop | fu
|
||||
fnstsw ax
|
||||
test ah,001h
|
||||
jz Lnewtop_fpop2
|
||||
|
||||
Lsortloop_fpop2:
|
||||
fstp st(0) ; clear the FP stack
|
||||
fstp st(0)
|
||||
mov eax,ds:dword ptr[st_key+edi]
|
||||
jmp Lsortloop
|
||||
|
||||
|
||||
public _R_EdgeCodeEnd
|
||||
_R_EdgeCodeEnd:
|
||||
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; Surface array address code patching routine
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
public _R_SurfacePatch
|
||||
_R_SurfacePatch:
|
||||
|
||||
mov eax,ds:dword ptr[_surfaces]
|
||||
add eax,offset st_size
|
||||
mov ds:dword ptr[LPatch4-4],eax
|
||||
|
||||
add eax,offset st_next
|
||||
mov ds:dword ptr[LPatch0-4],eax
|
||||
mov ds:dword ptr[LPatch2-4],eax
|
||||
mov ds:dword ptr[LPatch3-4],eax
|
||||
|
||||
ret
|
||||
|
||||
_TEXT ENDS
|
||||
endif ;id386
|
||||
END
|
||||
617
ref_soft/r_image.c
Normal file
617
ref_soft/r_image.c
Normal file
@@ -0,0 +1,617 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
|
||||
#define MAX_RIMAGES 1024
|
||||
image_t r_images[MAX_RIMAGES];
|
||||
int numr_images;
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ImageList_f
|
||||
===============
|
||||
*/
|
||||
void R_ImageList_f (void)
|
||||
{
|
||||
int i;
|
||||
image_t *image;
|
||||
int texels;
|
||||
|
||||
ri.Con_Printf (PRINT_ALL, "------------------\n");
|
||||
texels = 0;
|
||||
|
||||
for (i=0, image=r_images ; i<numr_images ; i++, image++)
|
||||
{
|
||||
if (image->registration_sequence <= 0)
|
||||
continue;
|
||||
texels += image->width*image->height;
|
||||
switch (image->type)
|
||||
{
|
||||
case it_skin:
|
||||
ri.Con_Printf (PRINT_ALL, "M");
|
||||
break;
|
||||
case it_sprite:
|
||||
ri.Con_Printf (PRINT_ALL, "S");
|
||||
break;
|
||||
case it_wall:
|
||||
ri.Con_Printf (PRINT_ALL, "W");
|
||||
break;
|
||||
case it_pic:
|
||||
ri.Con_Printf (PRINT_ALL, "P");
|
||||
break;
|
||||
default:
|
||||
ri.Con_Printf (PRINT_ALL, " ");
|
||||
break;
|
||||
}
|
||||
|
||||
ri.Con_Printf (PRINT_ALL, " %3i %3i : %s\n",
|
||||
image->width, image->height, image->name);
|
||||
}
|
||||
ri.Con_Printf (PRINT_ALL, "Total texel count: %i\n", texels);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================================================================
|
||||
|
||||
PCX LOADING
|
||||
|
||||
=================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
==============
|
||||
LoadPCX
|
||||
==============
|
||||
*/
|
||||
void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
|
||||
{
|
||||
byte *raw;
|
||||
pcx_t *pcx;
|
||||
int x, y;
|
||||
int len;
|
||||
int dataByte, runLength;
|
||||
byte *out, *pix;
|
||||
|
||||
*pic = NULL;
|
||||
|
||||
//
|
||||
// load the file
|
||||
//
|
||||
len = ri.FS_LoadFile (filename, (void **)&raw);
|
||||
if (!raw)
|
||||
{
|
||||
ri.Con_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// parse the PCX file
|
||||
//
|
||||
pcx = (pcx_t *)raw;
|
||||
|
||||
pcx->xmin = LittleShort(pcx->xmin);
|
||||
pcx->ymin = LittleShort(pcx->ymin);
|
||||
pcx->xmax = LittleShort(pcx->xmax);
|
||||
pcx->ymax = LittleShort(pcx->ymax);
|
||||
pcx->hres = LittleShort(pcx->hres);
|
||||
pcx->vres = LittleShort(pcx->vres);
|
||||
pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
|
||||
pcx->palette_type = LittleShort(pcx->palette_type);
|
||||
|
||||
raw = &pcx->data;
|
||||
|
||||
if (pcx->manufacturer != 0x0a
|
||||
|| pcx->version != 5
|
||||
|| pcx->encoding != 1
|
||||
|| pcx->bits_per_pixel != 8
|
||||
|| pcx->xmax >= 640
|
||||
|| pcx->ymax >= 480)
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "Bad pcx file %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
|
||||
|
||||
*pic = out;
|
||||
|
||||
pix = out;
|
||||
|
||||
if (palette)
|
||||
{
|
||||
*palette = malloc(768);
|
||||
memcpy (*palette, (byte *)pcx + len - 768, 768);
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = pcx->xmax+1;
|
||||
if (height)
|
||||
*height = pcx->ymax+1;
|
||||
|
||||
for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
|
||||
{
|
||||
for (x=0 ; x<=pcx->xmax ; )
|
||||
{
|
||||
dataByte = *raw++;
|
||||
|
||||
if((dataByte & 0xC0) == 0xC0)
|
||||
{
|
||||
runLength = dataByte & 0x3F;
|
||||
dataByte = *raw++;
|
||||
}
|
||||
else
|
||||
runLength = 1;
|
||||
|
||||
while(runLength-- > 0)
|
||||
pix[x++] = dataByte;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( raw - (byte *)pcx > len)
|
||||
{
|
||||
ri.Con_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename);
|
||||
free (*pic);
|
||||
*pic = NULL;
|
||||
}
|
||||
|
||||
ri.FS_FreeFile (pcx);
|
||||
}
|
||||
|
||||
/*
|
||||
=========================================================
|
||||
|
||||
TARGA LOADING
|
||||
|
||||
=========================================================
|
||||
*/
|
||||
|
||||
typedef struct _TargaHeader {
|
||||
unsigned char id_length, colormap_type, image_type;
|
||||
unsigned short colormap_index, colormap_length;
|
||||
unsigned char colormap_size;
|
||||
unsigned short x_origin, y_origin, width, height;
|
||||
unsigned char pixel_size, attributes;
|
||||
} TargaHeader;
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
LoadTGA
|
||||
=============
|
||||
*/
|
||||
void LoadTGA (char *name, byte **pic, int *width, int *height)
|
||||
{
|
||||
int columns, rows, numPixels;
|
||||
byte *pixbuf;
|
||||
int row, column;
|
||||
byte *buf_p;
|
||||
byte *buffer;
|
||||
int length;
|
||||
TargaHeader targa_header;
|
||||
byte *targa_rgba;
|
||||
|
||||
*pic = NULL;
|
||||
|
||||
//
|
||||
// load the file
|
||||
//
|
||||
length = ri.FS_LoadFile (name, (void **)&buffer);
|
||||
if (!buffer)
|
||||
{
|
||||
ri.Con_Printf (PRINT_DEVELOPER, "Bad tga file %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
buf_p = buffer;
|
||||
|
||||
targa_header.id_length = *buf_p++;
|
||||
targa_header.colormap_type = *buf_p++;
|
||||
targa_header.image_type = *buf_p++;
|
||||
|
||||
targa_header.colormap_index = LittleShort ( *((short *)buf_p) );
|
||||
buf_p+=2;
|
||||
targa_header.colormap_length = LittleShort ( *((short *)buf_p) );
|
||||
buf_p+=2;
|
||||
targa_header.colormap_size = *buf_p++;
|
||||
targa_header.x_origin = LittleShort ( *((short *)buf_p) );
|
||||
buf_p+=2;
|
||||
targa_header.y_origin = LittleShort ( *((short *)buf_p) );
|
||||
buf_p+=2;
|
||||
targa_header.width = LittleShort ( *((short *)buf_p) );
|
||||
buf_p+=2;
|
||||
targa_header.height = LittleShort ( *((short *)buf_p) );
|
||||
buf_p+=2;
|
||||
targa_header.pixel_size = *buf_p++;
|
||||
targa_header.attributes = *buf_p++;
|
||||
|
||||
if (targa_header.image_type!=2
|
||||
&& targa_header.image_type!=10)
|
||||
ri.Sys_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n");
|
||||
|
||||
if (targa_header.colormap_type !=0
|
||||
|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
|
||||
ri.Sys_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
|
||||
|
||||
columns = targa_header.width;
|
||||
rows = targa_header.height;
|
||||
numPixels = columns * rows;
|
||||
|
||||
if (width)
|
||||
*width = columns;
|
||||
if (height)
|
||||
*height = rows;
|
||||
|
||||
targa_rgba = malloc (numPixels*4);
|
||||
*pic = targa_rgba;
|
||||
|
||||
if (targa_header.id_length != 0)
|
||||
buf_p += targa_header.id_length; // skip TARGA image comment
|
||||
|
||||
if (targa_header.image_type==2) { // Uncompressed, RGB images
|
||||
for(row=rows-1; row>=0; row--) {
|
||||
pixbuf = targa_rgba + row*columns*4;
|
||||
for(column=0; column<columns; column++) {
|
||||
unsigned char red,green,blue,alphabyte;
|
||||
switch (targa_header.pixel_size) {
|
||||
case 24:
|
||||
|
||||
blue = *buf_p++;
|
||||
green = *buf_p++;
|
||||
red = *buf_p++;
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = *buf_p++;
|
||||
green = *buf_p++;
|
||||
red = *buf_p++;
|
||||
alphabyte = *buf_p++;
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alphabyte;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (targa_header.image_type==10) { // Runlength encoded RGB images
|
||||
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
|
||||
for(row=rows-1; row>=0; row--) {
|
||||
pixbuf = targa_rgba + row*columns*4;
|
||||
for(column=0; column<columns; ) {
|
||||
packetHeader= *buf_p++;
|
||||
packetSize = 1 + (packetHeader & 0x7f);
|
||||
if (packetHeader & 0x80) { // run-length packet
|
||||
switch (targa_header.pixel_size) {
|
||||
case 24:
|
||||
blue = *buf_p++;
|
||||
green = *buf_p++;
|
||||
red = *buf_p++;
|
||||
alphabyte = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = *buf_p++;
|
||||
green = *buf_p++;
|
||||
red = *buf_p++;
|
||||
alphabyte = *buf_p++;
|
||||
break;
|
||||
}
|
||||
|
||||
for(j=0;j<packetSize;j++) {
|
||||
*pixbuf++=red;
|
||||
*pixbuf++=green;
|
||||
*pixbuf++=blue;
|
||||
*pixbuf++=alphabyte;
|
||||
column++;
|
||||
if (column==columns) { // run spans across rows
|
||||
column=0;
|
||||
if (row>0)
|
||||
row--;
|
||||
else
|
||||
goto breakOut;
|
||||
pixbuf = targa_rgba + row*columns*4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // non run-length packet
|
||||
for(j=0;j<packetSize;j++) {
|
||||
switch (targa_header.pixel_size) {
|
||||
case 24:
|
||||
blue = *buf_p++;
|
||||
green = *buf_p++;
|
||||
red = *buf_p++;
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = *buf_p++;
|
||||
green = *buf_p++;
|
||||
red = *buf_p++;
|
||||
alphabyte = *buf_p++;
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alphabyte;
|
||||
break;
|
||||
}
|
||||
column++;
|
||||
if (column==columns) { // pixel packet run spans across rows
|
||||
column=0;
|
||||
if (row>0)
|
||||
row--;
|
||||
else
|
||||
goto breakOut;
|
||||
pixbuf = targa_rgba + row*columns*4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
breakOut:;
|
||||
}
|
||||
}
|
||||
|
||||
ri.FS_FreeFile (buffer);
|
||||
}
|
||||
|
||||
|
||||
//=======================================================
|
||||
|
||||
image_t *R_FindFreeImage (void)
|
||||
{
|
||||
image_t *image;
|
||||
int i;
|
||||
|
||||
// find a free image_t
|
||||
for (i=0, image=r_images ; i<numr_images ; i++,image++)
|
||||
{
|
||||
if (!image->registration_sequence)
|
||||
break;
|
||||
}
|
||||
if (i == numr_images)
|
||||
{
|
||||
if (numr_images == MAX_RIMAGES)
|
||||
ri.Sys_Error (ERR_DROP, "MAX_RIMAGES");
|
||||
numr_images++;
|
||||
}
|
||||
image = &r_images[i];
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_LoadPic
|
||||
|
||||
================
|
||||
*/
|
||||
image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
|
||||
{
|
||||
image_t *image;
|
||||
int i, c, b;
|
||||
|
||||
image = R_FindFreeImage ();
|
||||
if (strlen(name) >= sizeof(image->name))
|
||||
ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
|
||||
strcpy (image->name, name);
|
||||
image->registration_sequence = registration_sequence;
|
||||
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->type = type;
|
||||
|
||||
c = width*height;
|
||||
image->pixels[0] = malloc (c);
|
||||
image->transparent = false;
|
||||
for (i=0 ; i<c ; i++)
|
||||
{
|
||||
b = pic[i];
|
||||
if (b == 255)
|
||||
image->transparent = true;
|
||||
image->pixels[0][i] = b;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_LoadWal
|
||||
================
|
||||
*/
|
||||
image_t *R_LoadWal (char *name)
|
||||
{
|
||||
miptex_t *mt;
|
||||
int ofs;
|
||||
image_t *image;
|
||||
int size;
|
||||
|
||||
ri.FS_LoadFile (name, (void **)&mt);
|
||||
if (!mt)
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "R_LoadWal: can't load %s\n", name);
|
||||
return r_notexture_mip;
|
||||
}
|
||||
|
||||
image = R_FindFreeImage ();
|
||||
strcpy (image->name, name);
|
||||
image->width = LittleLong (mt->width);
|
||||
image->height = LittleLong (mt->height);
|
||||
image->type = it_wall;
|
||||
image->registration_sequence = registration_sequence;
|
||||
|
||||
size = image->width*image->height * (256+64+16+4)/256;
|
||||
image->pixels[0] = malloc (size);
|
||||
image->pixels[1] = image->pixels[0] + image->width*image->height;
|
||||
image->pixels[2] = image->pixels[1] + image->width*image->height/4;
|
||||
image->pixels[3] = image->pixels[2] + image->width*image->height/16;
|
||||
|
||||
ofs = LittleLong (mt->offsets[0]);
|
||||
memcpy ( image->pixels[0], (byte *)mt + ofs, size);
|
||||
|
||||
ri.FS_FreeFile ((void *)mt);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_FindImage
|
||||
|
||||
Finds or loads the given image
|
||||
===============
|
||||
*/
|
||||
image_t *R_FindImage (char *name, imagetype_t type)
|
||||
{
|
||||
image_t *image;
|
||||
int i, len;
|
||||
byte *pic, *palette;
|
||||
int width, height;
|
||||
|
||||
if (!name)
|
||||
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: NULL name");
|
||||
len = strlen(name);
|
||||
if (len<5)
|
||||
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name);
|
||||
|
||||
// look for it
|
||||
for (i=0, image=r_images ; i<numr_images ; i++,image++)
|
||||
{
|
||||
if (!strcmp(name, image->name))
|
||||
{
|
||||
image->registration_sequence = registration_sequence;
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// load the pic from disk
|
||||
//
|
||||
pic = NULL;
|
||||
palette = NULL;
|
||||
if (!strcmp(name+len-4, ".pcx"))
|
||||
{
|
||||
LoadPCX (name, &pic, &palette, &width, &height);
|
||||
if (!pic)
|
||||
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s", name);
|
||||
image = GL_LoadPic (name, pic, width, height, type);
|
||||
}
|
||||
else if (!strcmp(name+len-4, ".wal"))
|
||||
{
|
||||
image = R_LoadWal (name);
|
||||
}
|
||||
else if (!strcmp(name+len-4, ".tga"))
|
||||
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s in software renderer", name);
|
||||
else
|
||||
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad extension on: %s", name);
|
||||
|
||||
if (pic)
|
||||
free(pic);
|
||||
if (palette)
|
||||
free(palette);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_RegisterSkin
|
||||
===============
|
||||
*/
|
||||
struct image_s *R_RegisterSkin (char *name)
|
||||
{
|
||||
return R_FindImage (name, it_skin);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_FreeUnusedImages
|
||||
|
||||
Any image that was not touched on this registration sequence
|
||||
will be freed.
|
||||
================
|
||||
*/
|
||||
void R_FreeUnusedImages (void)
|
||||
{
|
||||
int i;
|
||||
image_t *image;
|
||||
|
||||
for (i=0, image=r_images ; i<numr_images ; i++, image++)
|
||||
{
|
||||
if (image->registration_sequence == registration_sequence)
|
||||
{
|
||||
Com_PageInMemory ((byte *)image->pixels[0], image->width*image->height);
|
||||
continue; // used this sequence
|
||||
}
|
||||
if (!image->registration_sequence)
|
||||
continue; // free texture
|
||||
if (image->type == it_pic)
|
||||
continue; // don't free pics
|
||||
// free it
|
||||
free (image->pixels[0]); // the other mip levels just follow
|
||||
memset (image, 0, sizeof(*image));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_InitImages
|
||||
===============
|
||||
*/
|
||||
void R_InitImages (void)
|
||||
{
|
||||
registration_sequence = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ShutdownImages
|
||||
===============
|
||||
*/
|
||||
void R_ShutdownImages (void)
|
||||
{
|
||||
int i;
|
||||
image_t *image;
|
||||
|
||||
for (i=0, image=r_images ; i<numr_images ; i++, image++)
|
||||
{
|
||||
if (!image->registration_sequence)
|
||||
continue; // free texture
|
||||
// free it
|
||||
free (image->pixels[0]); // the other mip levels just follow
|
||||
memset (image, 0, sizeof(*image));
|
||||
}
|
||||
}
|
||||
|
||||
442
ref_soft/r_light.c
Normal file
442
ref_soft/r_light.c
Normal file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// r_light.c
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
int r_dlightframecount;
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
DYNAMIC LIGHTS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=============
|
||||
R_MarkLights
|
||||
=============
|
||||
*/
|
||||
void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
|
||||
{
|
||||
mplane_t *splitplane;
|
||||
float dist;
|
||||
msurface_t *surf;
|
||||
int i;
|
||||
|
||||
if (node->contents != -1)
|
||||
return;
|
||||
|
||||
splitplane = node->plane;
|
||||
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
|
||||
|
||||
//=====
|
||||
//PGM
|
||||
i=light->intensity;
|
||||
if(i<0)
|
||||
i=-i;
|
||||
//PGM
|
||||
//=====
|
||||
|
||||
if (dist > i) // PGM (dist > light->intensity)
|
||||
{
|
||||
R_MarkLights (light, bit, node->children[0]);
|
||||
return;
|
||||
}
|
||||
if (dist < -i) // PGM (dist < -light->intensity)
|
||||
{
|
||||
R_MarkLights (light, bit, node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
// mark the polygons
|
||||
surf = r_worldmodel->surfaces + node->firstsurface;
|
||||
for (i=0 ; i<node->numsurfaces ; i++, surf++)
|
||||
{
|
||||
if (surf->dlightframe != r_dlightframecount)
|
||||
{
|
||||
surf->dlightbits = 0;
|
||||
surf->dlightframe = r_dlightframecount;
|
||||
}
|
||||
surf->dlightbits |= bit;
|
||||
}
|
||||
|
||||
R_MarkLights (light, bit, node->children[0]);
|
||||
R_MarkLights (light, bit, node->children[1]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PushDlights
|
||||
=============
|
||||
*/
|
||||
void R_PushDlights (model_t *model)
|
||||
{
|
||||
int i;
|
||||
dlight_t *l;
|
||||
|
||||
r_dlightframecount = r_framecount;
|
||||
for (i=0, l = r_newrefdef.dlights ; i<r_newrefdef.num_dlights ; i++, l++)
|
||||
{
|
||||
R_MarkLights ( l, 1<<i,
|
||||
model->nodes + model->firstnode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LIGHT SAMPLING
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
vec3_t pointcolor;
|
||||
mplane_t *lightplane; // used as shadow plane
|
||||
vec3_t lightspot;
|
||||
|
||||
int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
|
||||
{
|
||||
float front, back, frac;
|
||||
int side;
|
||||
mplane_t *plane;
|
||||
vec3_t mid;
|
||||
msurface_t *surf;
|
||||
int s, t, ds, dt;
|
||||
int i;
|
||||
mtexinfo_t *tex;
|
||||
byte *lightmap;
|
||||
float *scales;
|
||||
int maps;
|
||||
float samp;
|
||||
int r;
|
||||
|
||||
if (node->contents != -1)
|
||||
return -1; // didn't hit anything
|
||||
|
||||
// calculate mid point
|
||||
|
||||
// FIXME: optimize for axial
|
||||
plane = node->plane;
|
||||
front = DotProduct (start, plane->normal) - plane->dist;
|
||||
back = DotProduct (end, plane->normal) - plane->dist;
|
||||
side = front < 0;
|
||||
|
||||
if ( (back < 0) == side)
|
||||
return RecursiveLightPoint (node->children[side], start, end);
|
||||
|
||||
frac = front / (front-back);
|
||||
mid[0] = start[0] + (end[0] - start[0])*frac;
|
||||
mid[1] = start[1] + (end[1] - start[1])*frac;
|
||||
mid[2] = start[2] + (end[2] - start[2])*frac;
|
||||
if (plane->type < 3) // axial planes
|
||||
mid[plane->type] = plane->dist;
|
||||
|
||||
// go down front side
|
||||
r = RecursiveLightPoint (node->children[side], start, mid);
|
||||
if (r >= 0)
|
||||
return r; // hit something
|
||||
|
||||
if ( (back < 0) == side )
|
||||
return -1; // didn't hit anuthing
|
||||
|
||||
// check for impact on this node
|
||||
VectorCopy (mid, lightspot);
|
||||
lightplane = plane;
|
||||
|
||||
surf = r_worldmodel->surfaces + node->firstsurface;
|
||||
for (i=0 ; i<node->numsurfaces ; i++, surf++)
|
||||
{
|
||||
if (surf->flags&(SURF_DRAWTURB|SURF_DRAWSKY))
|
||||
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;
|
||||
VectorCopy (vec3_origin, pointcolor);
|
||||
if (lightmap)
|
||||
{
|
||||
lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
|
||||
|
||||
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
|
||||
maps++)
|
||||
{
|
||||
samp = *lightmap * /* 0.5 * */ (1.0/255); // adjust for gl scale
|
||||
scales = r_newrefdef.lightstyles[surf->styles[maps]].rgb;
|
||||
VectorMA (pointcolor, samp, scales, pointcolor);
|
||||
lightmap += ((surf->extents[0]>>4)+1) *
|
||||
((surf->extents[1]>>4)+1);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return RecursiveLightPoint (node->children[!side], mid, end);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_LightPoint
|
||||
===============
|
||||
*/
|
||||
void R_LightPoint (vec3_t p, vec3_t color)
|
||||
{
|
||||
vec3_t end;
|
||||
float r;
|
||||
int lnum;
|
||||
dlight_t *dl;
|
||||
float light;
|
||||
vec3_t dist;
|
||||
float add;
|
||||
|
||||
if (!r_worldmodel->lightdata)
|
||||
{
|
||||
color[0] = color[1] = color[2] = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
end[0] = p[0];
|
||||
end[1] = p[1];
|
||||
end[2] = p[2] - 2048;
|
||||
|
||||
r = RecursiveLightPoint (r_worldmodel->nodes, p, end);
|
||||
|
||||
if (r == -1)
|
||||
{
|
||||
VectorCopy (vec3_origin, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy (pointcolor, color);
|
||||
}
|
||||
|
||||
//
|
||||
// add dynamic lights
|
||||
//
|
||||
light = 0;
|
||||
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
|
||||
{
|
||||
dl = &r_newrefdef.dlights[lnum];
|
||||
VectorSubtract (currententity->origin,
|
||||
dl->origin,
|
||||
dist);
|
||||
add = dl->intensity - VectorLength(dist);
|
||||
add *= (1.0/256);
|
||||
if (add > 0)
|
||||
{
|
||||
VectorMA (color, add, dl->color, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
|
||||
|
||||
unsigned blocklights[1024]; // allow some very large lightmaps
|
||||
|
||||
/*
|
||||
===============
|
||||
R_AddDynamicLights
|
||||
===============
|
||||
*/
|
||||
void R_AddDynamicLights (void)
|
||||
{
|
||||
msurface_t *surf;
|
||||
int lnum;
|
||||
int sd, td;
|
||||
float dist, rad, minlight;
|
||||
vec3_t impact, local;
|
||||
int s, t;
|
||||
int i;
|
||||
int smax, tmax;
|
||||
mtexinfo_t *tex;
|
||||
dlight_t *dl;
|
||||
int negativeLight; //PGM
|
||||
|
||||
surf = r_drawsurf.surf;
|
||||
smax = (surf->extents[0]>>4)+1;
|
||||
tmax = (surf->extents[1]>>4)+1;
|
||||
tex = surf->texinfo;
|
||||
|
||||
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
|
||||
{
|
||||
if ( !(surf->dlightbits & (1<<lnum) ) )
|
||||
continue; // not lit by this light
|
||||
|
||||
dl = &r_newrefdef.dlights[lnum];
|
||||
rad = dl->intensity;
|
||||
|
||||
//=====
|
||||
//PGM
|
||||
negativeLight = 0;
|
||||
if(rad < 0)
|
||||
{
|
||||
negativeLight = 1;
|
||||
rad = -rad;
|
||||
}
|
||||
//PGM
|
||||
//=====
|
||||
|
||||
dist = DotProduct (dl->origin, surf->plane->normal) -
|
||||
surf->plane->dist;
|
||||
rad -= fabs(dist);
|
||||
minlight = 32; // dl->minlight;
|
||||
if (rad < minlight)
|
||||
continue;
|
||||
minlight = rad - minlight;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
impact[i] = dl->origin[i] -
|
||||
surf->plane->normal[i]*dist;
|
||||
}
|
||||
|
||||
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
|
||||
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
|
||||
|
||||
local[0] -= surf->texturemins[0];
|
||||
local[1] -= surf->texturemins[1];
|
||||
|
||||
for (t = 0 ; t<tmax ; t++)
|
||||
{
|
||||
td = local[1] - t*16;
|
||||
if (td < 0)
|
||||
td = -td;
|
||||
for (s=0 ; s<smax ; s++)
|
||||
{
|
||||
sd = local[0] - s*16;
|
||||
if (sd < 0)
|
||||
sd = -sd;
|
||||
if (sd > td)
|
||||
dist = sd + (td>>1);
|
||||
else
|
||||
dist = td + (sd>>1);
|
||||
//====
|
||||
//PGM
|
||||
if(!negativeLight)
|
||||
{
|
||||
if (dist < minlight)
|
||||
blocklights[t*smax + s] += (rad - dist)*256;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dist < minlight)
|
||||
blocklights[t*smax + s] -= (rad - dist)*256;
|
||||
if(blocklights[t*smax + s] < minlight)
|
||||
blocklights[t*smax + s] = minlight;
|
||||
}
|
||||
//PGM
|
||||
//====
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_BuildLightMap
|
||||
|
||||
Combine and scale multiple lightmaps into the 8.8 format in blocklights
|
||||
===============
|
||||
*/
|
||||
void R_BuildLightMap (void)
|
||||
{
|
||||
int smax, tmax;
|
||||
int t;
|
||||
int i, size;
|
||||
byte *lightmap;
|
||||
unsigned scale;
|
||||
int maps;
|
||||
msurface_t *surf;
|
||||
|
||||
surf = r_drawsurf.surf;
|
||||
|
||||
smax = (surf->extents[0]>>4)+1;
|
||||
tmax = (surf->extents[1]>>4)+1;
|
||||
size = smax*tmax;
|
||||
|
||||
if (r_fullbright->value || !r_worldmodel->lightdata)
|
||||
{
|
||||
for (i=0 ; i<size ; i++)
|
||||
blocklights[i] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// clear to no light
|
||||
for (i=0 ; i<size ; i++)
|
||||
blocklights[i] = 0;
|
||||
|
||||
|
||||
// add all the lightmaps
|
||||
lightmap = surf->samples;
|
||||
if (lightmap)
|
||||
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
|
||||
maps++)
|
||||
{
|
||||
scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
|
||||
for (i=0 ; i<size ; i++)
|
||||
blocklights[i] += lightmap[i] * scale;
|
||||
lightmap += size; // skip to next lightmap
|
||||
}
|
||||
|
||||
// add all the dynamic lights
|
||||
if (surf->dlightframe == r_framecount)
|
||||
R_AddDynamicLights ();
|
||||
|
||||
// bound, invert, and shift
|
||||
for (i=0 ; i<size ; i++)
|
||||
{
|
||||
t = (int)blocklights[i];
|
||||
if (t < 0)
|
||||
t = 0;
|
||||
t = (255*256 - t) >> (8 - VID_CBITS);
|
||||
|
||||
if (t < (1 << 6))
|
||||
t = (1 << 6);
|
||||
|
||||
blocklights[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
849
ref_soft/r_local.h
Normal file
849
ref_soft/r_local.h
Normal file
@@ -0,0 +1,849 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "../client/ref.h"
|
||||
|
||||
#define REF_VERSION "SOFT 0.01"
|
||||
|
||||
// up / down
|
||||
#define PITCH 0
|
||||
|
||||
// left / right
|
||||
#define YAW 1
|
||||
|
||||
// fall over
|
||||
#define ROLL 2
|
||||
|
||||
|
||||
/*
|
||||
|
||||
skins will be outline flood filled and mip mapped
|
||||
pics and sprites with alpha will be outline flood filled
|
||||
pic won't be mip mapped
|
||||
|
||||
model skin
|
||||
sprite frame
|
||||
wall texture
|
||||
pic
|
||||
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
it_skin,
|
||||
it_sprite,
|
||||
it_wall,
|
||||
it_pic,
|
||||
it_sky
|
||||
} imagetype_t;
|
||||
|
||||
typedef struct image_s
|
||||
{
|
||||
char name[MAX_QPATH]; // game path, including extension
|
||||
imagetype_t type;
|
||||
int width, height;
|
||||
qboolean transparent; // true if any 255 pixels in image
|
||||
int registration_sequence; // 0 = free
|
||||
byte *pixels[4]; // mip levels
|
||||
} image_t;
|
||||
|
||||
|
||||
//===================================================================
|
||||
|
||||
typedef unsigned char pixel_t;
|
||||
|
||||
typedef struct vrect_s
|
||||
{
|
||||
int x,y,width,height;
|
||||
struct vrect_s *pnext;
|
||||
} vrect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pixel_t *buffer; // invisible buffer
|
||||
pixel_t *colormap; // 256 * VID_GRADES size
|
||||
pixel_t *alphamap; // 256 * 256 translucency map
|
||||
int rowbytes; // may be > width if displayed in a window
|
||||
// can be negative for stupid dibs
|
||||
int width;
|
||||
int height;
|
||||
} viddef_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
rserr_ok,
|
||||
|
||||
rserr_invalid_fullscreen,
|
||||
rserr_invalid_mode,
|
||||
|
||||
rserr_unknown
|
||||
} rserr_t;
|
||||
|
||||
extern viddef_t vid;
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct
|
||||
{
|
||||
vrect_t vrect; // subwindow in video for refresh
|
||||
// FIXME: not need vrect next field here?
|
||||
vrect_t aliasvrect; // scaled Alias version
|
||||
int vrectright, vrectbottom; // right & bottom screen coords
|
||||
int aliasvrectright, aliasvrectbottom; // scaled Alias versions
|
||||
float vrectrightedge; // rightmost right edge we care about,
|
||||
// for use in edge list
|
||||
float fvrectx, fvrecty; // for floating-point compares
|
||||
float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping
|
||||
int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20
|
||||
int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20
|
||||
float fvrectright_adj, fvrectbottom_adj;
|
||||
// right and bottom edges, for clamping
|
||||
float fvrectright; // rightmost edge, for Alias clamping
|
||||
float fvrectbottom; // bottommost edge, for Alias clamping
|
||||
float horizontalFieldOfView; // at Z = 1.0, this many X is visible
|
||||
// 2.0 = 90 degrees
|
||||
float xOrigin; // should probably always be 0.5
|
||||
float yOrigin; // between be around 0.3 to 0.5
|
||||
|
||||
vec3_t vieworg;
|
||||
vec3_t viewangles;
|
||||
|
||||
int ambientlight;
|
||||
} oldrefdef_t;
|
||||
|
||||
extern oldrefdef_t r_refdef;
|
||||
|
||||
#include "r_model.h"
|
||||
|
||||
#define CACHE_SIZE 32
|
||||
|
||||
/*
|
||||
====================================================
|
||||
|
||||
CONSTANTS
|
||||
|
||||
====================================================
|
||||
*/
|
||||
|
||||
#define VID_CBITS 6
|
||||
#define VID_GRADES (1 << VID_CBITS)
|
||||
|
||||
|
||||
// r_shared.h: general refresh-related stuff shared between the refresh and the
|
||||
// driver
|
||||
|
||||
|
||||
#define MAXVERTS 64 // 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 1200
|
||||
#define MAXWIDTH 1600
|
||||
|
||||
#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
|
||||
// be farther away than anything in
|
||||
// the scene
|
||||
|
||||
|
||||
// d_iface.h: interface header file for rasterization driver modules
|
||||
|
||||
#define WARP_WIDTH 320
|
||||
#define WARP_HEIGHT 240
|
||||
|
||||
#define MAX_LBM_HEIGHT 480
|
||||
|
||||
|
||||
#define PARTICLE_Z_CLIP 8.0
|
||||
|
||||
// !!! must be kept the same as in quakeasm.h !!!
|
||||
#define TRANSPARENT_COLOR 0xFF
|
||||
|
||||
|
||||
// !!! 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 SCANBUFFERPAD 0x1000
|
||||
|
||||
#define DS_SPAN_LIST_END -128
|
||||
|
||||
#define NUMSTACKEDGES 2000
|
||||
#define MINEDGES NUMSTACKEDGES
|
||||
#define NUMSTACKSURFACES 1000
|
||||
#define MINSURFACES NUMSTACKSURFACES
|
||||
#define MAXSPANS 3000
|
||||
|
||||
// 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
|
||||
#define ALIAS_XY_CLIP_MASK 0x000F
|
||||
|
||||
#define SURFCACHE_SIZE_AT_320X240 1024*768
|
||||
|
||||
#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox ()
|
||||
// if bbox is trivially rejected
|
||||
|
||||
#define XCENTERING (1.0 / 2.0)
|
||||
#define YCENTERING (1.0 / 2.0)
|
||||
|
||||
#define CLIP_EPSILON 0.001
|
||||
|
||||
#define BACKFACE_EPSILON 0.01
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
#define NEAR_CLIP 0.01
|
||||
|
||||
|
||||
#define MAXALIASVERTS 2000 // TODO: tune this
|
||||
#define ALIAS_Z_CLIP_PLANE 4
|
||||
|
||||
// turbulence stuff
|
||||
|
||||
#define AMP 8*0x10000
|
||||
#define AMP2 3
|
||||
#define SPEED 20
|
||||
|
||||
|
||||
/*
|
||||
====================================================
|
||||
|
||||
TYPES
|
||||
|
||||
====================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float u, v;
|
||||
float s, t;
|
||||
float zi;
|
||||
} emitpoint_t;
|
||||
|
||||
/*
|
||||
** if you change this structure be sure to change the #defines
|
||||
** listed after it!
|
||||
*/
|
||||
#define SMALL_FINALVERT 0
|
||||
|
||||
#if SMALL_FINALVERT
|
||||
|
||||
typedef struct finalvert_s {
|
||||
short u, v, s, t;
|
||||
int l;
|
||||
int zi;
|
||||
int flags;
|
||||
float xyz[3]; // eye space
|
||||
} finalvert_t;
|
||||
|
||||
#define FINALVERT_V0 0
|
||||
#define FINALVERT_V1 2
|
||||
#define FINALVERT_V2 4
|
||||
#define FINALVERT_V3 6
|
||||
#define FINALVERT_V4 8
|
||||
#define FINALVERT_V5 12
|
||||
#define FINALVERT_FLAGS 16
|
||||
#define FINALVERT_X 20
|
||||
#define FINALVERT_Y 24
|
||||
#define FINALVERT_Z 28
|
||||
#define FINALVERT_SIZE 32
|
||||
|
||||
#else
|
||||
|
||||
typedef struct finalvert_s {
|
||||
int u, v, s, t;
|
||||
int l;
|
||||
int zi;
|
||||
int flags;
|
||||
float xyz[3]; // eye space
|
||||
} finalvert_t;
|
||||
|
||||
#define FINALVERT_V0 0
|
||||
#define FINALVERT_V1 4
|
||||
#define FINALVERT_V2 8
|
||||
#define FINALVERT_V3 12
|
||||
#define FINALVERT_V4 16
|
||||
#define FINALVERT_V5 20
|
||||
#define FINALVERT_FLAGS 24
|
||||
#define FINALVERT_X 28
|
||||
#define FINALVERT_Y 32
|
||||
#define FINALVERT_Z 36
|
||||
#define FINALVERT_SIZE 40
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *pskin;
|
||||
int pskindesc;
|
||||
int skinwidth;
|
||||
int skinheight;
|
||||
dtriangle_t *ptriangles;
|
||||
finalvert_t *pfinalverts;
|
||||
int numtriangles;
|
||||
int drawtype;
|
||||
int seamfixupX16;
|
||||
qboolean do_vis_thresh;
|
||||
int vis_thresh;
|
||||
} affinetridesc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte *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
|
||||
image_t *image;
|
||||
int surfmip; // mipmapped ratio of surface texels / world pixels
|
||||
int surfwidth; // in mipmapped texels
|
||||
int surfheight; // in mipmapped texels
|
||||
} drawsurf_t;
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
// !!! 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;
|
||||
byte leftedge;
|
||||
byte rightedge;
|
||||
byte reserved[2];
|
||||
} clipplane_t;
|
||||
|
||||
|
||||
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;
|
||||
image_t *image;
|
||||
byte data[4]; // width*height elements
|
||||
} surfcache_t;
|
||||
|
||||
// !!! 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;
|
||||
|
||||
// used by the polygon drawer (R_POLY.C) and sprite setup code (R_SPRITE.C)
|
||||
typedef struct
|
||||
{
|
||||
int nump;
|
||||
emitpoint_t *pverts;
|
||||
byte *pixels; // image
|
||||
int pixel_width; // image width
|
||||
int pixel_height; // image height
|
||||
vec3_t vup, vright, vpn; // in worldspace, for plane eq
|
||||
float dist;
|
||||
float s_offset, t_offset;
|
||||
float viewer_position[3];
|
||||
void (*drawspanlet)( void );
|
||||
int stipple_parity;
|
||||
} polydesc_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
|
||||
msurface_t *msurf;
|
||||
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;
|
||||
|
||||
// !!! 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;
|
||||
|
||||
|
||||
/*
|
||||
====================================================
|
||||
|
||||
VARS
|
||||
|
||||
====================================================
|
||||
*/
|
||||
|
||||
extern int d_spanpixcount;
|
||||
extern int r_framecount; // sequence # of current frame since Quake
|
||||
// started
|
||||
extern float r_aliasuvscale; // scale-up factor for screen u and v
|
||||
// on Alias vertices passed to driver
|
||||
extern qboolean r_dowarp;
|
||||
|
||||
extern affinetridesc_t r_affinetridesc;
|
||||
|
||||
extern vec3_t r_pright, r_pup, r_ppn;
|
||||
|
||||
void D_DrawSurfaces (void);
|
||||
void R_DrawParticle( void );
|
||||
void D_ViewChanged (void);
|
||||
void D_WarpScreen (void);
|
||||
void R_PolysetUpdateTables (void);
|
||||
|
||||
extern void *acolormap; // FIXME: should go away
|
||||
|
||||
//=======================================================================//
|
||||
|
||||
// callbacks to Quake
|
||||
|
||||
extern drawsurf_t r_drawsurf;
|
||||
|
||||
void R_DrawSurface (void);
|
||||
|
||||
extern int c_surf;
|
||||
|
||||
extern byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT];
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
extern fixed16_t sadjust, tadjust;
|
||||
extern fixed16_t bbextents, bbextentt;
|
||||
|
||||
|
||||
void D_DrawSpans16 (espan_t *pspans);
|
||||
void D_DrawZSpans (espan_t *pspans);
|
||||
void Turbulent8 (espan_t *pspan);
|
||||
void NonTurbulent8 (espan_t *pspan); //PGM
|
||||
|
||||
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
|
||||
|
||||
extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
|
||||
|
||||
extern int d_pix_min, d_pix_max, d_pix_shift;
|
||||
|
||||
extern pixel_t *d_viewbuffer;
|
||||
extern short *d_pzbuffer;
|
||||
extern unsigned int d_zrowbytes, d_zwidth;
|
||||
extern short *zspantable[MAXHEIGHT];
|
||||
extern int d_scantable[MAXHEIGHT];
|
||||
|
||||
extern int d_minmip;
|
||||
extern float d_scalemip[3];
|
||||
|
||||
//===================================================================
|
||||
|
||||
extern int cachewidth;
|
||||
extern pixel_t *cacheblock;
|
||||
extern int r_screenwidth;
|
||||
|
||||
extern int r_drawnpolycount;
|
||||
|
||||
extern int sintable[1280];
|
||||
extern int intsintable[1280];
|
||||
extern int blanktable[1280]; // PGM
|
||||
|
||||
extern vec3_t vup, base_vup;
|
||||
extern vec3_t vpn, base_vpn;
|
||||
extern vec3_t vright, base_vright;
|
||||
|
||||
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 float xcenter, ycenter;
|
||||
extern float xscale, yscale;
|
||||
extern float xscaleinv, yscaleinv;
|
||||
extern float xscaleshrink, yscaleshrink;
|
||||
|
||||
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 ubasestep, errorterm, erroradjustup, erroradjustdown;
|
||||
|
||||
//===========================================================================
|
||||
|
||||
extern cvar_t *sw_aliasstats;
|
||||
extern cvar_t *sw_clearcolor;
|
||||
extern cvar_t *sw_drawflat;
|
||||
extern cvar_t *sw_draworder;
|
||||
extern cvar_t *sw_maxedges;
|
||||
extern cvar_t *sw_maxsurfs;
|
||||
extern cvar_t *sw_mipcap;
|
||||
extern cvar_t *sw_mipscale;
|
||||
extern cvar_t *sw_mode;
|
||||
extern cvar_t *sw_reportsurfout;
|
||||
extern cvar_t *sw_reportedgeout;
|
||||
extern cvar_t *sw_stipplealpha;
|
||||
extern cvar_t *sw_surfcacheoverride;
|
||||
extern cvar_t *sw_waterwarp;
|
||||
|
||||
extern cvar_t *r_fullbright;
|
||||
extern cvar_t *r_lefthand;
|
||||
extern cvar_t *r_drawentities;
|
||||
extern cvar_t *r_drawworld;
|
||||
extern cvar_t *r_dspeeds;
|
||||
extern cvar_t *r_lerpmodels;
|
||||
|
||||
extern cvar_t *r_speeds;
|
||||
|
||||
extern cvar_t *r_lightlevel; //FIXME HACK
|
||||
|
||||
extern cvar_t *vid_fullscreen;
|
||||
extern cvar_t *vid_gamma;
|
||||
|
||||
|
||||
extern clipplane_t view_clipplanes[4];
|
||||
extern int *pfrustum_indexes[4];
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void R_RenderWorld (void);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
extern mplane_t screenedge[4];
|
||||
|
||||
extern vec3_t r_origin;
|
||||
|
||||
extern entity_t r_worldentity;
|
||||
extern model_t *currentmodel;
|
||||
extern entity_t *currententity;
|
||||
extern vec3_t modelorg;
|
||||
extern vec3_t r_entorigin;
|
||||
|
||||
extern float verticalFieldOfView;
|
||||
extern float xOrigin, yOrigin;
|
||||
|
||||
extern int r_visframecount;
|
||||
|
||||
extern msurface_t *r_alpha_surfaces;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void R_ClearPolyList (void);
|
||||
void R_DrawPolyList (void);
|
||||
|
||||
//
|
||||
// current entity info
|
||||
//
|
||||
extern qboolean insubmodel;
|
||||
|
||||
void R_DrawAlphaSurfaces( void );
|
||||
|
||||
void R_DrawSprite (void);
|
||||
void R_DrawBeam( entity_t *e );
|
||||
|
||||
void R_RenderFace (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_DrawSurfaceBlock16 (void);
|
||||
void R_DrawSurfaceBlock8 (void);
|
||||
|
||||
#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, mnode_t *topnode);
|
||||
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode);
|
||||
|
||||
void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
|
||||
surf_t *R_GetSurf (void);
|
||||
void R_AliasDrawModel (void);
|
||||
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);
|
||||
void R_PushDlights (model_t *model);
|
||||
|
||||
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 int ubasestep, errorterm, erroradjustup, erroradjustdown;
|
||||
|
||||
extern fixed16_t sadjust, tadjust;
|
||||
extern fixed16_t bbextents, bbextentt;
|
||||
|
||||
extern mvertex_t *r_ptverts, *r_ptvertsmax;
|
||||
|
||||
extern float entity_rotation[3][3];
|
||||
|
||||
extern int r_currentkey;
|
||||
extern int r_currentbkey;
|
||||
|
||||
void R_InitTurb (void);
|
||||
|
||||
void R_DrawParticles (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];
|
||||
|
||||
// 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_aliasblendcolor;
|
||||
|
||||
extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
|
||||
|
||||
extern int r_outofsurfaces;
|
||||
extern int r_outofedges;
|
||||
|
||||
extern mvertex_t *r_pcurrentvertbase;
|
||||
extern int r_maxvalidedgeoffset;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
finalvert_t *a, *b, *c;
|
||||
} aliastriangleparms_t;
|
||||
|
||||
extern aliastriangleparms_t aliastriangleparms;
|
||||
|
||||
void R_DrawTriangle( void );
|
||||
//void R_DrawTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2);
|
||||
void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2);
|
||||
|
||||
|
||||
extern float r_time1;
|
||||
extern float da_time1, da_time2;
|
||||
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 mleaf_t *r_viewleaf;
|
||||
extern int r_viewcluster, r_oldviewcluster;
|
||||
|
||||
extern int r_clipflags;
|
||||
extern int r_dlightframecount;
|
||||
extern qboolean r_fov_greater_than_90;
|
||||
|
||||
extern image_t *r_notexture_mip;
|
||||
extern model_t *r_worldmodel;
|
||||
|
||||
void R_PrintAliasStats (void);
|
||||
void R_PrintTimes (void);
|
||||
void R_PrintDSpeeds (void);
|
||||
void R_AnimateLight (void);
|
||||
void R_LightPoint (vec3_t p, vec3_t color);
|
||||
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_SplitEntityOnNode2 (mnode_t *node);
|
||||
|
||||
extern refdef_t r_newrefdef;
|
||||
|
||||
extern surfcache_t *sc_rover, *sc_base;
|
||||
|
||||
extern void *colormap;
|
||||
|
||||
//====================================================================
|
||||
|
||||
float R_DLightPoint (vec3_t p);
|
||||
|
||||
void R_NewMap (void);
|
||||
void R_Register (void);
|
||||
void R_UnRegister (void);
|
||||
void Draw_InitLocal (void);
|
||||
qboolean R_Init( void *hInstance, void *wndProc );
|
||||
void R_Shutdown (void);
|
||||
void R_InitCaches (void);
|
||||
void D_FlushCaches (void);
|
||||
|
||||
void R_ScreenShot_f( void );
|
||||
void R_BeginRegistration (char *map);
|
||||
struct model_s *R_RegisterModel (char *name);
|
||||
void R_EndRegistration (void);
|
||||
|
||||
void R_RenderFrame (refdef_t *fd);
|
||||
|
||||
struct image_s *Draw_FindPic (char *name);
|
||||
|
||||
void Draw_GetPicSize (int *w, int *h, char *name);
|
||||
void Draw_Pic (int x, int y, char *name);
|
||||
void Draw_StretchPic (int x, int y, int w, int h, char *name);
|
||||
void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data);
|
||||
void Draw_Char (int x, int y, int c);
|
||||
void Draw_TileClear (int x, int y, int w, int h, char *name);
|
||||
void Draw_Fill (int x, int y, int w, int h, int c);
|
||||
void Draw_FadeScreen (void);
|
||||
|
||||
void Draw_GetPalette (void);
|
||||
|
||||
void R_BeginFrame( float camera_separation );
|
||||
|
||||
void R_CinematicSetPalette( const unsigned char *palette );
|
||||
|
||||
extern unsigned d_8to24table[256]; // base
|
||||
|
||||
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length);
|
||||
void Sys_SetFPCW (void);
|
||||
|
||||
void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height);
|
||||
|
||||
void R_InitImages (void);
|
||||
void R_ShutdownImages (void);
|
||||
image_t *R_FindImage (char *name, imagetype_t type);
|
||||
void R_FreeUnusedImages (void);
|
||||
|
||||
void R_GammaCorrectAndSetPalette( const unsigned char *pal );
|
||||
|
||||
extern mtexinfo_t *sky_texinfo[6];
|
||||
|
||||
void R_InitSkyBox (void);
|
||||
|
||||
typedef struct swstate_s
|
||||
{
|
||||
qboolean fullscreen;
|
||||
int prev_mode; // last valid SW mode
|
||||
|
||||
byte gammatable[256];
|
||||
byte currentpalette[1024];
|
||||
|
||||
} swstate_t;
|
||||
|
||||
void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha );
|
||||
|
||||
extern swstate_t sw_state;
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
||||
IMPORTED FUNCTIONS
|
||||
|
||||
====================================================================
|
||||
*/
|
||||
|
||||
extern refimport_t ri;
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
||||
IMPLEMENTATION FUNCTIONS
|
||||
|
||||
====================================================================
|
||||
*/
|
||||
|
||||
void SWimp_BeginFrame( float camera_separation );
|
||||
void SWimp_EndFrame (void);
|
||||
int SWimp_Init( void *hInstance, void *wndProc );
|
||||
void SWimp_SetPalette( const unsigned char *palette);
|
||||
void SWimp_Shutdown( void );
|
||||
rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen );
|
||||
void SWimp_AppActivate( qboolean active );
|
||||
|
||||
1422
ref_soft/r_main.c
Normal file
1422
ref_soft/r_main.c
Normal file
File diff suppressed because it is too large
Load Diff
670
ref_soft/r_misc.c
Normal file
670
ref_soft/r_misc.c
Normal file
@@ -0,0 +1,670 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// r_misc.c
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
#define NUM_MIPS 4
|
||||
|
||||
cvar_t *sw_mipcap;
|
||||
cvar_t *sw_mipscale;
|
||||
|
||||
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;
|
||||
|
||||
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
|
||||
|
||||
int d_pix_min, d_pix_max, d_pix_shift;
|
||||
|
||||
int d_scantable[MAXHEIGHT];
|
||||
short *zspantable[MAXHEIGHT];
|
||||
|
||||
/*
|
||||
================
|
||||
D_Patch
|
||||
================
|
||||
*/
|
||||
void D_Patch (void)
|
||||
{
|
||||
#if id386
|
||||
extern void D_Aff8Patch( void );
|
||||
static qboolean protectset8 = false;
|
||||
extern void D_PolysetAff8Start( void );
|
||||
|
||||
if (!protectset8)
|
||||
{
|
||||
Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
|
||||
(int)D_Aff8Patch - (int)D_PolysetAff8Start);
|
||||
Sys_MakeCodeWriteable ((long)R_Surf8Start,
|
||||
(long)R_Surf8End - (long)R_Surf8Start);
|
||||
protectset8 = true;
|
||||
}
|
||||
colormap = vid.colormap;
|
||||
|
||||
R_Surf8Patch ();
|
||||
D_Aff8Patch();
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
================
|
||||
D_ViewChanged
|
||||
================
|
||||
*/
|
||||
unsigned char *alias_colormap;
|
||||
|
||||
void D_ViewChanged (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
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_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
|
||||
if (d_pix_max < 1)
|
||||
d_pix_max = 1;
|
||||
|
||||
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;
|
||||
|
||||
for (i=0 ; i<vid.height; i++)
|
||||
{
|
||||
d_scantable[i] = i*r_screenwidth;
|
||||
zspantable[i] = d_pzbuffer + i*d_zwidth;
|
||||
}
|
||||
|
||||
/*
|
||||
** clear Z-buffer and color-buffers if we're doing the gallery
|
||||
*/
|
||||
if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
|
||||
{
|
||||
memset( d_pzbuffer, 0xff, vid.width * vid.height * sizeof( d_pzbuffer[0] ) );
|
||||
Draw_Fill( r_newrefdef.x, r_newrefdef.y, r_newrefdef.width, r_newrefdef.height,( int ) sw_clearcolor->value & 0xff );
|
||||
}
|
||||
|
||||
alias_colormap = vid.colormap;
|
||||
|
||||
D_Patch ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PrintTimes
|
||||
=============
|
||||
*/
|
||||
void R_PrintTimes (void)
|
||||
{
|
||||
int r_time2;
|
||||
int ms;
|
||||
|
||||
r_time2 = Sys_Milliseconds ();
|
||||
|
||||
ms = r_time2 - r_time1;
|
||||
|
||||
ri.Con_Printf (PRINT_ALL,"%5i 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)
|
||||
{
|
||||
int ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, da_time;
|
||||
|
||||
r_time2 = Sys_Milliseconds ();
|
||||
|
||||
da_time = (da_time2 - da_time1);
|
||||
dp_time = (dp_time2 - dp_time1);
|
||||
rw_time = (rw_time2 - rw_time1);
|
||||
db_time = (db_time2 - db_time1);
|
||||
se_time = (se_time2 - se_time1);
|
||||
de_time = (de_time2 - de_time1);
|
||||
ms = (r_time2 - r_time1);
|
||||
|
||||
ri.Con_Printf (PRINT_ALL,"%3i %2ip %2iw %2ib %2is %2ie %2ia\n",
|
||||
ms, dp_time, rw_time, db_time, se_time, de_time, da_time);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PrintAliasStats
|
||||
=============
|
||||
*/
|
||||
void R_PrintAliasStats (void)
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL,"%3i polygon model drawn\n", r_amodels_drawn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
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 !(defined __linux__ && defined __i386__)
|
||||
#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);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
__declspec( naked ) void TransformVector( vec3_t vin, vec3_t vout )
|
||||
{
|
||||
__asm mov eax, dword ptr [esp+4]
|
||||
__asm mov edx, dword ptr [esp+8]
|
||||
|
||||
__asm fld dword ptr [eax+0]
|
||||
__asm fmul dword ptr [vright+0]
|
||||
__asm fld dword ptr [eax+0]
|
||||
__asm fmul dword ptr [vup+0]
|
||||
__asm fld dword ptr [eax+0]
|
||||
__asm fmul dword ptr [vpn+0]
|
||||
|
||||
__asm fld dword ptr [eax+4]
|
||||
__asm fmul dword ptr [vright+4]
|
||||
__asm fld dword ptr [eax+4]
|
||||
__asm fmul dword ptr [vup+4]
|
||||
__asm fld dword ptr [eax+4]
|
||||
__asm fmul dword ptr [vpn+4]
|
||||
|
||||
__asm fxch st(2)
|
||||
|
||||
__asm faddp st(5), st(0)
|
||||
__asm faddp st(3), st(0)
|
||||
__asm faddp st(1), st(0)
|
||||
|
||||
__asm fld dword ptr [eax+8]
|
||||
__asm fmul dword ptr [vright+8]
|
||||
__asm fld dword ptr [eax+8]
|
||||
__asm fmul dword ptr [vup+8]
|
||||
__asm fld dword ptr [eax+8]
|
||||
__asm fmul dword ptr [vpn+8]
|
||||
|
||||
__asm fxch st(2)
|
||||
|
||||
__asm faddp st(5), st(0)
|
||||
__asm faddp st(3), st(0)
|
||||
__asm faddp st(1), st(0)
|
||||
|
||||
__asm fstp dword ptr [edx+8]
|
||||
__asm fstp dword ptr [edx+4]
|
||||
__asm fstp dword ptr [edx+0]
|
||||
|
||||
__asm ret
|
||||
}
|
||||
|
||||
#endif
|
||||
#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_ViewChanged
|
||||
|
||||
Called every time the vid structure or r_refdef changes.
|
||||
Guaranteed to be called before the first refresh
|
||||
===============
|
||||
*/
|
||||
void R_ViewChanged (vrect_t *vr)
|
||||
{
|
||||
int i;
|
||||
|
||||
r_refdef.vrect = *vr;
|
||||
|
||||
r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);;
|
||||
verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI);
|
||||
|
||||
r_refdef.fvrectx = (float)r_refdef.vrect.x;
|
||||
r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
|
||||
r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
|
||||
r_refdef.fvrecty = (float)r_refdef.vrect.y;
|
||||
r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
|
||||
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
|
||||
r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
|
||||
r_refdef.fvrectright = (float)r_refdef.vrectright;
|
||||
r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
|
||||
r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
|
||||
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
|
||||
r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
|
||||
r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;
|
||||
|
||||
r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
|
||||
r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
|
||||
r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
|
||||
r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
|
||||
r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
|
||||
r_refdef.aliasvrect.width;
|
||||
r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
|
||||
r_refdef.aliasvrect.height;
|
||||
|
||||
xOrigin = r_refdef.xOrigin;
|
||||
yOrigin = r_refdef.yOrigin;
|
||||
|
||||
// values for perspective projection
|
||||
// if math were exact, the values would range from 0.5 to to range+0.5
|
||||
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
|
||||
// the polygon rasterization will never render in the first row or column
|
||||
// but will definately render in the [range] row and column, so adjust the
|
||||
// buffer origin to get an exact edge to edge fill
|
||||
xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
|
||||
r_refdef.vrect.x - 0.5;
|
||||
aliasxcenter = xcenter * r_aliasuvscale;
|
||||
ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
|
||||
r_refdef.vrect.y - 0.5;
|
||||
aliasycenter = ycenter * r_aliasuvscale;
|
||||
|
||||
xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
|
||||
aliasxscale = xscale * r_aliasuvscale;
|
||||
xscaleinv = 1.0 / xscale;
|
||||
|
||||
yscale = xscale;
|
||||
aliasyscale = yscale * r_aliasuvscale;
|
||||
yscaleinv = 1.0 / yscale;
|
||||
xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
|
||||
yscaleshrink = xscaleshrink;
|
||||
|
||||
// left side clip
|
||||
screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
|
||||
screenedge[0].normal[1] = 0;
|
||||
screenedge[0].normal[2] = 1;
|
||||
screenedge[0].type = PLANE_ANYZ;
|
||||
|
||||
// right side clip
|
||||
screenedge[1].normal[0] =
|
||||
1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
|
||||
screenedge[1].normal[1] = 0;
|
||||
screenedge[1].normal[2] = 1;
|
||||
screenedge[1].type = PLANE_ANYZ;
|
||||
|
||||
// top side clip
|
||||
screenedge[2].normal[0] = 0;
|
||||
screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
|
||||
screenedge[2].normal[2] = 1;
|
||||
screenedge[2].type = PLANE_ANYZ;
|
||||
|
||||
// bottom side clip
|
||||
screenedge[3].normal[0] = 0;
|
||||
screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
|
||||
screenedge[3].normal[2] = 1;
|
||||
screenedge[3].type = PLANE_ANYZ;
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
VectorNormalize (screenedge[i].normal);
|
||||
|
||||
D_ViewChanged ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SetupFrame
|
||||
===============
|
||||
*/
|
||||
void R_SetupFrame (void)
|
||||
{
|
||||
int i;
|
||||
vrect_t vrect;
|
||||
|
||||
if (r_fullbright->modified)
|
||||
{
|
||||
r_fullbright->modified = false;
|
||||
D_FlushCaches (); // so all lighting changes
|
||||
}
|
||||
|
||||
r_framecount++;
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
// current viewleaf
|
||||
if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
|
||||
{
|
||||
r_viewleaf = Mod_PointInLeaf (r_origin, r_worldmodel);
|
||||
r_viewcluster = r_viewleaf->cluster;
|
||||
}
|
||||
|
||||
if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) )
|
||||
r_dowarp = true;
|
||||
else
|
||||
r_dowarp = false;
|
||||
|
||||
if (r_dowarp)
|
||||
{ // warp into off screen buffer
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH;
|
||||
vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT;
|
||||
|
||||
d_viewbuffer = r_warpbuffer;
|
||||
r_screenwidth = WARP_WIDTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
vrect.x = r_newrefdef.x;
|
||||
vrect.y = r_newrefdef.y;
|
||||
vrect.width = r_newrefdef.width;
|
||||
vrect.height = r_newrefdef.height;
|
||||
|
||||
d_viewbuffer = (void *)vid.buffer;
|
||||
r_screenwidth = vid.rowbytes;
|
||||
}
|
||||
|
||||
R_ViewChanged (&vrect);
|
||||
|
||||
// start off with just the four screen edge clip planes
|
||||
R_TransformFrustum ();
|
||||
R_SetUpFrustumIndexes ();
|
||||
|
||||
// save base values
|
||||
VectorCopy (vpn, base_vpn);
|
||||
VectorCopy (vright, base_vright);
|
||||
VectorCopy (vup, base_vup);
|
||||
|
||||
// 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_setup
|
||||
d_roverwrapped = false;
|
||||
d_initial_rover = sc_rover;
|
||||
|
||||
d_minmip = sw_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] * sw_mipscale->value;
|
||||
|
||||
d_aflatcolor = 0;
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
================
|
||||
R_SurfacePatch
|
||||
================
|
||||
*/
|
||||
void R_SurfacePatch (void)
|
||||
{
|
||||
// we only patch code on Intel
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SCREEN SHOTS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
WritePCXfile
|
||||
==============
|
||||
*/
|
||||
void WritePCXfile (char *filename, byte *data, int width, int height,
|
||||
int rowbytes, byte *palette)
|
||||
{
|
||||
int i, j, length;
|
||||
pcx_t *pcx;
|
||||
byte *pack;
|
||||
FILE *f;
|
||||
|
||||
pcx = (pcx_t *)malloc (width*height*2+1000);
|
||||
if (!pcx)
|
||||
return;
|
||||
|
||||
pcx->manufacturer = 0x0a; // PCX id
|
||||
pcx->version = 5; // 256 color
|
||||
pcx->encoding = 1; // uncompressed
|
||||
pcx->bits_per_pixel = 8; // 256 color
|
||||
pcx->xmin = 0;
|
||||
pcx->ymin = 0;
|
||||
pcx->xmax = LittleShort((short)(width-1));
|
||||
pcx->ymax = LittleShort((short)(height-1));
|
||||
pcx->hres = LittleShort((short)width);
|
||||
pcx->vres = LittleShort((short)height);
|
||||
memset (pcx->palette,0,sizeof(pcx->palette));
|
||||
pcx->color_planes = 1; // chunky image
|
||||
pcx->bytes_per_line = LittleShort((short)width);
|
||||
pcx->palette_type = LittleShort(2); // not a grey scale
|
||||
memset (pcx->filler,0,sizeof(pcx->filler));
|
||||
|
||||
// pack the image
|
||||
pack = &pcx->data;
|
||||
|
||||
for (i=0 ; i<height ; i++)
|
||||
{
|
||||
for (j=0 ; j<width ; j++)
|
||||
{
|
||||
if ( (*data & 0xc0) != 0xc0)
|
||||
*pack++ = *data++;
|
||||
else
|
||||
{
|
||||
*pack++ = 0xc1;
|
||||
*pack++ = *data++;
|
||||
}
|
||||
}
|
||||
|
||||
data += rowbytes - width;
|
||||
}
|
||||
|
||||
// write the palette
|
||||
*pack++ = 0x0c; // palette ID byte
|
||||
for (i=0 ; i<768 ; i++)
|
||||
*pack++ = *palette++;
|
||||
|
||||
// write output file
|
||||
length = pack - (byte *)pcx;
|
||||
f = fopen (filename, "wb");
|
||||
if (!f)
|
||||
ri.Con_Printf (PRINT_ALL, "Failed to open to %s\n", filename);
|
||||
else
|
||||
{
|
||||
fwrite ((void *)pcx, 1, length, f);
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
free (pcx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
R_ScreenShot_f
|
||||
==================
|
||||
*/
|
||||
void R_ScreenShot_f (void)
|
||||
{
|
||||
int i;
|
||||
char pcxname[80];
|
||||
char checkname[MAX_OSPATH];
|
||||
FILE *f;
|
||||
byte palette[768];
|
||||
|
||||
// create the scrnshots directory if it doesn't exist
|
||||
Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir());
|
||||
Sys_Mkdir (checkname);
|
||||
|
||||
//
|
||||
// find a file name to save it to
|
||||
//
|
||||
strcpy(pcxname,"quake00.pcx");
|
||||
|
||||
for (i=0 ; i<=99 ; i++)
|
||||
{
|
||||
pcxname[5] = i/10 + '0';
|
||||
pcxname[6] = i%10 + '0';
|
||||
Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), pcxname);
|
||||
f = fopen (checkname, "r");
|
||||
if (!f)
|
||||
break; // file doesn't exist
|
||||
fclose (f);
|
||||
}
|
||||
if (i==100)
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "R_ScreenShot_f: Couldn't create a PCX");
|
||||
return;
|
||||
}
|
||||
|
||||
// turn the current 32 bit palette into a 24 bit palette
|
||||
for (i=0 ; i<256 ; i++)
|
||||
{
|
||||
palette[i*3+0] = sw_state.currentpalette[i*4+0];
|
||||
palette[i*3+1] = sw_state.currentpalette[i*4+1];
|
||||
palette[i*3+2] = sw_state.currentpalette[i*4+2];
|
||||
}
|
||||
|
||||
//
|
||||
// save the pcx file
|
||||
//
|
||||
|
||||
WritePCXfile (checkname, vid.buffer, vid.width, vid.height, vid.rowbytes,
|
||||
palette);
|
||||
|
||||
ri.Con_Printf (PRINT_ALL, "Wrote %s\n", checkname);
|
||||
}
|
||||
|
||||
1241
ref_soft/r_model.c
Normal file
1241
ref_soft/r_model.c
Normal file
File diff suppressed because it is too large
Load Diff
256
ref_soft/r_model.h
Normal file
256
ref_soft/r_model.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __MODEL__
|
||||
#define __MODEL__
|
||||
|
||||
/*
|
||||
|
||||
d*_t structures are on-disk representations
|
||||
m*_t structures are in-memory
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
BRUSH MODELS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// in memory representation
|
||||
//
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct
|
||||
{
|
||||
vec3_t position;
|
||||
} mvertex_t;
|
||||
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
|
||||
|
||||
// plane_t structure
|
||||
// !!! if this is changed, it must be changed in asm_i386.h too !!!
|
||||
typedef struct mplane_s
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
byte type; // for texture axis selection and fast side tests
|
||||
byte signbits; // signx + signy<<1 + signz<<1
|
||||
byte pad[2];
|
||||
} mplane_t;
|
||||
|
||||
|
||||
// FIXME: differentiate from texinfo SURF_ flags
|
||||
#define SURF_PLANEBACK 2
|
||||
#define SURF_DRAWSKY 4 // sky brush face
|
||||
#define SURF_DRAWTURB 0x10
|
||||
#define SURF_DRAWBACKGROUND 0x40
|
||||
#define SURF_DRAWSKYBOX 0x80 // sky box
|
||||
|
||||
#define SURF_FLOW 0x100 //PGM
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct
|
||||
{
|
||||
unsigned short v[2];
|
||||
unsigned int cachededgeoffset;
|
||||
} medge_t;
|
||||
|
||||
typedef struct mtexinfo_s
|
||||
{
|
||||
float vecs[2][4];
|
||||
float mipadjust;
|
||||
image_t *image;
|
||||
int flags;
|
||||
int numframes;
|
||||
struct mtexinfo_s *next; // animation chain
|
||||
} mtexinfo_t;
|
||||
|
||||
typedef struct msurface_s
|
||||
{
|
||||
int visframe; // should be drawn when node is crossed
|
||||
|
||||
int dlightframe;
|
||||
int dlightbits;
|
||||
|
||||
mplane_t *plane;
|
||||
int flags;
|
||||
|
||||
int firstedge; // look up in model->surfedges[], negative numbers
|
||||
int numedges; // are backwards edges
|
||||
|
||||
// surface generation data
|
||||
struct surfcache_s *cachespots[MIPLEVELS];
|
||||
|
||||
short texturemins[2];
|
||||
short extents[2];
|
||||
|
||||
mtexinfo_t *texinfo;
|
||||
|
||||
// lighting info
|
||||
byte styles[MAXLIGHTMAPS];
|
||||
byte *samples; // [numstyles*surfsize]
|
||||
|
||||
struct msurface_s *nextalphasurface;
|
||||
} msurface_t;
|
||||
|
||||
|
||||
#define CONTENTS_NODE -1
|
||||
typedef struct mnode_s
|
||||
{
|
||||
// common with leaf
|
||||
int contents; // CONTENTS_NODE, to differentiate from leafs
|
||||
int visframe; // node needs to be traversed if current
|
||||
|
||||
short minmaxs[6]; // for bounding box culling
|
||||
|
||||
struct mnode_s *parent;
|
||||
|
||||
// node specific
|
||||
mplane_t *plane;
|
||||
struct mnode_s *children[2];
|
||||
|
||||
unsigned short firstsurface;
|
||||
unsigned short numsurfaces;
|
||||
} mnode_t;
|
||||
|
||||
|
||||
|
||||
typedef struct mleaf_s
|
||||
{
|
||||
// common with node
|
||||
int contents; // wil be something other than CONTENTS_NODE
|
||||
int visframe; // node needs to be traversed if current
|
||||
|
||||
short minmaxs[6]; // for bounding box culling
|
||||
|
||||
struct mnode_s *parent;
|
||||
|
||||
// leaf specific
|
||||
int cluster;
|
||||
int area;
|
||||
|
||||
msurface_t **firstmarksurface;
|
||||
int nummarksurfaces;
|
||||
int key; // BSP sequence number for leaf's contents
|
||||
} mleaf_t;
|
||||
|
||||
|
||||
//===================================================================
|
||||
|
||||
//
|
||||
// Whole model
|
||||
//
|
||||
|
||||
typedef enum {mod_bad, mod_brush, mod_sprite, mod_alias } modtype_t;
|
||||
|
||||
typedef struct model_s
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
|
||||
int registration_sequence;
|
||||
|
||||
modtype_t type;
|
||||
int numframes;
|
||||
|
||||
int flags;
|
||||
|
||||
//
|
||||
// volume occupied by the model graphics
|
||||
//
|
||||
vec3_t mins, maxs;
|
||||
|
||||
//
|
||||
// solid volume for clipping (sent from server)
|
||||
//
|
||||
qboolean clipbox;
|
||||
vec3_t clipmins, clipmaxs;
|
||||
|
||||
//
|
||||
// brush model
|
||||
//
|
||||
int firstmodelsurface, nummodelsurfaces;
|
||||
|
||||
int numsubmodels;
|
||||
dmodel_t *submodels;
|
||||
|
||||
int numplanes;
|
||||
mplane_t *planes;
|
||||
|
||||
int numleafs; // number of visible leafs, not counting 0
|
||||
mleaf_t *leafs;
|
||||
|
||||
int numvertexes;
|
||||
mvertex_t *vertexes;
|
||||
|
||||
int numedges;
|
||||
medge_t *edges;
|
||||
|
||||
int numnodes;
|
||||
int firstnode;
|
||||
mnode_t *nodes;
|
||||
|
||||
int numtexinfo;
|
||||
mtexinfo_t *texinfo;
|
||||
|
||||
int numsurfaces;
|
||||
msurface_t *surfaces;
|
||||
|
||||
int numsurfedges;
|
||||
int *surfedges;
|
||||
|
||||
int nummarksurfaces;
|
||||
msurface_t **marksurfaces;
|
||||
|
||||
dvis_t *vis;
|
||||
|
||||
byte *lightdata;
|
||||
|
||||
// for alias models and sprites
|
||||
image_t *skins[MAX_MD2SKINS];
|
||||
void *extradata;
|
||||
int extradatasize;
|
||||
} model_t;
|
||||
|
||||
//============================================================================
|
||||
|
||||
void Mod_Init (void);
|
||||
void Mod_ClearAll (void);
|
||||
model_t *Mod_ForName (char *name, qboolean crash);
|
||||
void *Mod_Extradata (model_t *mod); // handles caching
|
||||
void Mod_TouchModel (char *name);
|
||||
|
||||
mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
|
||||
byte *Mod_ClusterPVS (int cluster, model_t *model);
|
||||
|
||||
void Mod_Modellist_f (void);
|
||||
void Mod_FreeAll (void);
|
||||
void Mod_Free (model_t *mod);
|
||||
|
||||
extern int registration_sequence;
|
||||
|
||||
#endif // __MODEL__
|
||||
638
ref_soft/r_part.c
Normal file
638
ref_soft/r_part.c
Normal file
@@ -0,0 +1,638 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
#include "r_local.h"
|
||||
|
||||
vec3_t r_pright, r_pup, r_ppn;
|
||||
|
||||
#define PARTICLE_33 0
|
||||
#define PARTICLE_66 1
|
||||
#define PARTICLE_OPAQUE 2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
particle_t *particle;
|
||||
int level;
|
||||
int color;
|
||||
} partparms_t;
|
||||
|
||||
static partparms_t partparms;
|
||||
|
||||
#if id386 && !defined __linux__
|
||||
|
||||
static unsigned s_prefetch_address;
|
||||
|
||||
/*
|
||||
** BlendParticleXX
|
||||
**
|
||||
** Inputs:
|
||||
** EAX = color
|
||||
** EDI = pdest
|
||||
**
|
||||
** Scratch:
|
||||
** EBX = scratch (dstcolor)
|
||||
** EBP = scratch
|
||||
**
|
||||
** Outputs:
|
||||
** none
|
||||
*/
|
||||
__declspec(naked) void BlendParticle33( void )
|
||||
{
|
||||
// return vid.alphamap[color + dstcolor*256];
|
||||
__asm mov ebp, vid.alphamap
|
||||
__asm xor ebx, ebx
|
||||
|
||||
__asm mov bl, byte ptr [edi]
|
||||
__asm shl ebx, 8
|
||||
|
||||
__asm add ebp, ebx
|
||||
__asm add ebp, eax
|
||||
|
||||
__asm mov al, byte ptr [ebp]
|
||||
|
||||
__asm mov byte ptr [edi], al
|
||||
|
||||
__asm ret
|
||||
}
|
||||
|
||||
__declspec(naked) void BlendParticle66( void )
|
||||
{
|
||||
// return vid.alphamap[pcolor*256 + dstcolor];
|
||||
__asm mov ebp, vid.alphamap
|
||||
__asm xor ebx, ebx
|
||||
|
||||
__asm shl eax, 8
|
||||
__asm mov bl, byte ptr [edi]
|
||||
|
||||
__asm add ebp, ebx
|
||||
__asm add ebp, eax
|
||||
|
||||
__asm mov al, byte ptr [ebp]
|
||||
|
||||
__asm mov byte ptr [edi], al
|
||||
|
||||
__asm ret
|
||||
}
|
||||
|
||||
__declspec(naked) void BlendParticle100( void )
|
||||
{
|
||||
__asm mov byte ptr [edi], al
|
||||
__asm ret
|
||||
}
|
||||
|
||||
/*
|
||||
** R_DrawParticle (asm version)
|
||||
**
|
||||
** Since we use __declspec( naked ) we don't have a stack frame
|
||||
** that we can use. Since I want to reserve EBP anyway, I tossed
|
||||
** all the important variables into statics. This routine isn't
|
||||
** meant to be re-entrant, so this shouldn't cause any problems
|
||||
** other than a slightly higher global memory footprint.
|
||||
**
|
||||
*/
|
||||
__declspec(naked) void R_DrawParticle( void )
|
||||
{
|
||||
static vec3_t local, transformed;
|
||||
static float zi;
|
||||
static int u, v, tmp;
|
||||
static short izi;
|
||||
static int ebpsave;
|
||||
|
||||
static byte (*blendfunc)(void);
|
||||
|
||||
/*
|
||||
** must be memvars since x86 can't load constants
|
||||
** directly. I guess I could use fld1, but that
|
||||
** actually costs one more clock than fld [one]!
|
||||
*/
|
||||
static float particle_z_clip = PARTICLE_Z_CLIP;
|
||||
static float one = 1.0F;
|
||||
static float point_five = 0.5F;
|
||||
static float eight_thousand_hex = 0x8000;
|
||||
|
||||
/*
|
||||
** save trashed variables
|
||||
*/
|
||||
__asm mov ebpsave, ebp
|
||||
__asm push esi
|
||||
__asm push edi
|
||||
|
||||
/*
|
||||
** transform the particle
|
||||
*/
|
||||
// VectorSubtract (pparticle->origin, r_origin, local);
|
||||
__asm mov esi, partparms.particle
|
||||
__asm fld dword ptr [esi+0] ; p_o.x
|
||||
__asm fsub dword ptr [r_origin+0] ; p_o.x-r_o.x
|
||||
__asm fld dword ptr [esi+4] ; p_o.y | p_o.x-r_o.x
|
||||
__asm fsub dword ptr [r_origin+4] ; p_o.y-r_o.y | p_o.x-r_o.x
|
||||
__asm fld dword ptr [esi+8] ; p_o.z | p_o.y-r_o.y | p_o.x-r_o.x
|
||||
__asm fsub dword ptr [r_origin+8] ; p_o.z-r_o.z | p_o.y-r_o.y | p_o.x-r_o.x
|
||||
__asm fxch st(2) ; p_o.x-r_o.x | p_o.y-r_o.y | p_o.z-r_o.z
|
||||
__asm fstp dword ptr [local+0] ; p_o.y-r_o.y | p_o.z-r_o.z
|
||||
__asm fstp dword ptr [local+4] ; p_o.z-r_o.z
|
||||
__asm fstp dword ptr [local+8] ; (empty)
|
||||
|
||||
// transformed[0] = DotProduct(local, r_pright);
|
||||
// transformed[1] = DotProduct(local, r_pup);
|
||||
// transformed[2] = DotProduct(local, r_ppn);
|
||||
__asm fld dword ptr [local+0] ; l.x
|
||||
__asm fmul dword ptr [r_pright+0] ; l.x*pr.x
|
||||
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
|
||||
__asm fmul dword ptr [r_pright+4] ; l.y*pr.y | l.x*pr.x
|
||||
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
|
||||
__asm fmul dword ptr [r_pright+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
|
||||
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
|
||||
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
|
||||
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
|
||||
__asm fstp dword ptr [transformed+0] ; (empty)
|
||||
|
||||
__asm fld dword ptr [local+0] ; l.x
|
||||
__asm fmul dword ptr [r_pup+0] ; l.x*pr.x
|
||||
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
|
||||
__asm fmul dword ptr [r_pup+4] ; l.y*pr.y | l.x*pr.x
|
||||
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
|
||||
__asm fmul dword ptr [r_pup+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
|
||||
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
|
||||
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
|
||||
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
|
||||
__asm fstp dword ptr [transformed+4] ; (empty)
|
||||
|
||||
__asm fld dword ptr [local+0] ; l.x
|
||||
__asm fmul dword ptr [r_ppn+0] ; l.x*pr.x
|
||||
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
|
||||
__asm fmul dword ptr [r_ppn+4] ; l.y*pr.y | l.x*pr.x
|
||||
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
|
||||
__asm fmul dword ptr [r_ppn+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
|
||||
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
|
||||
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
|
||||
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
|
||||
__asm fstp dword ptr [transformed+8] ; (empty)
|
||||
|
||||
/*
|
||||
** make sure that the transformed particle is not in front of
|
||||
** the particle Z clip plane. We can do the comparison in
|
||||
** integer space since we know the sign of one of the inputs
|
||||
** and can figure out the sign of the other easily enough.
|
||||
*/
|
||||
// if (transformed[2] < PARTICLE_Z_CLIP)
|
||||
// return;
|
||||
|
||||
__asm mov eax, dword ptr [transformed+8]
|
||||
__asm and eax, eax
|
||||
__asm js end
|
||||
__asm cmp eax, particle_z_clip
|
||||
__asm jl end
|
||||
|
||||
/*
|
||||
** project the point by initiating the 1/z calc
|
||||
*/
|
||||
// zi = 1.0 / transformed[2];
|
||||
__asm fld one
|
||||
__asm fdiv dword ptr [transformed+8]
|
||||
|
||||
/*
|
||||
** bind the blend function pointer to the appropriate blender
|
||||
** while we're dividing
|
||||
*/
|
||||
//if ( level == PARTICLE_33 )
|
||||
// blendparticle = BlendParticle33;
|
||||
//else if ( level == PARTICLE_66 )
|
||||
// blendparticle = BlendParticle66;
|
||||
//else
|
||||
// blendparticle = BlendParticle100;
|
||||
|
||||
__asm cmp partparms.level, PARTICLE_66
|
||||
__asm je blendfunc_66
|
||||
__asm jl blendfunc_33
|
||||
__asm lea ebx, BlendParticle100
|
||||
__asm jmp done_selecting_blend_func
|
||||
blendfunc_33:
|
||||
__asm lea ebx, BlendParticle33
|
||||
__asm jmp done_selecting_blend_func
|
||||
blendfunc_66:
|
||||
__asm lea ebx, BlendParticle66
|
||||
done_selecting_blend_func:
|
||||
__asm mov blendfunc, ebx
|
||||
|
||||
// prefetch the next particle
|
||||
__asm mov ebp, s_prefetch_address
|
||||
__asm mov ebp, [ebp]
|
||||
|
||||
// finish the above divide
|
||||
__asm fstp zi
|
||||
|
||||
// u = (int)(xcenter + zi * transformed[0] + 0.5);
|
||||
// v = (int)(ycenter - zi * transformed[1] + 0.5);
|
||||
__asm fld zi ; zi
|
||||
__asm fmul dword ptr [transformed+0] ; zi * transformed[0]
|
||||
__asm fld zi ; zi | zi * transformed[0]
|
||||
__asm fmul dword ptr [transformed+4] ; zi * transformed[1] | zi * transformed[0]
|
||||
__asm fxch st(1) ; zi * transformed[0] | zi * transformed[1]
|
||||
__asm fadd xcenter ; xcenter + zi * transformed[0] | zi * transformed[1]
|
||||
__asm fxch st(1) ; zi * transformed[1] | xcenter + zi * transformed[0]
|
||||
__asm fld ycenter ; ycenter | zi * transformed[1] | xcenter + zi * transformed[0]
|
||||
__asm fsubrp st(1), st(0) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0]
|
||||
__asm fxch st(1) ; xcenter + zi * transformed[0] | ycenter + zi * transformed[1]
|
||||
__asm fadd point_five ; xcenter + zi * transformed[0] + 0.5 | ycenter - zi * transformed[1]
|
||||
__asm fxch st(1) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0] + 0.5
|
||||
__asm fadd point_five ; ycenter - zi * transformed[1] + 0.5 | xcenter + zi * transformed[0] + 0.5
|
||||
__asm fxch st(1) ; u | v
|
||||
__asm fistp dword ptr [u] ; v
|
||||
__asm fistp dword ptr [v] ; (empty)
|
||||
|
||||
/*
|
||||
** clip out the particle
|
||||
*/
|
||||
|
||||
// if ((v > d_vrectbottom_particle) ||
|
||||
// (u > d_vrectright_particle) ||
|
||||
// (v < d_vrecty) ||
|
||||
// (u < d_vrectx))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
__asm mov ebx, u
|
||||
__asm mov ecx, v
|
||||
__asm cmp ecx, d_vrectbottom_particle
|
||||
__asm jg end
|
||||
__asm cmp ecx, d_vrecty
|
||||
__asm jl end
|
||||
__asm cmp ebx, d_vrectright_particle
|
||||
__asm jg end
|
||||
__asm cmp ebx, d_vrectx
|
||||
__asm jl end
|
||||
|
||||
/*
|
||||
** compute addresses of zbuffer, framebuffer, and
|
||||
** compute the Z-buffer reference value.
|
||||
**
|
||||
** EBX = U
|
||||
** ECX = V
|
||||
**
|
||||
** Outputs:
|
||||
** ESI = Z-buffer address
|
||||
** EDI = framebuffer address
|
||||
*/
|
||||
// ESI = d_pzbuffer + (d_zwidth * v) + u;
|
||||
__asm mov esi, d_pzbuffer ; esi = d_pzbuffer
|
||||
__asm mov eax, d_zwidth ; eax = d_zwidth
|
||||
__asm mul ecx ; eax = d_zwidth*v
|
||||
__asm add eax, ebx ; eax = d_zwidth*v+u
|
||||
__asm shl eax, 1 ; eax = 2*(d_zwidth*v+u)
|
||||
__asm add esi, eax ; esi = ( short * ) ( d_pzbuffer + ( d_zwidth * v ) + u )
|
||||
|
||||
// initiate
|
||||
// izi = (int)(zi * 0x8000);
|
||||
__asm fld zi
|
||||
__asm fmul eight_thousand_hex
|
||||
|
||||
// EDI = pdest = d_viewbuffer + d_scantable[v] + u;
|
||||
__asm lea edi, [d_scantable+ecx*4]
|
||||
__asm mov edi, [edi]
|
||||
__asm add edi, d_viewbuffer
|
||||
__asm add edi, ebx
|
||||
|
||||
// complete
|
||||
// izi = (int)(zi * 0x8000);
|
||||
__asm fistp tmp
|
||||
__asm mov eax, tmp
|
||||
__asm mov izi, ax
|
||||
|
||||
/*
|
||||
** determine the screen area covered by the particle,
|
||||
** which also means clamping to a min and max
|
||||
*/
|
||||
// pix = izi >> d_pix_shift;
|
||||
__asm xor edx, edx
|
||||
__asm mov dx, izi
|
||||
__asm mov ecx, d_pix_shift
|
||||
__asm shr dx, cl
|
||||
|
||||
// if (pix < d_pix_min)
|
||||
// pix = d_pix_min;
|
||||
__asm cmp edx, d_pix_min
|
||||
__asm jge check_pix_max
|
||||
__asm mov edx, d_pix_min
|
||||
__asm jmp skip_pix_clamp
|
||||
|
||||
// else if (pix > d_pix_max)
|
||||
// pix = d_pix_max;
|
||||
check_pix_max:
|
||||
__asm cmp edx, d_pix_max
|
||||
__asm jle skip_pix_clamp
|
||||
__asm mov edx, d_pix_max
|
||||
|
||||
skip_pix_clamp:
|
||||
|
||||
/*
|
||||
** render the appropriate pixels
|
||||
**
|
||||
** ECX = count (used for inner loop)
|
||||
** EDX = count (used for outer loop)
|
||||
** ESI = zbuffer
|
||||
** EDI = framebuffer
|
||||
*/
|
||||
__asm mov ecx, edx
|
||||
|
||||
__asm cmp ecx, 1
|
||||
__asm ja over
|
||||
|
||||
over:
|
||||
|
||||
/*
|
||||
** at this point:
|
||||
**
|
||||
** ECX = count
|
||||
*/
|
||||
__asm push ecx
|
||||
__asm push edi
|
||||
__asm push esi
|
||||
|
||||
top_of_pix_vert_loop:
|
||||
|
||||
top_of_pix_horiz_loop:
|
||||
|
||||
// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
|
||||
// {
|
||||
// for (i=0 ; i<pix ; i++)
|
||||
// {
|
||||
// if (pz[i] <= izi)
|
||||
// {
|
||||
// pdest[i] = blendparticle( color, pdest[i] );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
__asm xor eax, eax
|
||||
|
||||
__asm mov ax, word ptr [esi]
|
||||
|
||||
__asm cmp ax, izi
|
||||
__asm jg end_of_horiz_loop
|
||||
|
||||
#if ENABLE_ZWRITES_FOR_PARTICLES
|
||||
__asm mov bp, izi
|
||||
__asm mov word ptr [esi], bp
|
||||
#endif
|
||||
|
||||
__asm mov eax, partparms.color
|
||||
|
||||
__asm call [blendfunc]
|
||||
|
||||
__asm add edi, 1
|
||||
__asm add esi, 2
|
||||
|
||||
end_of_horiz_loop:
|
||||
|
||||
__asm dec ecx
|
||||
__asm jnz top_of_pix_horiz_loop
|
||||
|
||||
__asm pop esi
|
||||
__asm pop edi
|
||||
|
||||
__asm mov ebp, d_zwidth
|
||||
__asm shl ebp, 1
|
||||
|
||||
__asm add esi, ebp
|
||||
__asm add edi, [r_screenwidth]
|
||||
|
||||
__asm pop ecx
|
||||
__asm push ecx
|
||||
|
||||
__asm push edi
|
||||
__asm push esi
|
||||
|
||||
__asm dec edx
|
||||
__asm jnz top_of_pix_vert_loop
|
||||
|
||||
__asm pop ecx
|
||||
__asm pop ecx
|
||||
__asm pop ecx
|
||||
|
||||
end:
|
||||
__asm pop edi
|
||||
__asm pop esi
|
||||
__asm mov ebp, ebpsave
|
||||
__asm ret
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static byte BlendParticle33( int pcolor, int dstcolor )
|
||||
{
|
||||
return vid.alphamap[pcolor + dstcolor*256];
|
||||
}
|
||||
|
||||
static byte BlendParticle66( int pcolor, int dstcolor )
|
||||
{
|
||||
return vid.alphamap[pcolor*256+dstcolor];
|
||||
}
|
||||
|
||||
static byte BlendParticle100( int pcolor, int dstcolor )
|
||||
{
|
||||
dstcolor = dstcolor;
|
||||
return pcolor;
|
||||
}
|
||||
|
||||
/*
|
||||
** R_DrawParticle
|
||||
**
|
||||
** Yes, this is amazingly slow, but it's the C reference
|
||||
** implementation and should be both robust and vaguely
|
||||
** understandable. The only time this path should be
|
||||
** executed is if we're debugging on x86 or if we're
|
||||
** recompiling and deploying on a non-x86 platform.
|
||||
**
|
||||
** To minimize error and improve readability I went the
|
||||
** function pointer route. This exacts some overhead, but
|
||||
** it pays off in clean and easy to understand code.
|
||||
*/
|
||||
void R_DrawParticle( void )
|
||||
{
|
||||
particle_t *pparticle = partparms.particle;
|
||||
int level = partparms.level;
|
||||
vec3_t local, transformed;
|
||||
float zi;
|
||||
byte *pdest;
|
||||
short *pz;
|
||||
int color = pparticle->color;
|
||||
int i, izi, pix, count, u, v;
|
||||
byte (*blendparticle)( int, int );
|
||||
|
||||
/*
|
||||
** transform the particle
|
||||
*/
|
||||
VectorSubtract (pparticle->origin, 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;
|
||||
|
||||
/*
|
||||
** bind the blend function pointer to the appropriate blender
|
||||
*/
|
||||
if ( level == PARTICLE_33 )
|
||||
blendparticle = BlendParticle33;
|
||||
else if ( level == PARTICLE_66 )
|
||||
blendparticle = BlendParticle66;
|
||||
else
|
||||
blendparticle = BlendParticle100;
|
||||
|
||||
/*
|
||||
** 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;
|
||||
}
|
||||
|
||||
/*
|
||||
** compute addresses of zbuffer, framebuffer, and
|
||||
** compute the Z-buffer reference value.
|
||||
*/
|
||||
pz = d_pzbuffer + (d_zwidth * v) + u;
|
||||
pdest = d_viewbuffer + d_scantable[v] + u;
|
||||
izi = (int)(zi * 0x8000);
|
||||
|
||||
/*
|
||||
** determine the screen area covered by the particle,
|
||||
** which also means clamping to a min and max
|
||||
*/
|
||||
pix = izi >> d_pix_shift;
|
||||
if (pix < d_pix_min)
|
||||
pix = d_pix_min;
|
||||
else if (pix > d_pix_max)
|
||||
pix = d_pix_max;
|
||||
|
||||
/*
|
||||
** render the appropriate pixels
|
||||
*/
|
||||
count = pix;
|
||||
|
||||
switch (level) {
|
||||
case PARTICLE_33 :
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
|
||||
{
|
||||
//FIXME--do it in blocks of 8?
|
||||
for (i=0 ; i<pix ; i++)
|
||||
{
|
||||
if (pz[i] <= izi)
|
||||
{
|
||||
pz[i] = izi;
|
||||
pdest[i] = vid.alphamap[color + ((int)pdest[i]<<8)];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PARTICLE_66 :
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
|
||||
{
|
||||
for (i=0 ; i<pix ; i++)
|
||||
{
|
||||
if (pz[i] <= izi)
|
||||
{
|
||||
pz[i] = izi;
|
||||
pdest[i] = vid.alphamap[(color<<8) + (int)pdest[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: //100
|
||||
for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
|
||||
{
|
||||
for (i=0 ; i<pix ; i++)
|
||||
{
|
||||
if (pz[i] <= izi)
|
||||
{
|
||||
pz[i] = izi;
|
||||
pdest[i] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
/*
|
||||
** R_DrawParticles
|
||||
**
|
||||
** Responsible for drawing all of the particles in the particle list
|
||||
** throughout the world. Doesn't care if we're using the C path or
|
||||
** if we're using the asm path, it simply assigns a function pointer
|
||||
** and goes.
|
||||
*/
|
||||
void R_DrawParticles (void)
|
||||
{
|
||||
particle_t *p;
|
||||
int i;
|
||||
extern unsigned long fpu_sp24_cw, fpu_chop_cw;
|
||||
|
||||
VectorScale( vright, xscaleshrink, r_pright );
|
||||
VectorScale( vup, yscaleshrink, r_pup );
|
||||
VectorCopy( vpn, r_ppn );
|
||||
|
||||
#if id386 && !defined __linux__
|
||||
__asm fldcw word ptr [fpu_sp24_cw]
|
||||
#endif
|
||||
|
||||
for (p=r_newrefdef.particles, i=0 ; i<r_newrefdef.num_particles ; i++,p++)
|
||||
{
|
||||
|
||||
if ( p->alpha > 0.66 )
|
||||
partparms.level = PARTICLE_OPAQUE;
|
||||
else if ( p->alpha > 0.33 )
|
||||
partparms.level = PARTICLE_66;
|
||||
else
|
||||
partparms.level = PARTICLE_33;
|
||||
|
||||
partparms.particle = p;
|
||||
partparms.color = p->color;
|
||||
|
||||
#if id386 && !defined __linux__
|
||||
if ( i < r_newrefdef.num_particles-1 )
|
||||
s_prefetch_address = ( unsigned int ) ( p + 1 );
|
||||
else
|
||||
s_prefetch_address = ( unsigned int ) r_newrefdef.particles;
|
||||
#endif
|
||||
|
||||
R_DrawParticle();
|
||||
}
|
||||
|
||||
#if id386 && !defined __linux__
|
||||
__asm fldcw word ptr [fpu_chop_cw]
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
1244
ref_soft/r_poly.c
Normal file
1244
ref_soft/r_poly.c
Normal file
File diff suppressed because it is too large
Load Diff
812
ref_soft/r_polysa.asm
Normal file
812
ref_soft/r_polysa.asm
Normal file
@@ -0,0 +1,812 @@
|
||||
.386P
|
||||
.model FLAT
|
||||
;
|
||||
; d_polysa.s
|
||||
; x86 assembly-language polygon model drawing code
|
||||
;
|
||||
|
||||
include qasm.inc
|
||||
include d_if.inc
|
||||
|
||||
if id386
|
||||
|
||||
; !!! if this is changed, it must be changed in d_polyse.c too !!!
|
||||
;DPS_MAXSPANS equ (MAXHEIGHT+1)
|
||||
; 1 extra for spanpackage that marks end
|
||||
|
||||
;SPAN_SIZE equ (((DPS_MAXSPANS + 1 + ((CACHE_SIZE - 1) / spanpackage_t_size)) + 1) * spanpackage_t_size)
|
||||
|
||||
MASK_1K equ 03FFh
|
||||
|
||||
_DATA SEGMENT
|
||||
|
||||
align 4
|
||||
;p10_minus_p20 dd 0
|
||||
;p01_minus_p21 dd 0
|
||||
;temp0 dd 0
|
||||
;temp1 dd 0
|
||||
;Ltemp dd 0
|
||||
|
||||
aff8entryvec_table dd LDraw8, LDraw7, LDraw6, LDraw5
|
||||
dd LDraw4, LDraw3, LDraw2, LDraw1, LDraw8IR, LDraw7IR, LDraw6IR, LDraw5IR, LDraw4IR, LDraw3IR, LDraw2IR, LDraw1IR
|
||||
|
||||
lzistepx dd 0
|
||||
|
||||
externdef _rand1k:dword
|
||||
externdef _rand1k_index:dword
|
||||
externdef _alias_colormap:dword
|
||||
|
||||
;PGM
|
||||
externdef _irtable:dword
|
||||
externdef _iractive:byte
|
||||
;PGM
|
||||
|
||||
_DATA ENDS
|
||||
_TEXT SEGMENT
|
||||
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; 8-bpp horizontal span drawing code for affine polygons, with smooth
|
||||
; shading and no transparency
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
;===================================
|
||||
;===================================
|
||||
|
||||
pspans equ 4+8
|
||||
|
||||
public _D_PolysetAff8Start
|
||||
_D_PolysetAff8Start:
|
||||
|
||||
public _R_PolysetDrawSpans8_Opaque
|
||||
_R_PolysetDrawSpans8_Opaque:
|
||||
|
||||
push esi ; preserve register variables
|
||||
push ebx
|
||||
|
||||
mov esi,ds:dword ptr[pspans+esp] ; point to the first span descriptor
|
||||
mov ecx,ds:dword ptr[_r_zistepx]
|
||||
|
||||
push ebp ; preserve caller's stack frame
|
||||
push edi
|
||||
|
||||
ror ecx,16 ; put high 16 bits of 1/z step in low word
|
||||
mov edx,ds:dword ptr[spanpackage_t_count+esi]
|
||||
|
||||
mov ds:dword ptr[lzistepx],ecx
|
||||
|
||||
LSpanLoop:
|
||||
|
||||
; lcount = d_aspancount - pspanpackage->count;
|
||||
;
|
||||
; errorterm += erroradjustup;
|
||||
; if (errorterm >= 0)
|
||||
; {
|
||||
; d_aspancount += d_countextrastep;
|
||||
; errorterm -= erroradjustdown;
|
||||
; }
|
||||
; else
|
||||
; {
|
||||
; d_aspancount += ubasestep;
|
||||
; }
|
||||
|
||||
mov eax,ds:dword ptr[_d_aspancount]
|
||||
sub eax,edx
|
||||
|
||||
mov edx,ds:dword ptr[_erroradjustup]
|
||||
mov ebx,ds:dword ptr[_errorterm]
|
||||
add ebx,edx
|
||||
js LNoTurnover
|
||||
|
||||
mov edx,ds:dword ptr[_erroradjustdown]
|
||||
mov edi,ds:dword ptr[_d_countextrastep]
|
||||
sub ebx,edx
|
||||
mov ebp,ds:dword ptr[_d_aspancount]
|
||||
mov ds:dword ptr[_errorterm],ebx
|
||||
add ebp,edi
|
||||
mov ds:dword ptr[_d_aspancount],ebp
|
||||
jmp LRightEdgeStepped
|
||||
|
||||
LNoTurnover:
|
||||
mov edi,ds:dword ptr[_d_aspancount]
|
||||
mov edx,ds:dword ptr[_ubasestep]
|
||||
mov ds:dword ptr[_errorterm],ebx
|
||||
add edi,edx
|
||||
mov ds:dword ptr[_d_aspancount],edi
|
||||
|
||||
LRightEdgeStepped:
|
||||
cmp eax,1
|
||||
|
||||
jl LNextSpan
|
||||
jz LExactlyOneLong
|
||||
|
||||
;
|
||||
; set up advancetable
|
||||
;
|
||||
mov ecx,ds:dword ptr[_a_ststepxwhole]
|
||||
mov edx,ds:dword ptr[_r_affinetridesc+atd_skinwidth]
|
||||
|
||||
mov ds:dword ptr[advancetable+4],ecx ; advance base in t
|
||||
add ecx,edx
|
||||
|
||||
mov ds:dword ptr[advancetable],ecx ; advance extra in t
|
||||
mov ecx,ds:dword ptr[_a_tstepxfrac]
|
||||
|
||||
mov cx,ds:word ptr[_r_lstepx]
|
||||
mov edx,eax ; count
|
||||
|
||||
mov ds:dword ptr[tstep],ecx
|
||||
add edx,7
|
||||
|
||||
shr edx,3 ; count of full and partial loops
|
||||
mov ebx,ds:dword ptr[spanpackage_t_sfrac+esi]
|
||||
|
||||
mov bx,dx
|
||||
mov ecx,ds:dword ptr[spanpackage_t_pz+esi]
|
||||
|
||||
neg eax
|
||||
|
||||
mov edi,ds:dword ptr[spanpackage_t_pdest+esi]
|
||||
and eax,7 ; 0->0, 1->7, 2->6, ... , 7->1
|
||||
|
||||
sub edi,eax ; compensate for hardwired offsets
|
||||
sub ecx,eax
|
||||
|
||||
sub ecx,eax
|
||||
mov edx,ds:dword ptr[spanpackage_t_tfrac+esi]
|
||||
|
||||
mov dx,ds:word ptr[spanpackage_t_light+esi]
|
||||
mov ebp,ds:dword ptr[spanpackage_t_zi+esi]
|
||||
|
||||
ror ebp,16 ; put high 16 bits of 1/z in low word
|
||||
push esi
|
||||
|
||||
push eax
|
||||
mov al, [_iractive]
|
||||
cmp al, 0
|
||||
pop eax
|
||||
jne IRInsert
|
||||
|
||||
mov esi,ds:dword ptr[spanpackage_t_ptex+esi]
|
||||
jmp dword ptr[aff8entryvec_table+eax*4]
|
||||
|
||||
IRInsert:
|
||||
mov esi,ds:dword ptr[spanpackage_t_ptex+esi]
|
||||
add eax, 8
|
||||
jmp dword ptr[aff8entryvec_table+eax*4]
|
||||
|
||||
; %bx = count of full and partial loops
|
||||
; %ebx high word = sfrac
|
||||
; %ecx = pz
|
||||
; %dx = light
|
||||
; %edx high word = tfrac
|
||||
; %esi = ptex
|
||||
; %edi = pdest
|
||||
; %ebp = 1/z
|
||||
; tstep low word = C(r_lstepx)
|
||||
; tstep high word = C(a_tstepxfrac)
|
||||
; C(a_sstepxfrac) low word = 0
|
||||
; C(a_sstepxfrac) high word = C(a_sstepxfrac)
|
||||
|
||||
;===
|
||||
;Standard Draw Loop
|
||||
;===
|
||||
LDrawLoop:
|
||||
|
||||
mov al,[_iractive]
|
||||
cmp al,0
|
||||
jne LDrawLoopIR
|
||||
|
||||
; FIXME: do we need to clamp light? We may need at least a buffer bit to
|
||||
; keep it from poking into tfrac and causing problems
|
||||
|
||||
LDraw8:
|
||||
cmp bp,ds:word ptr[ecx]
|
||||
jl Lp1
|
||||
xor eax,eax
|
||||
mov ah,dh
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov ds:word ptr[ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch8:
|
||||
mov ds:byte ptr[edi],al
|
||||
Lp1:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw7:
|
||||
cmp bp,ds:word ptr[2+ecx]
|
||||
jl Lp2
|
||||
xor eax,eax
|
||||
mov ah,dh
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov ds:word ptr[2+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch7:
|
||||
mov ds:byte ptr[1+edi],al
|
||||
Lp2:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw6:
|
||||
cmp bp,ds:word ptr[4+ecx]
|
||||
jl Lp3
|
||||
xor eax,eax
|
||||
mov ah,dh
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov ds:word ptr[4+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch6:
|
||||
mov ds:byte ptr[2+edi],al
|
||||
Lp3:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw5:
|
||||
cmp bp,ds:word ptr[6+ecx]
|
||||
jl Lp4
|
||||
xor eax,eax
|
||||
mov ah,dh
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov ds:word ptr[6+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch5:
|
||||
mov ds:byte ptr[3+edi],al
|
||||
Lp4:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw4:
|
||||
cmp bp,ds:word ptr[8+ecx]
|
||||
jl Lp5
|
||||
xor eax,eax
|
||||
mov ah,dh
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov ds:word ptr[8+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch4:
|
||||
mov ds:byte ptr[4+edi],al
|
||||
Lp5:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw3:
|
||||
cmp bp,ds:word ptr[10+ecx]
|
||||
jl Lp6
|
||||
xor eax,eax
|
||||
mov ah,dh
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov ds:word ptr[10+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch3:
|
||||
mov ds:byte ptr[5+edi],al
|
||||
Lp6:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw2:
|
||||
cmp bp,ds:word ptr[12+ecx]
|
||||
jl Lp7
|
||||
xor eax,eax
|
||||
mov ah,dh
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov ds:word ptr[12+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch2:
|
||||
mov ds:byte ptr[6+edi],al
|
||||
Lp7:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw1:
|
||||
cmp bp,ds:word ptr[14+ecx]
|
||||
jl Lp8
|
||||
xor eax,eax
|
||||
mov ah,dh
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov ds:word ptr[14+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch1:
|
||||
mov ds:byte ptr[7+edi],al
|
||||
Lp8:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
add edi,8
|
||||
add ecx,16
|
||||
|
||||
dec bx
|
||||
jnz LDrawLoop
|
||||
|
||||
pop esi ; restore spans pointer
|
||||
LNextSpan:
|
||||
add esi,offset spanpackage_t_size ; point to next span
|
||||
LNextSpanESISet:
|
||||
mov edx,ds:dword ptr[spanpackage_t_count+esi]
|
||||
cmp edx,offset -999999 ; any more spans?
|
||||
jnz LSpanLoop ; yes
|
||||
|
||||
pop edi
|
||||
pop ebp ; restore the caller's stack frame
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
ret
|
||||
|
||||
;=======
|
||||
; IR active draw loop
|
||||
;=======
|
||||
LDrawLoopIR:
|
||||
|
||||
; FIXME: do we need to clamp light? We may need at least a buffer bit to
|
||||
; keep it from poking into tfrac and causing problems
|
||||
|
||||
LDraw8IR:
|
||||
cmp bp,ds:word ptr[ecx]
|
||||
jl Lp1IR
|
||||
xor eax,eax
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch8IR:
|
||||
mov ds:byte ptr[edi],al
|
||||
Lp1IR:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw7IR:
|
||||
cmp bp,ds:word ptr[2+ecx]
|
||||
jl Lp2IR
|
||||
xor eax,eax
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[2+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch7IR:
|
||||
mov ds:byte ptr[1+edi],al
|
||||
Lp2IR:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw6IR:
|
||||
cmp bp,ds:word ptr[4+ecx]
|
||||
jl Lp3IR
|
||||
xor eax,eax
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[4+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch6IR:
|
||||
mov ds:byte ptr[2+edi],al
|
||||
Lp3IR:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw5IR:
|
||||
cmp bp,ds:word ptr[6+ecx]
|
||||
jl Lp4IR
|
||||
xor eax,eax
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[6+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch5IR:
|
||||
mov ds:byte ptr[3+edi],al
|
||||
Lp4IR:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw4IR:
|
||||
cmp bp,ds:word ptr[8+ecx]
|
||||
jl Lp5IR
|
||||
xor eax,eax
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[8+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch4IR:
|
||||
mov ds:byte ptr[4+edi],al
|
||||
Lp5IR:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw3IR:
|
||||
cmp bp,ds:word ptr[10+ecx]
|
||||
jl Lp6IR
|
||||
xor eax,eax
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[10+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch3IR:
|
||||
mov ds:byte ptr[5+edi],al
|
||||
Lp6IR:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw2IR:
|
||||
cmp bp,ds:word ptr[12+ecx]
|
||||
jl Lp7IR
|
||||
xor eax,eax
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[12+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch2IR:
|
||||
mov ds:byte ptr[6+edi],al
|
||||
Lp7IR:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LDraw1IR:
|
||||
cmp bp,ds:word ptr[14+ecx]
|
||||
jl Lp8IR
|
||||
xor eax,eax
|
||||
mov al,ds:byte ptr[esi]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[14+ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch1IR:
|
||||
mov ds:byte ptr[7+edi],al
|
||||
Lp8IR:
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebp,ds:dword ptr[lzistepx]
|
||||
adc ebp,0
|
||||
add ebx,ds:dword ptr[_a_sstepxfrac]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
add edi,8
|
||||
add ecx,16
|
||||
|
||||
dec bx
|
||||
jnz LDrawLoopIR
|
||||
|
||||
pop esi ; restore spans pointer
|
||||
LNextSpanIR:
|
||||
add esi,offset spanpackage_t_size ; point to next span
|
||||
LNextSpanESISetIR:
|
||||
mov edx,ds:dword ptr[spanpackage_t_count+esi]
|
||||
cmp edx,offset -999999 ; any more spans?
|
||||
jnz LSpanLoop ; yes
|
||||
|
||||
pop edi
|
||||
pop ebp ; restore the caller's stack frame
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
ret
|
||||
|
||||
;=======
|
||||
; Standard One-Long Draw
|
||||
;=======
|
||||
; draw a one-long span
|
||||
|
||||
LExactlyOneLong:
|
||||
mov al,[_iractive]
|
||||
cmp al,0
|
||||
jne LExactlyOneLongIR
|
||||
|
||||
mov ecx,ds:dword ptr[spanpackage_t_pz+esi]
|
||||
mov ebp,ds:dword ptr[spanpackage_t_zi+esi]
|
||||
|
||||
ror ebp,16 ; put high 16 bits of 1/z in low word
|
||||
mov ebx,ds:dword ptr[spanpackage_t_ptex+esi]
|
||||
|
||||
cmp bp,ds:word ptr[ecx]
|
||||
jl LNextSpan
|
||||
xor eax,eax
|
||||
mov edi,ds:dword ptr[spanpackage_t_pdest+esi]
|
||||
mov ah,ds:byte ptr[spanpackage_t_light+1+esi]
|
||||
add esi,offset spanpackage_t_size ; point to next span
|
||||
mov al,ds:byte ptr[ebx]
|
||||
mov ds:word ptr[ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch9:
|
||||
mov ds:byte ptr[edi],al
|
||||
|
||||
jmp LNextSpanESISet
|
||||
|
||||
|
||||
;========
|
||||
;========
|
||||
; draw a one-long span
|
||||
|
||||
LExactlyOneLongIR:
|
||||
|
||||
mov ecx,ds:dword ptr[spanpackage_t_pz+esi]
|
||||
mov ebp,ds:dword ptr[spanpackage_t_zi+esi]
|
||||
|
||||
ror ebp,16 ; put high 16 bits of 1/z in low word
|
||||
mov ebx,ds:dword ptr[spanpackage_t_ptex+esi]
|
||||
|
||||
cmp bp,ds:word ptr[ecx]
|
||||
jl LNextSpanIR
|
||||
xor eax,eax
|
||||
mov edi,ds:dword ptr[spanpackage_t_pdest+esi]
|
||||
add esi,offset spanpackage_t_size ; point to next span
|
||||
mov al,ds:byte ptr[ebx]
|
||||
mov al,ds:byte ptr[_irtable+eax]
|
||||
mov ds:word ptr[ecx],bp
|
||||
mov al,ds:byte ptr[12345678h+eax]
|
||||
LPatch9IR:
|
||||
mov ds:byte ptr[edi],al
|
||||
|
||||
jmp LNextSpanESISetIR
|
||||
|
||||
;===================================
|
||||
;===================================
|
||||
public _D_Aff8Patch
|
||||
_D_Aff8Patch:
|
||||
mov eax,[_alias_colormap]
|
||||
mov ds:dword ptr[LPatch1-4],eax
|
||||
mov ds:dword ptr[LPatch2-4],eax
|
||||
mov ds:dword ptr[LPatch3-4],eax
|
||||
mov ds:dword ptr[LPatch4-4],eax
|
||||
mov ds:dword ptr[LPatch5-4],eax
|
||||
mov ds:dword ptr[LPatch6-4],eax
|
||||
mov ds:dword ptr[LPatch7-4],eax
|
||||
mov ds:dword ptr[LPatch8-4],eax
|
||||
mov ds:dword ptr[LPatch9-4],eax
|
||||
mov ds:dword ptr[LPatch1IR-4],eax
|
||||
mov ds:dword ptr[LPatch2IR-4],eax
|
||||
mov ds:dword ptr[LPatch3IR-4],eax
|
||||
mov ds:dword ptr[LPatch4IR-4],eax
|
||||
mov ds:dword ptr[LPatch5IR-4],eax
|
||||
mov ds:dword ptr[LPatch6IR-4],eax
|
||||
mov ds:dword ptr[LPatch7IR-4],eax
|
||||
mov ds:dword ptr[LPatch8IR-4],eax
|
||||
mov ds:dword ptr[LPatch9IR-4],eax
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;===================================
|
||||
;===================================
|
||||
|
||||
height equ 4+16
|
||||
|
||||
public _R_PolysetScanLeftEdge
|
||||
_R_PolysetScanLeftEdge:
|
||||
push ebp ; preserve caller stack frame pointer
|
||||
push esi ; preserve register variables
|
||||
push edi
|
||||
push ebx
|
||||
|
||||
mov eax,ds:dword ptr[height+esp]
|
||||
mov ecx,ds:dword ptr[_d_sfrac]
|
||||
|
||||
and eax,0FFFFh
|
||||
mov ebx,ds:dword ptr[_d_ptex]
|
||||
or ecx,eax
|
||||
mov esi,ds:dword ptr[_d_pedgespanpackage]
|
||||
mov edx,ds:dword ptr[_d_tfrac]
|
||||
mov edi,ds:dword ptr[_d_light]
|
||||
mov ebp,ds:dword ptr[_d_zi]
|
||||
|
||||
; %eax: scratch
|
||||
; %ebx: d_ptex
|
||||
; %ecx: d_sfrac in high word, count in low word
|
||||
; %edx: d_tfrac
|
||||
; %esi: d_pedgespanpackage, errorterm, scratch alternately
|
||||
; %edi: d_light
|
||||
; %ebp: d_zi
|
||||
|
||||
; do
|
||||
; {
|
||||
|
||||
LScanLoop:
|
||||
|
||||
; d_pedgespanpackage->ptex = ptex;
|
||||
; d_pedgespanpackage->pdest = d_pdest;
|
||||
; d_pedgespanpackage->pz = d_pz;
|
||||
; d_pedgespanpackage->count = d_aspancount;
|
||||
; d_pedgespanpackage->light = d_light;
|
||||
; d_pedgespanpackage->zi = d_zi;
|
||||
; d_pedgespanpackage->sfrac = d_sfrac << 16;
|
||||
; d_pedgespanpackage->tfrac = d_tfrac << 16;
|
||||
mov ds:dword ptr[spanpackage_t_ptex+esi],ebx
|
||||
mov eax,ds:dword ptr[_d_pdest]
|
||||
mov ds:dword ptr[spanpackage_t_pdest+esi],eax
|
||||
mov eax,ds:dword ptr[_d_pz]
|
||||
mov ds:dword ptr[spanpackage_t_pz+esi],eax
|
||||
mov eax,ds:dword ptr[_d_aspancount]
|
||||
mov ds:dword ptr[spanpackage_t_count+esi],eax
|
||||
mov ds:dword ptr[spanpackage_t_light+esi],edi
|
||||
mov ds:dword ptr[spanpackage_t_zi+esi],ebp
|
||||
mov ds:dword ptr[spanpackage_t_sfrac+esi],ecx
|
||||
mov ds:dword ptr[spanpackage_t_tfrac+esi],edx
|
||||
|
||||
; pretouch the next cache line
|
||||
mov al,ds:byte ptr[spanpackage_t_size+esi]
|
||||
|
||||
; d_pedgespanpackage++;
|
||||
add esi,offset spanpackage_t_size
|
||||
mov eax,ds:dword ptr[_erroradjustup]
|
||||
mov ds:dword ptr[_d_pedgespanpackage],esi
|
||||
|
||||
; errorterm += erroradjustup;
|
||||
mov esi,ds:dword ptr[_errorterm]
|
||||
add esi,eax
|
||||
mov eax,ds:dword ptr[_d_pdest]
|
||||
|
||||
; if (errorterm >= 0)
|
||||
; {
|
||||
js LNoLeftEdgeTurnover
|
||||
|
||||
; errorterm -= erroradjustdown;
|
||||
; d_pdest += d_pdestextrastep;
|
||||
sub esi,ds:dword ptr[_erroradjustdown]
|
||||
add eax,ds:dword ptr[_d_pdestextrastep]
|
||||
mov ds:dword ptr[_errorterm],esi
|
||||
mov ds:dword ptr[_d_pdest],eax
|
||||
|
||||
; d_pz += d_pzextrastep;
|
||||
; d_aspancount += d_countextrastep;
|
||||
; d_ptex += d_ptexextrastep;
|
||||
; d_sfrac += d_sfracextrastep;
|
||||
; d_ptex += d_sfrac >> 16;
|
||||
; d_sfrac &= 0xFFFF;
|
||||
; d_tfrac += d_tfracextrastep;
|
||||
mov eax,ds:dword ptr[_d_pz]
|
||||
mov esi,ds:dword ptr[_d_aspancount]
|
||||
add eax,ds:dword ptr[_d_pzextrastep]
|
||||
add ecx,ds:dword ptr[_d_sfracextrastep]
|
||||
adc ebx,ds:dword ptr[_d_ptexextrastep]
|
||||
add esi,ds:dword ptr[_d_countextrastep]
|
||||
mov ds:dword ptr[_d_pz],eax
|
||||
mov eax,ds:dword ptr[_d_tfracextrastep]
|
||||
mov ds:dword ptr[_d_aspancount],esi
|
||||
add edx,eax
|
||||
|
||||
; if (d_tfrac & 0x10000)
|
||||
; {
|
||||
jnc LSkip1
|
||||
|
||||
; d_ptex += r_affinetridesc.skinwidth;
|
||||
; d_tfrac &= 0xFFFF;
|
||||
add ebx,ds:dword ptr[_r_affinetridesc+atd_skinwidth]
|
||||
|
||||
; }
|
||||
|
||||
LSkip1:
|
||||
|
||||
; d_light += d_lightextrastep;
|
||||
; d_zi += d_ziextrastep;
|
||||
add edi,ds:dword ptr[_d_lightextrastep]
|
||||
add ebp,ds:dword ptr[_d_ziextrastep]
|
||||
|
||||
; }
|
||||
mov esi,ds:dword ptr[_d_pedgespanpackage]
|
||||
dec ecx
|
||||
test ecx,0FFFFh
|
||||
jnz LScanLoop
|
||||
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
; else
|
||||
; {
|
||||
|
||||
LNoLeftEdgeTurnover:
|
||||
mov ds:dword ptr[_errorterm],esi
|
||||
|
||||
; d_pdest += d_pdestbasestep;
|
||||
add eax,ds:dword ptr[_d_pdestbasestep]
|
||||
mov ds:dword ptr[_d_pdest],eax
|
||||
|
||||
; d_pz += d_pzbasestep;
|
||||
; d_aspancount += ubasestep;
|
||||
; d_ptex += d_ptexbasestep;
|
||||
; d_sfrac += d_sfracbasestep;
|
||||
; d_ptex += d_sfrac >> 16;
|
||||
; d_sfrac &= 0xFFFF;
|
||||
mov eax,ds:dword ptr[_d_pz]
|
||||
mov esi,ds:dword ptr[_d_aspancount]
|
||||
add eax,ds:dword ptr[_d_pzbasestep]
|
||||
add ecx,ds:dword ptr[_d_sfracbasestep]
|
||||
adc ebx,ds:dword ptr[_d_ptexbasestep]
|
||||
add esi,ds:dword ptr[_ubasestep]
|
||||
mov ds:dword ptr[_d_pz],eax
|
||||
mov ds:dword ptr[_d_aspancount],esi
|
||||
|
||||
; d_tfrac += d_tfracbasestep;
|
||||
mov esi,ds:dword ptr[_d_tfracbasestep]
|
||||
add edx,esi
|
||||
|
||||
; if (d_tfrac & 0x10000)
|
||||
; {
|
||||
jnc LSkip2
|
||||
|
||||
; d_ptex += r_affinetridesc.skinwidth;
|
||||
; d_tfrac &= 0xFFFF;
|
||||
add ebx,ds:dword ptr[_r_affinetridesc+atd_skinwidth]
|
||||
|
||||
; }
|
||||
|
||||
LSkip2:
|
||||
|
||||
; d_light += d_lightbasestep;
|
||||
; d_zi += d_zibasestep;
|
||||
add edi,ds:dword ptr[_d_lightbasestep]
|
||||
add ebp,ds:dword ptr[_d_zibasestep]
|
||||
|
||||
; }
|
||||
; } while (--height);
|
||||
mov esi,ds:dword ptr[_d_pedgespanpackage]
|
||||
dec ecx
|
||||
test ecx,0FFFFh
|
||||
jnz LScanLoop
|
||||
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
_TEXT ENDS
|
||||
endif ;id386
|
||||
END
|
||||
1539
ref_soft/r_polyse.c
Normal file
1539
ref_soft/r_polyse.c
Normal file
File diff suppressed because it is too large
Load Diff
852
ref_soft/r_rast.c
Normal file
852
ref_soft/r_rast.c
Normal file
@@ -0,0 +1,852 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// r_rast.c
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
#define MAXLEFTCLIPEDGES 100
|
||||
|
||||
// !!! if these are changed, they must be changed in asm_draw.h too !!!
|
||||
#define FULLY_CLIPPED_CACHED 0x80000000
|
||||
#define FRAMECOUNT_MASK 0x7FFFFFFF
|
||||
|
||||
unsigned int cacheoffset;
|
||||
|
||||
int c_faceclip; // number of faces clipped
|
||||
|
||||
|
||||
clipplane_t *entity_clipplanes;
|
||||
clipplane_t view_clipplanes[4];
|
||||
clipplane_t world_clipplanes[16];
|
||||
|
||||
medge_t *r_pedge;
|
||||
|
||||
qboolean r_leftclipped, r_rightclipped;
|
||||
static qboolean makeleftedge, makerightedge;
|
||||
qboolean r_nearzionly;
|
||||
|
||||
int sintable[1280];
|
||||
int intsintable[1280];
|
||||
int blanktable[1280]; // PGM
|
||||
|
||||
mvertex_t r_leftenter, r_leftexit;
|
||||
mvertex_t r_rightenter, r_rightexit;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float u,v;
|
||||
int ceilv;
|
||||
} evert_t;
|
||||
|
||||
int r_emitted;
|
||||
float r_nearzi;
|
||||
float r_u1, r_v1, r_lzi1;
|
||||
int r_ceilv1;
|
||||
|
||||
qboolean r_lastvertvalid;
|
||||
int r_skyframe;
|
||||
|
||||
msurface_t *r_skyfaces;
|
||||
mplane_t r_skyplanes[6];
|
||||
mtexinfo_t r_skytexinfo[6];
|
||||
mvertex_t *r_skyverts;
|
||||
medge_t *r_skyedges;
|
||||
int *r_skysurfedges;
|
||||
|
||||
// I just copied this data from a box map...
|
||||
int skybox_planes[12] = {2,-128, 0,-128, 2,128, 1,128, 0,128, 1,-128};
|
||||
|
||||
int box_surfedges[24] = { 1,2,3,4, -1,5,6,7, 8,9,-6,10, -2,-7,-9,11,
|
||||
12,-3,-11,-8, -12,-10,-5,-4};
|
||||
int box_edges[24] = { 1,2, 2,3, 3,4, 4,1, 1,5, 5,6, 6,2, 7,8, 8,6, 5,7, 8,3, 7,4};
|
||||
|
||||
int box_faces[6] = {0,0,2,2,2,0};
|
||||
|
||||
vec3_t box_vecs[6][2] = {
|
||||
{ {0,-1,0}, {-1,0,0} },
|
||||
{ {0,1,0}, {0,0,-1} },
|
||||
{ {0,-1,0}, {1,0,0} },
|
||||
{ {1,0,0}, {0,0,-1} },
|
||||
{ {0,-1,0}, {0,0,-1} },
|
||||
{ {-1,0,0}, {0,0,-1} }
|
||||
};
|
||||
|
||||
float box_verts[8][3] = {
|
||||
{-1,-1,-1},
|
||||
{-1,1,-1},
|
||||
{1,1,-1},
|
||||
{1,-1,-1},
|
||||
{-1,-1,1},
|
||||
{-1,1,1},
|
||||
{1,-1,1},
|
||||
{1,1,1}
|
||||
};
|
||||
|
||||
// down, west, up, north, east, south
|
||||
// {"rt", "bk", "lf", "ft", "up", "dn"};
|
||||
|
||||
/*
|
||||
================
|
||||
R_InitSkyBox
|
||||
|
||||
================
|
||||
*/
|
||||
void R_InitSkyBox (void)
|
||||
{
|
||||
int i;
|
||||
extern model_t *loadmodel;
|
||||
|
||||
r_skyfaces = loadmodel->surfaces + loadmodel->numsurfaces;
|
||||
loadmodel->numsurfaces += 6;
|
||||
r_skyverts = loadmodel->vertexes + loadmodel->numvertexes;
|
||||
loadmodel->numvertexes += 8;
|
||||
r_skyedges = loadmodel->edges + loadmodel->numedges;
|
||||
loadmodel->numedges += 12;
|
||||
r_skysurfedges = loadmodel->surfedges + loadmodel->numsurfedges;
|
||||
loadmodel->numsurfedges += 24;
|
||||
if (loadmodel->numsurfaces > MAX_MAP_FACES
|
||||
|| loadmodel->numvertexes > MAX_MAP_VERTS
|
||||
|| loadmodel->numedges > MAX_MAP_EDGES)
|
||||
ri.Sys_Error (ERR_DROP, "InitSkyBox: map overflow");
|
||||
|
||||
memset (r_skyfaces, 0, 6*sizeof(*r_skyfaces));
|
||||
for (i=0 ; i<6 ; i++)
|
||||
{
|
||||
r_skyplanes[i].normal[skybox_planes[i*2]] = 1;
|
||||
r_skyplanes[i].dist = skybox_planes[i*2+1];
|
||||
|
||||
VectorCopy (box_vecs[i][0], r_skytexinfo[i].vecs[0]);
|
||||
VectorCopy (box_vecs[i][1], r_skytexinfo[i].vecs[1]);
|
||||
|
||||
r_skyfaces[i].plane = &r_skyplanes[i];
|
||||
r_skyfaces[i].numedges = 4;
|
||||
r_skyfaces[i].flags = box_faces[i] | SURF_DRAWSKYBOX;
|
||||
r_skyfaces[i].firstedge = loadmodel->numsurfedges-24+i*4;
|
||||
r_skyfaces[i].texinfo = &r_skytexinfo[i];
|
||||
r_skyfaces[i].texturemins[0] = -128;
|
||||
r_skyfaces[i].texturemins[1] = -128;
|
||||
r_skyfaces[i].extents[0] = 256;
|
||||
r_skyfaces[i].extents[1] = 256;
|
||||
}
|
||||
|
||||
for (i=0 ; i<24 ; i++)
|
||||
if (box_surfedges[i] > 0)
|
||||
r_skysurfedges[i] = loadmodel->numedges-13 + box_surfedges[i];
|
||||
else
|
||||
r_skysurfedges[i] = - (loadmodel->numedges-13 + -box_surfedges[i]);
|
||||
|
||||
for(i=0 ; i<12 ; i++)
|
||||
{
|
||||
r_skyedges[i].v[0] = loadmodel->numvertexes-9+box_edges[i*2+0];
|
||||
r_skyedges[i].v[1] = loadmodel->numvertexes-9+box_edges[i*2+1];
|
||||
r_skyedges[i].cachededgeoffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_EmitSkyBox
|
||||
================
|
||||
*/
|
||||
void R_EmitSkyBox (void)
|
||||
{
|
||||
int i, j;
|
||||
int oldkey;
|
||||
|
||||
if (insubmodel)
|
||||
return; // submodels should never have skies
|
||||
if (r_skyframe == r_framecount)
|
||||
return; // already set this frame
|
||||
|
||||
r_skyframe = r_framecount;
|
||||
|
||||
// set the eight fake vertexes
|
||||
for (i=0 ; i<8 ; i++)
|
||||
for (j=0 ; j<3 ; j++)
|
||||
r_skyverts[i].position[j] = r_origin[j] + box_verts[i][j]*128;
|
||||
|
||||
// set the six fake planes
|
||||
for (i=0 ; i<6 ; i++)
|
||||
if (skybox_planes[i*2+1] > 0)
|
||||
r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]+128;
|
||||
else
|
||||
r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]-128;
|
||||
|
||||
// fix texture offseets
|
||||
for (i=0 ; i<6 ; i++)
|
||||
{
|
||||
r_skytexinfo[i].vecs[0][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[0]);
|
||||
r_skytexinfo[i].vecs[1][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[1]);
|
||||
}
|
||||
|
||||
// emit the six faces
|
||||
oldkey = r_currentkey;
|
||||
r_currentkey = 0x7ffffff0;
|
||||
for (i=0 ; i<6 ; i++)
|
||||
{
|
||||
R_RenderFace (r_skyfaces + i, 15);
|
||||
}
|
||||
r_currentkey = oldkey; // bsp sorting order
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
================
|
||||
R_EmitEdge
|
||||
================
|
||||
*/
|
||||
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
|
||||
{
|
||||
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)
|
||||
{
|
||||
u0 = r_u1;
|
||||
v0 = r_v1;
|
||||
lzi0 = r_lzi1;
|
||||
ceilv0 = r_ceilv1;
|
||||
}
|
||||
else
|
||||
{
|
||||
world = &pv0->position[0];
|
||||
|
||||
// transform and project
|
||||
VectorSubtract (world, modelorg, local);
|
||||
TransformVector (local, transformed);
|
||||
|
||||
if (transformed[2] < NEAR_CLIP)
|
||||
transformed[2] = NEAR_CLIP;
|
||||
|
||||
lzi0 = 1.0 / transformed[2];
|
||||
|
||||
// FIXME: build x/yscale into transform?
|
||||
scale = xscale * lzi0;
|
||||
u0 = (xcenter + scale*transformed[0]);
|
||||
if (u0 < r_refdef.fvrectx_adj)
|
||||
u0 = r_refdef.fvrectx_adj;
|
||||
if (u0 > r_refdef.fvrectright_adj)
|
||||
u0 = r_refdef.fvrectright_adj;
|
||||
|
||||
scale = yscale * lzi0;
|
||||
v0 = (ycenter - scale*transformed[1]);
|
||||
if (v0 < r_refdef.fvrecty_adj)
|
||||
v0 = r_refdef.fvrecty_adj;
|
||||
if (v0 > r_refdef.fvrectbottom_adj)
|
||||
v0 = r_refdef.fvrectbottom_adj;
|
||||
|
||||
ceilv0 = (int) ceil(v0);
|
||||
}
|
||||
|
||||
world = &pv1->position[0];
|
||||
|
||||
// transform and project
|
||||
VectorSubtract (world, modelorg, local);
|
||||
TransformVector (local, transformed);
|
||||
|
||||
if (transformed[2] < NEAR_CLIP)
|
||||
transformed[2] = NEAR_CLIP;
|
||||
|
||||
r_lzi1 = 1.0 / transformed[2];
|
||||
|
||||
scale = xscale * r_lzi1;
|
||||
r_u1 = (xcenter + scale*transformed[0]);
|
||||
if (r_u1 < r_refdef.fvrectx_adj)
|
||||
r_u1 = r_refdef.fvrectx_adj;
|
||||
if (r_u1 > r_refdef.fvrectright_adj)
|
||||
r_u1 = r_refdef.fvrectright_adj;
|
||||
|
||||
scale = yscale * r_lzi1;
|
||||
r_v1 = (ycenter - scale*transformed[1]);
|
||||
if (r_v1 < r_refdef.fvrecty_adj)
|
||||
r_v1 = r_refdef.fvrecty_adj;
|
||||
if (r_v1 > r_refdef.fvrectbottom_adj)
|
||||
r_v1 = r_refdef.fvrectbottom_adj;
|
||||
|
||||
if (r_lzi1 > lzi0)
|
||||
lzi0 = r_lzi1;
|
||||
|
||||
if (lzi0 > r_nearzi) // for mipmap finding
|
||||
r_nearzi = lzi0;
|
||||
|
||||
// for right edges, all we want is the effect on 1/z
|
||||
if (r_nearzionly)
|
||||
return;
|
||||
|
||||
r_emitted = 1;
|
||||
|
||||
r_ceilv1 = (int) ceil(r_v1);
|
||||
|
||||
|
||||
// create the edge
|
||||
if (ceilv0 == r_ceilv1)
|
||||
{
|
||||
// we cache unclipped horizontal edges as fully clipped
|
||||
if (cacheoffset != 0x7FFFFFFF)
|
||||
{
|
||||
cacheoffset = FULLY_CLIPPED_CACHED |
|
||||
(r_framecount & FRAMECOUNT_MASK);
|
||||
}
|
||||
|
||||
return; // horizontal edge
|
||||
}
|
||||
|
||||
side = ceilv0 > r_ceilv1;
|
||||
|
||||
edge = edge_p++;
|
||||
|
||||
edge->owner = r_pedge;
|
||||
|
||||
edge->nearzi = lzi0;
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
// trailing edge (go from p1 to p2)
|
||||
v = ceilv0;
|
||||
v2 = r_ceilv1 - 1;
|
||||
|
||||
edge->surfs[0] = surface_p - surfaces;
|
||||
edge->surfs[1] = 0;
|
||||
|
||||
u_step = ((r_u1 - u0) / (r_v1 - v0));
|
||||
u = u0 + ((float)v - v0) * u_step;
|
||||
}
|
||||
else
|
||||
{
|
||||
// leading edge (go from p2 to p1)
|
||||
v2 = ceilv0 - 1;
|
||||
v = r_ceilv1;
|
||||
|
||||
edge->surfs[0] = 0;
|
||||
edge->surfs[1] = surface_p - surfaces;
|
||||
|
||||
u_step = ((u0 - r_u1) / (v0 - r_v1));
|
||||
u = r_u1 + ((float)v - r_v1) * u_step;
|
||||
}
|
||||
|
||||
edge->u_step = u_step*0x100000;
|
||||
edge->u = u*0x100000 + 0xFFFFF;
|
||||
|
||||
// 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;
|
||||
|
||||
//
|
||||
// sort the edge in normally
|
||||
//
|
||||
u_check = edge->u;
|
||||
if (edge->surfs[0])
|
||||
u_check++; // sort trailers after leaders
|
||||
|
||||
if (!newedges[v] || newedges[v]->u >= u_check)
|
||||
{
|
||||
edge->next = newedges[v];
|
||||
newedges[v] = edge;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcheck = newedges[v];
|
||||
while (pcheck->next && pcheck->next->u < u_check)
|
||||
pcheck = pcheck->next;
|
||||
edge->next = pcheck->next;
|
||||
pcheck->next = edge;
|
||||
}
|
||||
|
||||
edge->nextremove = removeedges[v2];
|
||||
removeedges[v2] = edge;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_ClipEdge
|
||||
================
|
||||
*/
|
||||
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
|
||||
{
|
||||
float d0, d1, f;
|
||||
mvertex_t clipvert;
|
||||
|
||||
if (clip)
|
||||
{
|
||||
do
|
||||
{
|
||||
d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
|
||||
d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
|
||||
|
||||
if (d0 >= 0)
|
||||
{
|
||||
// point 0 is unclipped
|
||||
if (d1 >= 0)
|
||||
{
|
||||
// both points are unclipped
|
||||
continue;
|
||||
}
|
||||
|
||||
// only point 1 is clipped
|
||||
|
||||
// we don't cache clipped edges
|
||||
cacheoffset = 0x7FFFFFFF;
|
||||
|
||||
f = d0 / (d0 - d1);
|
||||
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]);
|
||||
|
||||
if (clip->leftedge)
|
||||
{
|
||||
r_leftclipped = true;
|
||||
r_leftexit = clipvert;
|
||||
}
|
||||
else if (clip->rightedge)
|
||||
{
|
||||
r_rightclipped = true;
|
||||
r_rightexit = clipvert;
|
||||
}
|
||||
|
||||
R_ClipEdge (pv0, &clipvert, clip->next);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point 0 is clipped
|
||||
if (d1 < 0)
|
||||
{
|
||||
// both points are clipped
|
||||
// we do cache fully clipped edges
|
||||
if (!r_leftclipped)
|
||||
cacheoffset = FULLY_CLIPPED_CACHED |
|
||||
(r_framecount & FRAMECOUNT_MASK);
|
||||
return;
|
||||
}
|
||||
|
||||
// only point 0 is clipped
|
||||
r_lastvertvalid = false;
|
||||
|
||||
// we don't cache partially clipped edges
|
||||
cacheoffset = 0x7FFFFFFF;
|
||||
|
||||
f = d0 / (d0 - d1);
|
||||
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]);
|
||||
|
||||
if (clip->leftedge)
|
||||
{
|
||||
r_leftclipped = true;
|
||||
r_leftenter = clipvert;
|
||||
}
|
||||
else if (clip->rightedge)
|
||||
{
|
||||
r_rightclipped = true;
|
||||
r_rightenter = clipvert;
|
||||
}
|
||||
|
||||
R_ClipEdge (&clipvert, pv1, clip->next);
|
||||
return;
|
||||
}
|
||||
} while ((clip = clip->next) != NULL);
|
||||
}
|
||||
|
||||
// add the edge
|
||||
R_EmitEdge (pv0, pv1);
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_EmitCachedEdge
|
||||
================
|
||||
*/
|
||||
void R_EmitCachedEdge (void)
|
||||
{
|
||||
edge_t *pedge_t;
|
||||
|
||||
pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset);
|
||||
|
||||
if (!pedge_t->surfs[0])
|
||||
pedge_t->surfs[0] = surface_p - surfaces;
|
||||
else
|
||||
pedge_t->surfs[1] = surface_p - surfaces;
|
||||
|
||||
if (pedge_t->nearzi > r_nearzi) // for mipmap finding
|
||||
r_nearzi = pedge_t->nearzi;
|
||||
|
||||
r_emitted = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderFace
|
||||
================
|
||||
*/
|
||||
void R_RenderFace (msurface_t *fa, int clipflags)
|
||||
{
|
||||
int i, lindex;
|
||||
unsigned mask;
|
||||
mplane_t *pplane;
|
||||
float distinv;
|
||||
vec3_t p_normal;
|
||||
medge_t *pedges, tedge;
|
||||
clipplane_t *pclip;
|
||||
|
||||
// translucent surfaces are not drawn by the edge renderer
|
||||
if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
|
||||
{
|
||||
fa->nextalphasurface = r_alpha_surfaces;
|
||||
r_alpha_surfaces = fa;
|
||||
return;
|
||||
}
|
||||
|
||||
// sky surfaces encountered in the world will cause the
|
||||
// environment box surfaces to be emited
|
||||
if ( fa->texinfo->flags & SURF_SKY )
|
||||
{
|
||||
R_EmitSkyBox ();
|
||||
return;
|
||||
}
|
||||
|
||||
// skip out if no more surfs
|
||||
if ((surface_p) >= surf_max)
|
||||
{
|
||||
r_outofsurfaces++;
|
||||
return;
|
||||
}
|
||||
|
||||
// ditto if not enough edges left, or switch to auxedges if possible
|
||||
if ((edge_p + fa->numedges + 4) >= edge_max)
|
||||
{
|
||||
r_outofedges += fa->numedges;
|
||||
return;
|
||||
}
|
||||
|
||||
c_faceclip++;
|
||||
|
||||
// set up clip planes
|
||||
pclip = NULL;
|
||||
|
||||
for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
|
||||
{
|
||||
if (clipflags & mask)
|
||||
{
|
||||
view_clipplanes[i].next = pclip;
|
||||
pclip = &view_clipplanes[i];
|
||||
}
|
||||
}
|
||||
|
||||
// push the edges through
|
||||
r_emitted = 0;
|
||||
r_nearzi = 0;
|
||||
r_nearzionly = false;
|
||||
makeleftedge = makerightedge = false;
|
||||
pedges = currentmodel->edges;
|
||||
r_lastvertvalid = false;
|
||||
|
||||
for (i=0 ; i<fa->numedges ; i++)
|
||||
{
|
||||
lindex = currentmodel->surfedges[fa->firstedge + i];
|
||||
|
||||
if (lindex > 0)
|
||||
{
|
||||
r_pedge = &pedges[lindex];
|
||||
|
||||
// if the edge is cached, we can just reuse the edge
|
||||
if (!insubmodel)
|
||||
{
|
||||
if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
|
||||
{
|
||||
if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
|
||||
r_framecount)
|
||||
{
|
||||
r_lastvertvalid = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((((unsigned long)edge_p - (unsigned long)r_edges) >
|
||||
r_pedge->cachededgeoffset) &&
|
||||
(((edge_t *)((unsigned long)r_edges +
|
||||
r_pedge->cachededgeoffset))->owner == r_pedge))
|
||||
{
|
||||
R_EmitCachedEdge ();
|
||||
r_lastvertvalid = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assume it's cacheable
|
||||
cacheoffset = (byte *)edge_p - (byte *)r_edges;
|
||||
r_leftclipped = r_rightclipped = false;
|
||||
R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
|
||||
&r_pcurrentvertbase[r_pedge->v[1]],
|
||||
pclip);
|
||||
r_pedge->cachededgeoffset = cacheoffset;
|
||||
|
||||
if (r_leftclipped)
|
||||
makeleftedge = true;
|
||||
if (r_rightclipped)
|
||||
makerightedge = true;
|
||||
r_lastvertvalid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
lindex = -lindex;
|
||||
r_pedge = &pedges[lindex];
|
||||
// if the edge is cached, we can just reuse the edge
|
||||
if (!insubmodel)
|
||||
{
|
||||
if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
|
||||
{
|
||||
if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
|
||||
r_framecount)
|
||||
{
|
||||
r_lastvertvalid = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's cached if the cached edge is valid and is owned
|
||||
// by this medge_t
|
||||
if ((((unsigned long)edge_p - (unsigned long)r_edges) >
|
||||
r_pedge->cachededgeoffset) &&
|
||||
(((edge_t *)((unsigned long)r_edges +
|
||||
r_pedge->cachededgeoffset))->owner == r_pedge))
|
||||
{
|
||||
R_EmitCachedEdge ();
|
||||
r_lastvertvalid = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assume it's cacheable
|
||||
cacheoffset = (byte *)edge_p - (byte *)r_edges;
|
||||
r_leftclipped = r_rightclipped = false;
|
||||
R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
|
||||
&r_pcurrentvertbase[r_pedge->v[0]],
|
||||
pclip);
|
||||
r_pedge->cachededgeoffset = cacheoffset;
|
||||
|
||||
if (r_leftclipped)
|
||||
makeleftedge = true;
|
||||
if (r_rightclipped)
|
||||
makerightedge = true;
|
||||
r_lastvertvalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if there was a clip off the left edge, add that edge too
|
||||
// FIXME: faster to do in screen space?
|
||||
// FIXME: share clipped edges?
|
||||
if (makeleftedge)
|
||||
{
|
||||
r_pedge = &tedge;
|
||||
r_lastvertvalid = false;
|
||||
R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
|
||||
}
|
||||
|
||||
// if there was a clip off the right edge, get the right r_nearzi
|
||||
if (makerightedge)
|
||||
{
|
||||
r_pedge = &tedge;
|
||||
r_lastvertvalid = false;
|
||||
r_nearzionly = true;
|
||||
R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
|
||||
}
|
||||
|
||||
// if no edges made it out, return without posting the surface
|
||||
if (!r_emitted)
|
||||
return;
|
||||
|
||||
r_polycount++;
|
||||
|
||||
surface_p->msurf = fa;
|
||||
surface_p->nearzi = r_nearzi;
|
||||
surface_p->flags = fa->flags;
|
||||
surface_p->insubmodel = insubmodel;
|
||||
surface_p->spanstate = 0;
|
||||
surface_p->entity = currententity;
|
||||
surface_p->key = r_currentkey++;
|
||||
surface_p->spans = NULL;
|
||||
|
||||
pplane = fa->plane;
|
||||
// FIXME: cache this?
|
||||
TransformVector (pplane->normal, p_normal);
|
||||
// FIXME: cache this?
|
||||
distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
|
||||
|
||||
surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
|
||||
surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
|
||||
surface_p->d_ziorigin = p_normal[2] * distinv -
|
||||
xcenter * surface_p->d_zistepu -
|
||||
ycenter * surface_p->d_zistepv;
|
||||
|
||||
surface_p++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderBmodelFace
|
||||
================
|
||||
*/
|
||||
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
|
||||
{
|
||||
int i;
|
||||
unsigned mask;
|
||||
mplane_t *pplane;
|
||||
float distinv;
|
||||
vec3_t p_normal;
|
||||
medge_t tedge;
|
||||
clipplane_t *pclip;
|
||||
|
||||
if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
|
||||
{
|
||||
psurf->nextalphasurface = r_alpha_surfaces;
|
||||
r_alpha_surfaces = psurf;
|
||||
return;
|
||||
}
|
||||
|
||||
// skip out if no more surfs
|
||||
if (surface_p >= surf_max)
|
||||
{
|
||||
r_outofsurfaces++;
|
||||
return;
|
||||
}
|
||||
|
||||
// ditto if not enough edges left, or switch to auxedges if possible
|
||||
if ((edge_p + psurf->numedges + 4) >= edge_max)
|
||||
{
|
||||
r_outofedges += psurf->numedges;
|
||||
return;
|
||||
}
|
||||
|
||||
c_faceclip++;
|
||||
|
||||
// this is a dummy to give the caching mechanism someplace to write to
|
||||
r_pedge = &tedge;
|
||||
|
||||
// set up clip planes
|
||||
pclip = NULL;
|
||||
|
||||
for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
|
||||
{
|
||||
if (r_clipflags & mask)
|
||||
{
|
||||
view_clipplanes[i].next = pclip;
|
||||
pclip = &view_clipplanes[i];
|
||||
}
|
||||
}
|
||||
|
||||
// push the edges through
|
||||
r_emitted = 0;
|
||||
r_nearzi = 0;
|
||||
r_nearzionly = false;
|
||||
makeleftedge = makerightedge = false;
|
||||
// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
|
||||
// can be used?
|
||||
r_lastvertvalid = false;
|
||||
|
||||
for ( ; pedges ; pedges = pedges->pnext)
|
||||
{
|
||||
r_leftclipped = r_rightclipped = false;
|
||||
R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
|
||||
|
||||
if (r_leftclipped)
|
||||
makeleftedge = true;
|
||||
if (r_rightclipped)
|
||||
makerightedge = true;
|
||||
}
|
||||
|
||||
// if there was a clip off the left edge, add that edge too
|
||||
// FIXME: faster to do in screen space?
|
||||
// FIXME: share clipped edges?
|
||||
if (makeleftedge)
|
||||
{
|
||||
r_pedge = &tedge;
|
||||
R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
|
||||
}
|
||||
|
||||
// if there was a clip off the right edge, get the right r_nearzi
|
||||
if (makerightedge)
|
||||
{
|
||||
r_pedge = &tedge;
|
||||
r_nearzionly = true;
|
||||
R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
|
||||
}
|
||||
|
||||
// if no edges made it out, return without posting the surface
|
||||
if (!r_emitted)
|
||||
return;
|
||||
|
||||
r_polycount++;
|
||||
|
||||
surface_p->msurf = psurf;
|
||||
surface_p->nearzi = r_nearzi;
|
||||
surface_p->flags = psurf->flags;
|
||||
surface_p->insubmodel = true;
|
||||
surface_p->spanstate = 0;
|
||||
surface_p->entity = currententity;
|
||||
surface_p->key = r_currentbkey;
|
||||
surface_p->spans = NULL;
|
||||
|
||||
pplane = psurf->plane;
|
||||
// FIXME: cache this?
|
||||
TransformVector (pplane->normal, p_normal);
|
||||
// FIXME: cache this?
|
||||
distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
|
||||
|
||||
surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
|
||||
surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
|
||||
surface_p->d_ziorigin = p_normal[2] * distinv -
|
||||
xcenter * surface_p->d_zistepu -
|
||||
ycenter * surface_p->d_zistepv;
|
||||
|
||||
surface_p++;
|
||||
}
|
||||
|
||||
591
ref_soft/r_scan.c
Normal file
591
ref_soft/r_scan.c
Normal file
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// d_scan.c
|
||||
//
|
||||
// Portable C scan-level rasterization code, all pixel depths.
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
unsigned char *r_turb_pbase, *r_turb_pdest;
|
||||
fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
|
||||
int *r_turb_turb;
|
||||
int r_turb_spancount;
|
||||
|
||||
void D_DrawTurbulent8Span (void);
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
D_WarpScreen
|
||||
|
||||
this performs a slight compression of the screen at the same time as
|
||||
the sine warp, to keep the edges from wrapping
|
||||
=============
|
||||
*/
|
||||
void D_WarpScreen (void)
|
||||
{
|
||||
int w, h;
|
||||
int u,v, u2, v2;
|
||||
byte *dest;
|
||||
int *turb;
|
||||
int *col;
|
||||
byte **row;
|
||||
|
||||
static int cached_width, cached_height;
|
||||
static byte *rowptr[1200+AMP2*2];
|
||||
static int column[1600+AMP2*2];
|
||||
|
||||
//
|
||||
// these are constant over resolutions, and can be saved
|
||||
//
|
||||
w = r_newrefdef.width;
|
||||
h = r_newrefdef.height;
|
||||
if (w != cached_width || h != cached_height)
|
||||
{
|
||||
cached_width = w;
|
||||
cached_height = h;
|
||||
for (v=0 ; v<h+AMP2*2 ; v++)
|
||||
{
|
||||
v2 = (int)((float)v/(h + AMP2 * 2) * r_refdef.vrect.height);
|
||||
rowptr[v] = r_warpbuffer + (WARP_WIDTH * v2);
|
||||
}
|
||||
|
||||
for (u=0 ; u<w+AMP2*2 ; u++)
|
||||
{
|
||||
u2 = (int)((float)u/(w + AMP2 * 2) * r_refdef.vrect.width);
|
||||
column[u] = u2;
|
||||
}
|
||||
}
|
||||
|
||||
turb = intsintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
|
||||
dest = vid.buffer + r_newrefdef.y * vid.rowbytes + r_newrefdef.x;
|
||||
|
||||
for (v=0 ; v<h ; v++, dest += vid.rowbytes)
|
||||
{
|
||||
col = &column[turb[v]];
|
||||
row = &rowptr[v];
|
||||
for (u=0 ; u<w ; u+=4)
|
||||
{
|
||||
dest[u+0] = row[turb[u+0]][col[u+0]];
|
||||
dest[u+1] = row[turb[u+1]][col[u+1]];
|
||||
dest[u+2] = row[turb[u+2]][col[u+2]];
|
||||
dest[u+3] = row[turb[u+3]][col[u+3]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
=============
|
||||
D_DrawTurbulent8Span
|
||||
=============
|
||||
*/
|
||||
void D_DrawTurbulent8Span (void)
|
||||
{
|
||||
int sturb, tturb;
|
||||
|
||||
do
|
||||
{
|
||||
sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
|
||||
tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
|
||||
*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
|
||||
r_turb_s += r_turb_sstep;
|
||||
r_turb_t += r_turb_tstep;
|
||||
} while (--r_turb_spancount > 0);
|
||||
}
|
||||
|
||||
#endif // !id386
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
Turbulent8
|
||||
=============
|
||||
*/
|
||||
void Turbulent8 (espan_t *pspan)
|
||||
{
|
||||
int count;
|
||||
fixed16_t snext, tnext;
|
||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
||||
float sdivz16stepu, tdivz16stepu, zi16stepu;
|
||||
|
||||
r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
|
||||
|
||||
r_turb_sstep = 0; // keep compiler happy
|
||||
r_turb_tstep = 0; // ditto
|
||||
|
||||
r_turb_pbase = (unsigned char *)cacheblock;
|
||||
|
||||
sdivz16stepu = d_sdivzstepu * 16;
|
||||
tdivz16stepu = d_tdivzstepu * 16;
|
||||
zi16stepu = d_zistepu * 16;
|
||||
|
||||
do
|
||||
{
|
||||
r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
|
||||
(r_screenwidth * pspan->v) + pspan->u);
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
// 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
|
||||
|
||||
r_turb_s = (int)(sdivz * z) + sadjust;
|
||||
if (r_turb_s > bbextents)
|
||||
r_turb_s = bbextents;
|
||||
else if (r_turb_s < 0)
|
||||
r_turb_s = 0;
|
||||
|
||||
r_turb_t = (int)(tdivz * z) + tadjust;
|
||||
if (r_turb_t > bbextentt)
|
||||
r_turb_t = bbextentt;
|
||||
else if (r_turb_t < 0)
|
||||
r_turb_t = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// calculate s and t at the far end of the span
|
||||
if (count >= 16)
|
||||
r_turb_spancount = 16;
|
||||
else
|
||||
r_turb_spancount = count;
|
||||
|
||||
count -= r_turb_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 += sdivz16stepu;
|
||||
tdivz += tdivz16stepu;
|
||||
zi += zi16stepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 16)
|
||||
snext = 16; // 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 < 16)
|
||||
tnext = 16; // guard against round-off error on <0 steps
|
||||
|
||||
r_turb_sstep = (snext - r_turb_s) >> 4;
|
||||
r_turb_tstep = (tnext - r_turb_t) >> 4;
|
||||
}
|
||||
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)(r_turb_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 < 16)
|
||||
snext = 16; // 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 < 16)
|
||||
tnext = 16; // guard against round-off error on <0 steps
|
||||
|
||||
if (r_turb_spancount > 1)
|
||||
{
|
||||
r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
|
||||
r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
r_turb_s = r_turb_s & ((CYCLE<<16)-1);
|
||||
r_turb_t = r_turb_t & ((CYCLE<<16)-1);
|
||||
|
||||
D_DrawTurbulent8Span ();
|
||||
|
||||
r_turb_s = snext;
|
||||
r_turb_t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
} while ((pspan = pspan->pnext) != NULL);
|
||||
}
|
||||
|
||||
//====================
|
||||
//PGM
|
||||
/*
|
||||
=============
|
||||
NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures
|
||||
but the turbulence is automatically 0.
|
||||
=============
|
||||
*/
|
||||
void NonTurbulent8 (espan_t *pspan)
|
||||
{
|
||||
int count;
|
||||
fixed16_t snext, tnext;
|
||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
||||
float sdivz16stepu, tdivz16stepu, zi16stepu;
|
||||
|
||||
// r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
|
||||
r_turb_turb = blanktable;
|
||||
|
||||
r_turb_sstep = 0; // keep compiler happy
|
||||
r_turb_tstep = 0; // ditto
|
||||
|
||||
r_turb_pbase = (unsigned char *)cacheblock;
|
||||
|
||||
sdivz16stepu = d_sdivzstepu * 16;
|
||||
tdivz16stepu = d_tdivzstepu * 16;
|
||||
zi16stepu = d_zistepu * 16;
|
||||
|
||||
do
|
||||
{
|
||||
r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
|
||||
(r_screenwidth * pspan->v) + pspan->u);
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
// 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
|
||||
|
||||
r_turb_s = (int)(sdivz * z) + sadjust;
|
||||
if (r_turb_s > bbextents)
|
||||
r_turb_s = bbextents;
|
||||
else if (r_turb_s < 0)
|
||||
r_turb_s = 0;
|
||||
|
||||
r_turb_t = (int)(tdivz * z) + tadjust;
|
||||
if (r_turb_t > bbextentt)
|
||||
r_turb_t = bbextentt;
|
||||
else if (r_turb_t < 0)
|
||||
r_turb_t = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// calculate s and t at the far end of the span
|
||||
if (count >= 16)
|
||||
r_turb_spancount = 16;
|
||||
else
|
||||
r_turb_spancount = count;
|
||||
|
||||
count -= r_turb_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 += sdivz16stepu;
|
||||
tdivz += tdivz16stepu;
|
||||
zi += zi16stepu;
|
||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
||||
|
||||
snext = (int)(sdivz * z) + sadjust;
|
||||
if (snext > bbextents)
|
||||
snext = bbextents;
|
||||
else if (snext < 16)
|
||||
snext = 16; // 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 < 16)
|
||||
tnext = 16; // guard against round-off error on <0 steps
|
||||
|
||||
r_turb_sstep = (snext - r_turb_s) >> 4;
|
||||
r_turb_tstep = (tnext - r_turb_t) >> 4;
|
||||
}
|
||||
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)(r_turb_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 < 16)
|
||||
snext = 16; // 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 < 16)
|
||||
tnext = 16; // guard against round-off error on <0 steps
|
||||
|
||||
if (r_turb_spancount > 1)
|
||||
{
|
||||
r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
|
||||
r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
r_turb_s = r_turb_s & ((CYCLE<<16)-1);
|
||||
r_turb_t = r_turb_t & ((CYCLE<<16)-1);
|
||||
|
||||
D_DrawTurbulent8Span ();
|
||||
|
||||
r_turb_s = snext;
|
||||
r_turb_t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
} while ((pspan = pspan->pnext) != NULL);
|
||||
}
|
||||
//PGM
|
||||
//====================
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
=============
|
||||
D_DrawSpans16
|
||||
|
||||
FIXME: actually make this subdivide by 16 instead of 8!!!
|
||||
=============
|
||||
*/
|
||||
void D_DrawSpans16 (espan_t *pspan)
|
||||
{
|
||||
int count, spancount;
|
||||
unsigned char *pbase, *pdest;
|
||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
||||
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
||||
|
||||
sstep = 0; // keep compiler happy
|
||||
tstep = 0; // ditto
|
||||
|
||||
pbase = (unsigned char *)cacheblock;
|
||||
|
||||
sdivz8stepu = d_sdivzstepu * 8;
|
||||
tdivz8stepu = d_tdivzstepu * 8;
|
||||
zi8stepu = d_zistepu * 8;
|
||||
|
||||
do
|
||||
{
|
||||
pdest = (unsigned char *)((byte *)d_viewbuffer +
|
||||
(r_screenwidth * pspan->v) + pspan->u);
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
// 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
|
||||
|
||||
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
|
||||
{
|
||||
*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
|
||||
s += sstep;
|
||||
t += tstep;
|
||||
} while (--spancount > 0);
|
||||
|
||||
s = snext;
|
||||
t = tnext;
|
||||
|
||||
} while (count > 0);
|
||||
|
||||
} while ((pspan = pspan->pnext) != NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
=============
|
||||
D_DrawZSpans
|
||||
=============
|
||||
*/
|
||||
void D_DrawZSpans (espan_t *pspan)
|
||||
{
|
||||
int count, doublecount, izistep;
|
||||
int izi;
|
||||
short *pdest;
|
||||
unsigned ltemp;
|
||||
float zi;
|
||||
float du, dv;
|
||||
|
||||
// FIXME: check for clamping/range problems
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
|
||||
|
||||
do
|
||||
{
|
||||
pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
|
||||
|
||||
count = pspan->count;
|
||||
|
||||
// calculate the initial 1/z
|
||||
du = (float)pspan->u;
|
||||
dv = (float)pspan->v;
|
||||
|
||||
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
|
||||
// we count on FP exceptions being turned off to avoid range problems
|
||||
izi = (int)(zi * 0x8000 * 0x10000);
|
||||
|
||||
if ((long)pdest & 0x02)
|
||||
{
|
||||
*pdest++ = (short)(izi >> 16);
|
||||
izi += izistep;
|
||||
count--;
|
||||
}
|
||||
|
||||
if ((doublecount = count >> 1) > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
ltemp = izi >> 16;
|
||||
izi += izistep;
|
||||
ltemp |= izi & 0xFFFF0000;
|
||||
izi += izistep;
|
||||
*(int *)pdest = ltemp;
|
||||
pdest += 2;
|
||||
} while (--doublecount > 0);
|
||||
}
|
||||
|
||||
if (count & 1)
|
||||
*pdest = (short)(izi >> 16);
|
||||
|
||||
} while ((pspan = pspan->pnext) != NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
73
ref_soft/r_scana.asm
Normal file
73
ref_soft/r_scana.asm
Normal file
@@ -0,0 +1,73 @@
|
||||
.386P
|
||||
.model FLAT
|
||||
;
|
||||
; d_scana.s
|
||||
; x86 assembly-language turbulent texture mapping code
|
||||
;
|
||||
|
||||
include qasm.inc
|
||||
include d_if.inc
|
||||
|
||||
if id386
|
||||
|
||||
_DATA SEGMENT
|
||||
|
||||
_DATA ENDS
|
||||
_TEXT SEGMENT
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; turbulent texture mapping code
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
public _D_DrawTurbulent8Span
|
||||
_D_DrawTurbulent8Span:
|
||||
push ebp ; preserve caller's stack frame pointer
|
||||
push esi ; preserve register variables
|
||||
push edi
|
||||
push ebx
|
||||
|
||||
mov esi,ds:dword ptr[_r_turb_s]
|
||||
mov ecx,ds:dword ptr[_r_turb_t]
|
||||
mov edi,ds:dword ptr[_r_turb_pdest]
|
||||
mov ebx,ds:dword ptr[_r_turb_spancount]
|
||||
|
||||
Llp:
|
||||
mov eax,ecx
|
||||
mov edx,esi
|
||||
sar eax,16
|
||||
mov ebp,ds:dword ptr[_r_turb_turb]
|
||||
sar edx,16
|
||||
and eax,offset CYCLE-1
|
||||
and edx,offset CYCLE-1
|
||||
mov eax,ds:dword ptr[ebp+eax*4]
|
||||
mov edx,ds:dword ptr[ebp+edx*4]
|
||||
add eax,esi
|
||||
sar eax,16
|
||||
add edx,ecx
|
||||
sar edx,16
|
||||
and eax,offset TURB_TEX_SIZE-1
|
||||
and edx,offset TURB_TEX_SIZE-1
|
||||
shl edx,6
|
||||
mov ebp,ds:dword ptr[_r_turb_pbase]
|
||||
add edx,eax
|
||||
inc edi
|
||||
add esi,ds:dword ptr[_r_turb_sstep]
|
||||
add ecx,ds:dword ptr[_r_turb_tstep]
|
||||
mov dl,ds:byte ptr[ebp+edx*1]
|
||||
dec ebx
|
||||
mov ds:byte ptr[-1+edi],dl
|
||||
jnz Llp
|
||||
|
||||
mov ds:dword ptr[_r_turb_pdest],edi
|
||||
|
||||
pop ebx ; restore register variables
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp ; restore caller's stack frame pointer
|
||||
ret
|
||||
|
||||
|
||||
_TEXT ENDS
|
||||
endif ;id386
|
||||
END
|
||||
884
ref_soft/r_spr8.asm
Normal file
884
ref_soft/r_spr8.asm
Normal file
@@ -0,0 +1,884 @@
|
||||
.386P
|
||||
.model FLAT
|
||||
;
|
||||
; d_spr8.s
|
||||
; x86 assembly-language horizontal 8-bpp transparent span-drawing code.
|
||||
;
|
||||
|
||||
include qasm.inc
|
||||
include d_if.inc
|
||||
|
||||
if id386
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; 8-bpp horizontal span drawing code for polygons, with transparency.
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
_TEXT SEGMENT
|
||||
|
||||
; out-of-line, rarely-needed clamping code
|
||||
|
||||
LClampHigh0:
|
||||
mov esi,ds:dword ptr[_bbextents]
|
||||
jmp LClampReentry0
|
||||
LClampHighOrLow0:
|
||||
jg LClampHigh0
|
||||
xor esi,esi
|
||||
jmp LClampReentry0
|
||||
|
||||
LClampHigh1:
|
||||
mov edx,ds:dword ptr[_bbextentt]
|
||||
jmp LClampReentry1
|
||||
LClampHighOrLow1:
|
||||
jg LClampHigh1
|
||||
xor edx,edx
|
||||
jmp LClampReentry1
|
||||
|
||||
LClampLow2:
|
||||
mov ebp,2048
|
||||
jmp LClampReentry2
|
||||
LClampHigh2:
|
||||
mov ebp,ds:dword ptr[_bbextents]
|
||||
jmp LClampReentry2
|
||||
|
||||
LClampLow3:
|
||||
mov ecx,2048
|
||||
jmp LClampReentry3
|
||||
LClampHigh3:
|
||||
mov ecx,ds:dword ptr[_bbextentt]
|
||||
jmp LClampReentry3
|
||||
|
||||
LClampLow4:
|
||||
mov eax,2048
|
||||
jmp LClampReentry4
|
||||
LClampHigh4:
|
||||
mov eax,ds:dword ptr[_bbextents]
|
||||
jmp LClampReentry4
|
||||
|
||||
LClampLow5:
|
||||
mov ebx,2048
|
||||
jmp LClampReentry5
|
||||
LClampHigh5:
|
||||
mov ebx,ds:dword ptr[_bbextentt]
|
||||
jmp LClampReentry5
|
||||
|
||||
|
||||
pspans equ 4+16
|
||||
|
||||
align 4
|
||||
public _D_SpriteDrawSpansXXX
|
||||
_D_SpriteDrawSpansXXX:
|
||||
push ebp ; preserve caller's stack frame
|
||||
push edi
|
||||
push esi ; preserve register variables
|
||||
push 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?
|
||||
fld ds:dword ptr[_d_sdivzstepu]
|
||||
fmul ds:dword ptr[fp_8]
|
||||
mov edx,ds:dword ptr[_cacheblock]
|
||||
fld ds:dword ptr[_d_tdivzstepu]
|
||||
fmul ds:dword ptr[fp_8]
|
||||
mov ebx,ds:dword ptr[pspans+esp] ; point to the first span descriptor
|
||||
fld ds:dword ptr[_d_zistepu]
|
||||
fmul ds:dword ptr[fp_8]
|
||||
mov ds:dword ptr[pbase],edx ; pbase = cacheblock
|
||||
fld ds:dword ptr[_d_zistepu]
|
||||
fmul ds:dword ptr[fp_64kx64k]
|
||||
fxch st(3)
|
||||
fstp ds:dword ptr[sdivz8stepu]
|
||||
fstp ds:dword ptr[zi8stepu]
|
||||
fstp ds:dword ptr[tdivz8stepu]
|
||||
fistp ds:dword ptr[izistep]
|
||||
mov eax,ds:dword ptr[izistep]
|
||||
ror eax,16 ; put upper 16 bits in low word
|
||||
mov ecx,ds:dword ptr[sspan_t_count+ebx]
|
||||
mov ds:dword ptr[izistep],eax
|
||||
|
||||
cmp ecx,0
|
||||
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?
|
||||
fild ds:dword ptr[sspan_t_v+ebx]
|
||||
fild ds:dword ptr[sspan_t_u+ebx]
|
||||
|
||||
fld st(1) ; dv | du | dv
|
||||
fmul ds:dword ptr[_d_sdivzstepv] ; dv*d_sdivzstepv | du | dv
|
||||
fld st(1) ; du | dv*d_sdivzstepv | du | dv
|
||||
fmul ds:dword ptr[_d_sdivzstepu] ; du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
|
||||
fld st(2) ; du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
|
||||
fmul ds:dword ptr[_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(2),st(0) ; 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
|
||||
fmul ds:dword ptr[_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
|
||||
fadd ds:dword ptr[_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
|
||||
fmul ds:dword ptr[_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(2),st(0) ; 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
|
||||
fmul ds:dword ptr[_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
|
||||
fadd ds:dword ptr[_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(1),st(0) ; dv*d_zistepv + du*d_zistepu | t/z | s/z
|
||||
|
||||
fld ds:dword ptr[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
|
||||
fadd ds:dword ptr[_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?
|
||||
fmul ds:dword ptr[fp_64kx64k]
|
||||
fxch st(1)
|
||||
|
||||
;
|
||||
; calculate and clamp s & t
|
||||
;
|
||||
fdiv st(2),st(0) ; 1/z | z*64k | t/z | s/z
|
||||
fxch st(1)
|
||||
|
||||
fistp ds:dword ptr[izi] ; 0.32 fixed-point 1/z
|
||||
mov ebp,ds:dword ptr[izi]
|
||||
|
||||
;
|
||||
; set pz to point to the first z-buffer pixel in the span
|
||||
;
|
||||
ror ebp,16 ; put upper 16 bits in low word
|
||||
mov eax,ds:dword ptr[sspan_t_v+ebx]
|
||||
mov ds:dword ptr[izi],ebp
|
||||
mov ebp,ds:dword ptr[sspan_t_u+ebx]
|
||||
imul ds:dword ptr[_d_zrowbytes]
|
||||
shl ebp,1 ; a word per pixel
|
||||
add eax,ds:dword ptr[_d_pzbuffer]
|
||||
add eax,ebp
|
||||
mov ds:dword ptr[pz],eax
|
||||
|
||||
;
|
||||
; point %edi to the first pixel in the span
|
||||
;
|
||||
mov ebp,ds:dword ptr[_d_viewbuffer]
|
||||
mov eax,ds:dword ptr[sspan_t_v+ebx]
|
||||
push ebx ; preserve spans pointer
|
||||
mov edx,ds:dword ptr[_tadjust]
|
||||
mov esi,ds:dword ptr[_sadjust]
|
||||
mov edi,ds:dword ptr[_d_scantable+eax*4] ; v * screenwidth
|
||||
add edi,ebp
|
||||
mov ebp,ds:dword ptr[sspan_t_u+ebx]
|
||||
add edi,ebp ; pdest = &pdestspan[scans->u];
|
||||
|
||||
;
|
||||
; now start the FDIV for the end of the span
|
||||
;
|
||||
cmp ecx,8
|
||||
ja LSetupNotLast1
|
||||
|
||||
dec ecx
|
||||
jz LCleanup1 ; if only one pixel, no need to start an FDIV
|
||||
mov ds:dword ptr[spancountminus1],ecx
|
||||
|
||||
; 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(0),st(4) ; s | z*64k | 1/z | t/z | s/z
|
||||
fxch st(1) ; z*64k | s | 1/z | t/z | s/z
|
||||
fmul st(0),st(3) ; t | s | 1/z | t/z | s/z
|
||||
fxch st(1) ; s | t | 1/z | t/z | s/z
|
||||
fistp ds:dword ptr[s] ; 1/z | t | t/z | s/z
|
||||
fistp ds:dword ptr[t] ; 1/z | t/z | s/z
|
||||
|
||||
fild ds:dword ptr[spancountminus1]
|
||||
|
||||
fld ds:dword ptr[_d_tdivzstepu] ; _d_tdivzstepu | spancountminus1
|
||||
fld ds:dword ptr[_d_zistepu] ; _d_zistepu | _d_tdivzstepu | spancountminus1
|
||||
fmul st(0),st(2) ; _d_zistepu*scm1 | _d_tdivzstepu | scm1
|
||||
fxch st(1) ; _d_tdivzstepu | _d_zistepu*scm1 | scm1
|
||||
fmul st(0),st(2) ; _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
|
||||
fxch st(2) ; scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1
|
||||
fmul ds:dword ptr[_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(3),st(0) ; _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
|
||||
fxch st(1) ; _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
|
||||
faddp st(3),st(0) ; _d_sdivzstepu*scm1
|
||||
faddp st(3),st(0)
|
||||
|
||||
fld ds:dword ptr[fp_64k]
|
||||
fdiv st(0),st(1) ; 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(0),st(4) ; s | z*64k | 1/z | t/z | s/z
|
||||
fxch st(1) ; z*64k | s | 1/z | t/z | s/z
|
||||
fmul st(0),st(3) ; t | s | 1/z | t/z | s/z
|
||||
fxch st(1) ; s | t | 1/z | t/z | s/z
|
||||
fistp ds:dword ptr[s] ; 1/z | t | t/z | s/z
|
||||
fistp ds:dword ptr[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(0),st(4) ; s | z*64k | 1/z | t/z | s/z
|
||||
fxch st(1) ; z*64k | s | 1/z | t/z | s/z
|
||||
fmul st(0),st(3) ; t | s | 1/z | t/z | s/z
|
||||
fxch st(1) ; s | t | 1/z | t/z | s/z
|
||||
fistp ds:dword ptr[s] ; 1/z | t | t/z | s/z
|
||||
fistp ds:dword ptr[t] ; 1/z | t/z | s/z
|
||||
|
||||
fadd ds:dword ptr[zi8stepu]
|
||||
fxch st(2)
|
||||
fadd ds:dword ptr[sdivz8stepu]
|
||||
fxch st(2)
|
||||
fld ds:dword ptr[tdivz8stepu]
|
||||
faddp st(2),st(0)
|
||||
fld ds:dword ptr[fp_64k]
|
||||
fdiv st(0),st(1) ; z = 1/1/z
|
||||
; this is what we've gone to all this trouble to
|
||||
; overlap
|
||||
LFDIVInFlight1:
|
||||
|
||||
add esi,ds:dword ptr[s]
|
||||
add edx,ds:dword ptr[t]
|
||||
mov ebx,ds:dword ptr[_bbextents]
|
||||
mov ebp,ds:dword ptr[_bbextentt]
|
||||
cmp esi,ebx
|
||||
ja LClampHighOrLow0
|
||||
LClampReentry0:
|
||||
mov ds:dword ptr[s],esi
|
||||
mov ebx,ds:dword ptr[pbase]
|
||||
shl esi,16
|
||||
cmp edx,ebp
|
||||
mov ds:dword ptr[sfracf],esi
|
||||
ja LClampHighOrLow1
|
||||
LClampReentry1:
|
||||
mov ds:dword ptr[t],edx
|
||||
mov esi,ds:dword ptr[s] ; sfrac = scans->sfrac;
|
||||
shl edx,16
|
||||
mov eax,ds:dword ptr[t] ; tfrac = scans->tfrac;
|
||||
sar esi,16
|
||||
mov ds:dword ptr[tfracf],edx
|
||||
|
||||
;
|
||||
; calculate the texture starting address
|
||||
;
|
||||
sar eax,16
|
||||
add esi,ebx
|
||||
imul eax,ds:dword ptr[_cachewidth] ; (tfrac >> 16) * cachewidth
|
||||
add esi,eax ; psource = pbase + (sfrac >> 16) +
|
||||
; ((tfrac >> 16) * cachewidth);
|
||||
|
||||
;
|
||||
; determine whether last span or not
|
||||
;
|
||||
cmp ecx,8
|
||||
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(0),st(4) ; s = s/z * z
|
||||
fxch st(1)
|
||||
fmul st(0),st(3) ; t = t/z * z
|
||||
fxch st(1)
|
||||
fistp ds:dword ptr[snext]
|
||||
fistp ds:dword ptr[tnext]
|
||||
mov eax,ds:dword ptr[snext]
|
||||
mov edx,ds:dword ptr[tnext]
|
||||
|
||||
sub ecx,8 ; count off this segments' pixels
|
||||
mov ebp,ds:dword ptr[_sadjust]
|
||||
push ecx ; remember count of remaining pixels
|
||||
mov ecx,ds:dword ptr[_tadjust]
|
||||
|
||||
add ebp,eax
|
||||
add ecx,edx
|
||||
|
||||
mov eax,ds:dword ptr[_bbextents]
|
||||
mov edx,ds:dword ptr[_bbextentt]
|
||||
|
||||
cmp ebp,2048
|
||||
jl LClampLow2
|
||||
cmp ebp,eax
|
||||
ja LClampHigh2
|
||||
LClampReentry2:
|
||||
|
||||
cmp ecx,2048
|
||||
jl LClampLow3
|
||||
cmp ecx,edx
|
||||
ja LClampHigh3
|
||||
LClampReentry3:
|
||||
|
||||
mov ds:dword ptr[snext],ebp
|
||||
mov ds:dword ptr[tnext],ecx
|
||||
|
||||
sub ebp,ds:dword ptr[s]
|
||||
sub ecx,ds:dword ptr[t]
|
||||
|
||||
;
|
||||
; set up advancetable
|
||||
;
|
||||
mov eax,ecx
|
||||
mov edx,ebp
|
||||
sar edx,19 ; sstep >>= 16;
|
||||
mov ebx,ds:dword ptr[_cachewidth]
|
||||
sar eax,19 ; tstep >>= 16;
|
||||
jz LIsZero
|
||||
imul eax,ebx ; (tstep >> 16) * cachewidth;
|
||||
LIsZero:
|
||||
add eax,edx ; add in sstep
|
||||
; (tstep >> 16) * cachewidth + (sstep >> 16);
|
||||
mov edx,ds:dword ptr[tfracf]
|
||||
mov ds:dword ptr[advancetable+4],eax ; advance base in t
|
||||
add eax,ebx ; ((tstep >> 16) + 1) * cachewidth +
|
||||
; (sstep >> 16);
|
||||
shl ebp,13 ; left-justify sstep fractional part
|
||||
mov ds:dword ptr[sstep],ebp
|
||||
mov ebx,ds:dword ptr[sfracf]
|
||||
shl ecx,13 ; left-justify tstep fractional part
|
||||
mov ds:dword ptr[advancetable],eax ; advance extra in t
|
||||
mov ds:dword ptr[tstep],ecx
|
||||
|
||||
mov ecx,ds:dword ptr[pz]
|
||||
mov ebp,ds:dword ptr[izi]
|
||||
|
||||
cmp bp,ds:word ptr[ecx]
|
||||
jl Lp1
|
||||
mov al,ds:byte ptr[esi] ; get first source texel
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp1
|
||||
mov ds:word ptr[ecx],bp
|
||||
mov ds:byte ptr[edi],al ; store first dest pixel
|
||||
Lp1:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep] ; advance tfrac fractional part by tstep frac
|
||||
|
||||
sbb eax,eax ; turn tstep carry into -1 (0 if none)
|
||||
add ebx,ds:dword ptr[sstep] ; advance sfrac fractional part by sstep frac
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4] ; point to next source texel
|
||||
|
||||
cmp bp,ds:word ptr[2+ecx]
|
||||
jl Lp2
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp2
|
||||
mov ds:word ptr[2+ecx],bp
|
||||
mov ds:byte ptr[1+edi],al
|
||||
Lp2:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
cmp bp,ds:word ptr[4+ecx]
|
||||
jl Lp3
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp3
|
||||
mov ds:word ptr[4+ecx],bp
|
||||
mov ds:byte ptr[2+edi],al
|
||||
Lp3:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
cmp bp,ds:word ptr[6+ecx]
|
||||
jl Lp4
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp4
|
||||
mov ds:word ptr[6+ecx],bp
|
||||
mov ds:byte ptr[3+edi],al
|
||||
Lp4:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
cmp bp,ds:word ptr[8+ecx]
|
||||
jl Lp5
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp5
|
||||
mov ds:word ptr[8+ecx],bp
|
||||
mov ds:byte ptr[4+edi],al
|
||||
Lp5:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
;
|
||||
; start FDIV for end of next segment in flight, so it can overlap
|
||||
;
|
||||
pop eax
|
||||
cmp eax,8 ; more than one segment after this?
|
||||
ja LSetupNotLast2 ; yes
|
||||
|
||||
dec eax
|
||||
jz LFDIVInFlight2 ; if only one pixel, no need to start an FDIV
|
||||
mov ds:dword ptr[spancountminus1],eax
|
||||
fild ds:dword ptr[spancountminus1]
|
||||
|
||||
fld ds:dword ptr[_d_zistepu] ; _d_zistepu | spancountminus1
|
||||
fmul st(0),st(1) ; _d_zistepu*scm1 | scm1
|
||||
fld ds:dword ptr[_d_tdivzstepu] ; _d_tdivzstepu | _d_zistepu*scm1 | scm1
|
||||
fmul st(0),st(2) ; _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
|
||||
fxch st(1) ; _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1
|
||||
faddp st(3),st(0) ; _d_tdivzstepu*scm1 | scm1
|
||||
fxch st(1) ; scm1 | _d_tdivzstepu*scm1
|
||||
fmul ds:dword ptr[_d_sdivzstepu] ; _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
|
||||
fxch st(1) ; _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
|
||||
faddp st(3),st(0) ; _d_sdivzstepu*scm1
|
||||
fld ds:dword ptr[fp_64k] ; 64k | _d_sdivzstepu*scm1
|
||||
fxch st(1) ; _d_sdivzstepu*scm1 | 64k
|
||||
faddp st(4),st(0) ; 64k
|
||||
|
||||
fdiv st(0),st(1) ; this is what we've gone to all this trouble to
|
||||
; overlap
|
||||
jmp LFDIVInFlight2
|
||||
|
||||
align 4
|
||||
LSetupNotLast2:
|
||||
fadd ds:dword ptr[zi8stepu]
|
||||
fxch st(2)
|
||||
fadd ds:dword ptr[sdivz8stepu]
|
||||
fxch st(2)
|
||||
fld ds:dword ptr[tdivz8stepu]
|
||||
faddp st(2),st(0)
|
||||
fld ds:dword ptr[fp_64k]
|
||||
fdiv st(0),st(1) ; z = 1/1/z
|
||||
; this is what we've gone to all this trouble to
|
||||
; overlap
|
||||
LFDIVInFlight2:
|
||||
push eax
|
||||
|
||||
cmp bp,ds:word ptr[10+ecx]
|
||||
jl Lp6
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp6
|
||||
mov ds:word ptr[10+ecx],bp
|
||||
mov ds:byte ptr[5+edi],al
|
||||
Lp6:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
cmp bp,ds:word ptr[12+ecx]
|
||||
jl Lp7
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp7
|
||||
mov ds:word ptr[12+ecx],bp
|
||||
mov ds:byte ptr[6+edi],al
|
||||
Lp7:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
cmp bp,ds:word ptr[14+ecx]
|
||||
jl Lp8
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp8
|
||||
mov ds:word ptr[14+ecx],bp
|
||||
mov ds:byte ptr[7+edi],al
|
||||
Lp8:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
add edi,8
|
||||
add ecx,16
|
||||
mov ds:dword ptr[tfracf],edx
|
||||
mov edx,ds:dword ptr[snext]
|
||||
mov ds:dword ptr[sfracf],ebx
|
||||
mov ebx,ds:dword ptr[tnext]
|
||||
mov ds:dword ptr[s],edx
|
||||
mov ds:dword ptr[t],ebx
|
||||
|
||||
mov ds:dword ptr[pz],ecx
|
||||
mov ds:dword ptr[izi],ebp
|
||||
|
||||
pop ecx ; retrieve count
|
||||
|
||||
;
|
||||
; determine whether last span or not
|
||||
;
|
||||
cmp ecx,8 ; 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
|
||||
;
|
||||
test 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(0),st(4) ; s = s/z * z
|
||||
fxch st(1)
|
||||
fmul st(0),st(3) ; t = t/z * z
|
||||
fxch st(1)
|
||||
fistp ds:dword ptr[snext]
|
||||
fistp ds:dword ptr[tnext]
|
||||
|
||||
mov ebx,ds:dword ptr[_tadjust]
|
||||
mov eax,ds:dword ptr[_sadjust]
|
||||
|
||||
add eax,ds:dword ptr[snext]
|
||||
add ebx,ds:dword ptr[tnext]
|
||||
|
||||
mov ebp,ds:dword ptr[_bbextents]
|
||||
mov edx,ds:dword ptr[_bbextentt]
|
||||
|
||||
cmp eax,2048
|
||||
jl LClampLow4
|
||||
cmp eax,ebp
|
||||
ja LClampHigh4
|
||||
LClampReentry4:
|
||||
mov ds:dword ptr[snext],eax
|
||||
|
||||
cmp ebx,2048
|
||||
jl LClampLow5
|
||||
cmp ebx,edx
|
||||
ja LClampHigh5
|
||||
LClampReentry5:
|
||||
|
||||
cmp ecx,1 ; don't bother
|
||||
je LOnlyOneStep ; if two pixels in segment, there's only one step,
|
||||
; of the segment length
|
||||
sub eax,ds:dword ptr[s]
|
||||
sub ebx,ds:dword ptr[t]
|
||||
|
||||
add eax,eax ; convert to 15.17 format so multiply by 1.31
|
||||
add ebx,ebx ; reciprocal yields 16.48
|
||||
imul ds:dword ptr[reciprocal_table-8+ecx*4] ; sstep = (snext - s) / (spancount-1)
|
||||
mov ebp,edx
|
||||
|
||||
mov eax,ebx
|
||||
imul ds:dword ptr[reciprocal_table-8+ecx*4] ; tstep = (tnext - t) / (spancount-1)
|
||||
|
||||
LSetEntryvec:
|
||||
;
|
||||
; set up advancetable
|
||||
;
|
||||
mov ebx,ds:dword ptr[spr8entryvec_table+ecx*4]
|
||||
mov eax,edx
|
||||
push ebx ; entry point into code for RET later
|
||||
mov ecx,ebp
|
||||
sar ecx,16 ; sstep >>= 16;
|
||||
mov ebx,ds:dword ptr[_cachewidth]
|
||||
sar edx,16 ; tstep >>= 16;
|
||||
jz LIsZeroLast
|
||||
imul edx,ebx ; (tstep >> 16) * cachewidth;
|
||||
LIsZeroLast:
|
||||
add edx,ecx ; add in sstep
|
||||
; (tstep >> 16) * cachewidth + (sstep >> 16);
|
||||
mov ecx,ds:dword ptr[tfracf]
|
||||
mov ds:dword ptr[advancetable+4],edx ; advance base in t
|
||||
add edx,ebx ; ((tstep >> 16) + 1) * cachewidth +
|
||||
; (sstep >> 16);
|
||||
shl ebp,16 ; left-justify sstep fractional part
|
||||
mov ebx,ds:dword ptr[sfracf]
|
||||
shl eax,16 ; left-justify tstep fractional part
|
||||
mov ds:dword ptr[advancetable],edx ; advance extra in t
|
||||
|
||||
mov ds:dword ptr[tstep],eax
|
||||
mov ds:dword ptr[sstep],ebp
|
||||
mov edx,ecx
|
||||
|
||||
mov ecx,ds:dword ptr[pz]
|
||||
mov ebp,ds:dword ptr[izi]
|
||||
|
||||
ret ; jump to the number-of-pixels handler
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
LNoSteps:
|
||||
mov ecx,ds:dword ptr[pz]
|
||||
sub edi,7 ; adjust for hardwired offset
|
||||
sub ecx,14
|
||||
jmp LEndSpan
|
||||
|
||||
|
||||
LOnlyOneStep:
|
||||
sub eax,ds:dword ptr[s]
|
||||
sub ebx,ds:dword ptr[t]
|
||||
mov ebp,eax
|
||||
mov edx,ebx
|
||||
jmp LSetEntryvec
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
public Spr8Entry2_8
|
||||
Spr8Entry2_8:
|
||||
sub edi,6 ; adjust for hardwired offsets
|
||||
sub ecx,12
|
||||
mov al,ds:byte ptr[esi]
|
||||
jmp LLEntry2_8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
public Spr8Entry3_8
|
||||
Spr8Entry3_8:
|
||||
sub edi,5 ; adjust for hardwired offsets
|
||||
sub ecx,10
|
||||
jmp LLEntry3_8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
public Spr8Entry4_8
|
||||
Spr8Entry4_8:
|
||||
sub edi,4 ; adjust for hardwired offsets
|
||||
sub ecx,8
|
||||
jmp LLEntry4_8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
public Spr8Entry5_8
|
||||
Spr8Entry5_8:
|
||||
sub edi,3 ; adjust for hardwired offsets
|
||||
sub ecx,6
|
||||
jmp LLEntry5_8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
public Spr8Entry6_8
|
||||
Spr8Entry6_8:
|
||||
sub edi,2 ; adjust for hardwired offsets
|
||||
sub ecx,4
|
||||
jmp LLEntry6_8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
public Spr8Entry7_8
|
||||
Spr8Entry7_8:
|
||||
dec edi ; adjust for hardwired offsets
|
||||
sub ecx,2
|
||||
jmp LLEntry7_8
|
||||
|
||||
;----------------------------------------
|
||||
|
||||
public Spr8Entry8_8
|
||||
Spr8Entry8_8:
|
||||
cmp bp,ds:word ptr[ecx]
|
||||
jl Lp9
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp9
|
||||
mov ds:word ptr[ecx],bp
|
||||
mov ds:byte ptr[edi],al
|
||||
Lp9:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
LLEntry7_8:
|
||||
cmp bp,ds:word ptr[2+ecx]
|
||||
jl Lp10
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp10
|
||||
mov ds:word ptr[2+ecx],bp
|
||||
mov ds:byte ptr[1+edi],al
|
||||
Lp10:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
LLEntry6_8:
|
||||
cmp bp,ds:word ptr[4+ecx]
|
||||
jl Lp11
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp11
|
||||
mov ds:word ptr[4+ecx],bp
|
||||
mov ds:byte ptr[2+edi],al
|
||||
Lp11:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
LLEntry5_8:
|
||||
cmp bp,ds:word ptr[6+ecx]
|
||||
jl Lp12
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp12
|
||||
mov ds:word ptr[6+ecx],bp
|
||||
mov ds:byte ptr[3+edi],al
|
||||
Lp12:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
LLEntry4_8:
|
||||
cmp bp,ds:word ptr[8+ecx]
|
||||
jl Lp13
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp13
|
||||
mov ds:word ptr[8+ecx],bp
|
||||
mov ds:byte ptr[4+edi],al
|
||||
Lp13:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
LLEntry3_8:
|
||||
cmp bp,ds:word ptr[10+ecx]
|
||||
jl Lp14
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp14
|
||||
mov ds:word ptr[10+ecx],bp
|
||||
mov ds:byte ptr[5+edi],al
|
||||
Lp14:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
LLEntry2_8:
|
||||
cmp bp,ds:word ptr[12+ecx]
|
||||
jl Lp15
|
||||
mov al,ds:byte ptr[esi]
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp15
|
||||
mov ds:word ptr[12+ecx],bp
|
||||
mov ds:byte ptr[6+edi],al
|
||||
Lp15:
|
||||
add ebp,ds:dword ptr[izistep]
|
||||
adc ebp,0
|
||||
add edx,ds:dword ptr[tstep]
|
||||
sbb eax,eax
|
||||
add ebx,ds:dword ptr[sstep]
|
||||
adc esi,ds:dword ptr[advancetable+4+eax*4]
|
||||
|
||||
LEndSpan:
|
||||
cmp bp,ds:word ptr[14+ecx]
|
||||
jl Lp16
|
||||
mov al,ds:byte ptr[esi] ; load first texel in segment
|
||||
cmp al,offset TRANSPARENT_COLOR
|
||||
jz Lp16
|
||||
mov ds:word ptr[14+ecx],bp
|
||||
mov ds:byte ptr[7+edi],al
|
||||
Lp16:
|
||||
|
||||
;
|
||||
; clear s/z, t/z, 1/z from FP stack
|
||||
;
|
||||
fstp st(0)
|
||||
fstp st(0)
|
||||
fstp st(0)
|
||||
|
||||
pop ebx ; restore spans pointer
|
||||
LNextSpan:
|
||||
add ebx,offset sspan_t_size ; point to next span
|
||||
mov ecx,ds:dword ptr[sspan_t_count+ebx]
|
||||
cmp ecx,0 ; any more spans?
|
||||
jg LSpanLoop ; yes
|
||||
jz LNextSpan ; yes, but this one's empty
|
||||
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp ; restore the caller's stack frame
|
||||
ret
|
||||
|
||||
_TEXT ENDS
|
||||
endif ; id386
|
||||
END
|
||||
123
ref_soft/r_sprite.c
Normal file
123
ref_soft/r_sprite.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// r_sprite.c
|
||||
#include "r_local.h"
|
||||
|
||||
extern polydesc_t r_polydesc;
|
||||
|
||||
void R_BuildPolygonFromSurface(msurface_t *fa);
|
||||
void R_PolygonCalculateGradients (void);
|
||||
|
||||
extern void R_PolyChooseSpanletRoutine( float alpha, qboolean isturbulent );
|
||||
|
||||
extern vec5_t r_clip_verts[2][MAXWORKINGVERTS+2];
|
||||
|
||||
extern void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured );
|
||||
|
||||
/*
|
||||
** R_DrawSprite
|
||||
**
|
||||
** Draw currententity / currentmodel as a single texture
|
||||
** mapped polygon
|
||||
*/
|
||||
void R_DrawSprite (void)
|
||||
{
|
||||
vec5_t *pverts;
|
||||
vec3_t left, up, right, down;
|
||||
dsprite_t *s_psprite;
|
||||
dsprframe_t *s_psprframe;
|
||||
|
||||
|
||||
s_psprite = (dsprite_t *)currentmodel->extradata;
|
||||
#if 0
|
||||
if (currententity->frame >= s_psprite->numframes
|
||||
|| currententity->frame < 0)
|
||||
{
|
||||
ri.Con_Printf (PRINT_ALL, "No such sprite frame %i\n",
|
||||
currententity->frame);
|
||||
currententity->frame = 0;
|
||||
}
|
||||
#endif
|
||||
currententity->frame %= s_psprite->numframes;
|
||||
|
||||
s_psprframe = &s_psprite->frames[currententity->frame];
|
||||
|
||||
r_polydesc.pixels = currentmodel->skins[currententity->frame]->pixels[0];
|
||||
r_polydesc.pixel_width = s_psprframe->width;
|
||||
r_polydesc.pixel_height = s_psprframe->height;
|
||||
r_polydesc.dist = 0;
|
||||
|
||||
// generate the sprite's axes, completely parallel to the viewplane.
|
||||
VectorCopy (vup, r_polydesc.vup);
|
||||
VectorCopy (vright, r_polydesc.vright);
|
||||
VectorCopy (vpn, r_polydesc.vpn);
|
||||
|
||||
// build the sprite poster in worldspace
|
||||
VectorScale (r_polydesc.vright,
|
||||
s_psprframe->width - s_psprframe->origin_x, right);
|
||||
VectorScale (r_polydesc.vup,
|
||||
s_psprframe->height - s_psprframe->origin_y, up);
|
||||
VectorScale (r_polydesc.vright,
|
||||
-s_psprframe->origin_x, left);
|
||||
VectorScale (r_polydesc.vup,
|
||||
-s_psprframe->origin_y, down);
|
||||
|
||||
// invert UP vector for sprites
|
||||
VectorInverse( r_polydesc.vup );
|
||||
|
||||
pverts = r_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] = s_psprframe->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] = s_psprframe->width;
|
||||
pverts[2][4] = s_psprframe->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] = s_psprframe->height;
|
||||
|
||||
r_polydesc.nump = 4;
|
||||
r_polydesc.s_offset = ( r_polydesc.pixel_width >> 1);
|
||||
r_polydesc.t_offset = ( r_polydesc.pixel_height >> 1);
|
||||
VectorCopy( modelorg, r_polydesc.viewer_position );
|
||||
|
||||
r_polydesc.stipple_parity = 1;
|
||||
if ( currententity->flags & RF_TRANSLUCENT )
|
||||
R_ClipAndDrawPoly ( currententity->alpha, false, true );
|
||||
else
|
||||
R_ClipAndDrawPoly ( 1.0F, false, true );
|
||||
r_polydesc.stipple_parity = 0;
|
||||
}
|
||||
|
||||
651
ref_soft/r_surf.c
Normal file
651
ref_soft/r_surf.c
Normal file
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// r_surf.c: surface-related refresh code
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
drawsurf_t r_drawsurf;
|
||||
|
||||
int lightleft, sourcesstep, blocksize, sourcetstep;
|
||||
int lightdelta, lightdeltastep;
|
||||
int lightright, lightleftstep, lightrightstep, blockdivshift;
|
||||
unsigned blockdivmask;
|
||||
void *prowdestbase;
|
||||
unsigned char *pbasesource;
|
||||
int surfrowbytes; // used by ASM files
|
||||
unsigned *r_lightptr;
|
||||
int r_stepback;
|
||||
int r_lightwidth;
|
||||
int r_numhblocks, r_numvblocks;
|
||||
unsigned char *r_source, *r_sourcemax;
|
||||
|
||||
void R_DrawSurfaceBlock8_mip0 (void);
|
||||
void R_DrawSurfaceBlock8_mip1 (void);
|
||||
void R_DrawSurfaceBlock8_mip2 (void);
|
||||
void R_DrawSurfaceBlock8_mip3 (void);
|
||||
|
||||
static void (*surfmiptable[4])(void) = {
|
||||
R_DrawSurfaceBlock8_mip0,
|
||||
R_DrawSurfaceBlock8_mip1,
|
||||
R_DrawSurfaceBlock8_mip2,
|
||||
R_DrawSurfaceBlock8_mip3
|
||||
};
|
||||
|
||||
void R_BuildLightMap (void);
|
||||
extern unsigned blocklights[1024]; // allow some very large lightmaps
|
||||
|
||||
float surfscale;
|
||||
qboolean r_cache_thrash; // set if surface cache is thrashing
|
||||
|
||||
int sc_size;
|
||||
surfcache_t *sc_rover, *sc_base;
|
||||
|
||||
/*
|
||||
===============
|
||||
R_TextureAnimation
|
||||
|
||||
Returns the proper texture for a given time and base texture
|
||||
===============
|
||||
*/
|
||||
image_t *R_TextureAnimation (mtexinfo_t *tex)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (!tex->next)
|
||||
return tex->image;
|
||||
|
||||
c = currententity->frame % tex->numframes;
|
||||
while (c)
|
||||
{
|
||||
tex = tex->next;
|
||||
c--;
|
||||
}
|
||||
|
||||
return tex->image;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_DrawSurface
|
||||
===============
|
||||
*/
|
||||
void R_DrawSurface (void)
|
||||
{
|
||||
unsigned char *basetptr;
|
||||
int smax, tmax, twidth;
|
||||
int u;
|
||||
int soffset, basetoffset, texwidth;
|
||||
int horzblockstep;
|
||||
unsigned char *pcolumndest;
|
||||
void (*pblockdrawer)(void);
|
||||
image_t *mt;
|
||||
|
||||
surfrowbytes = r_drawsurf.rowbytes;
|
||||
|
||||
mt = r_drawsurf.image;
|
||||
|
||||
r_source = mt->pixels[r_drawsurf.surfmip];
|
||||
|
||||
// the fractional light values should range from 0 to (VID_GRADES - 1) << 16
|
||||
// from a source range of 0 - 255
|
||||
|
||||
texwidth = mt->width >> r_drawsurf.surfmip;
|
||||
|
||||
blocksize = 16 >> r_drawsurf.surfmip;
|
||||
blockdivshift = 4 - r_drawsurf.surfmip;
|
||||
blockdivmask = (1 << blockdivshift) - 1;
|
||||
|
||||
r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
|
||||
|
||||
r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
|
||||
r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
|
||||
|
||||
//==============================
|
||||
|
||||
pblockdrawer = surfmiptable[r_drawsurf.surfmip];
|
||||
// TODO: only needs to be set when there is a display settings change
|
||||
horzblockstep = blocksize;
|
||||
|
||||
smax = mt->width >> r_drawsurf.surfmip;
|
||||
twidth = texwidth;
|
||||
tmax = mt->height >> r_drawsurf.surfmip;
|
||||
sourcetstep = texwidth;
|
||||
r_stepback = tmax * twidth;
|
||||
|
||||
r_sourcemax = r_source + (tmax * smax);
|
||||
|
||||
soffset = r_drawsurf.surf->texturemins[0];
|
||||
basetoffset = r_drawsurf.surf->texturemins[1];
|
||||
|
||||
// << 16 components are to guarantee positive values for %
|
||||
soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
|
||||
basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
|
||||
+ (tmax << 16)) % tmax) * twidth)];
|
||||
|
||||
pcolumndest = r_drawsurf.surfdat;
|
||||
|
||||
for (u=0 ; u<r_numhblocks; u++)
|
||||
{
|
||||
r_lightptr = blocklights + u;
|
||||
|
||||
prowdestbase = pcolumndest;
|
||||
|
||||
pbasesource = basetptr + soffset;
|
||||
|
||||
(*pblockdrawer)();
|
||||
|
||||
soffset = soffset + blocksize;
|
||||
if (soffset >= smax)
|
||||
soffset = 0;
|
||||
|
||||
pcolumndest += horzblockstep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSurfaceBlock8_mip0
|
||||
================
|
||||
*/
|
||||
void R_DrawSurfaceBlock8_mip0 (void)
|
||||
{
|
||||
int v, i, b, lightstep, lighttemp, light;
|
||||
unsigned char pix, *psource, *prowdest;
|
||||
|
||||
psource = pbasesource;
|
||||
prowdest = prowdestbase;
|
||||
|
||||
for (v=0 ; v<r_numvblocks ; v++)
|
||||
{
|
||||
// FIXME: make these locals?
|
||||
// FIXME: use delta rather than both right and left, like ASM?
|
||||
lightleft = r_lightptr[0];
|
||||
lightright = r_lightptr[1];
|
||||
r_lightptr += r_lightwidth;
|
||||
lightleftstep = (r_lightptr[0] - lightleft) >> 4;
|
||||
lightrightstep = (r_lightptr[1] - lightright) >> 4;
|
||||
|
||||
for (i=0 ; i<16 ; i++)
|
||||
{
|
||||
lighttemp = lightleft - lightright;
|
||||
lightstep = lighttemp >> 4;
|
||||
|
||||
light = lightright;
|
||||
|
||||
for (b=15; b>=0; b--)
|
||||
{
|
||||
pix = psource[b];
|
||||
prowdest[b] = ((unsigned char *)vid.colormap)
|
||||
[(light & 0xFF00) + pix];
|
||||
light += lightstep;
|
||||
}
|
||||
|
||||
psource += sourcetstep;
|
||||
lightright += lightrightstep;
|
||||
lightleft += lightleftstep;
|
||||
prowdest += surfrowbytes;
|
||||
}
|
||||
|
||||
if (psource >= r_sourcemax)
|
||||
psource -= r_stepback;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSurfaceBlock8_mip1
|
||||
================
|
||||
*/
|
||||
void R_DrawSurfaceBlock8_mip1 (void)
|
||||
{
|
||||
int v, i, b, lightstep, lighttemp, light;
|
||||
unsigned char pix, *psource, *prowdest;
|
||||
|
||||
psource = pbasesource;
|
||||
prowdest = prowdestbase;
|
||||
|
||||
for (v=0 ; v<r_numvblocks ; v++)
|
||||
{
|
||||
// FIXME: make these locals?
|
||||
// FIXME: use delta rather than both right and left, like ASM?
|
||||
lightleft = r_lightptr[0];
|
||||
lightright = r_lightptr[1];
|
||||
r_lightptr += r_lightwidth;
|
||||
lightleftstep = (r_lightptr[0] - lightleft) >> 3;
|
||||
lightrightstep = (r_lightptr[1] - lightright) >> 3;
|
||||
|
||||
for (i=0 ; i<8 ; i++)
|
||||
{
|
||||
lighttemp = lightleft - lightright;
|
||||
lightstep = lighttemp >> 3;
|
||||
|
||||
light = lightright;
|
||||
|
||||
for (b=7; b>=0; b--)
|
||||
{
|
||||
pix = psource[b];
|
||||
prowdest[b] = ((unsigned char *)vid.colormap)
|
||||
[(light & 0xFF00) + pix];
|
||||
light += lightstep;
|
||||
}
|
||||
|
||||
psource += sourcetstep;
|
||||
lightright += lightrightstep;
|
||||
lightleft += lightleftstep;
|
||||
prowdest += surfrowbytes;
|
||||
}
|
||||
|
||||
if (psource >= r_sourcemax)
|
||||
psource -= r_stepback;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSurfaceBlock8_mip2
|
||||
================
|
||||
*/
|
||||
void R_DrawSurfaceBlock8_mip2 (void)
|
||||
{
|
||||
int v, i, b, lightstep, lighttemp, light;
|
||||
unsigned char pix, *psource, *prowdest;
|
||||
|
||||
psource = pbasesource;
|
||||
prowdest = prowdestbase;
|
||||
|
||||
for (v=0 ; v<r_numvblocks ; v++)
|
||||
{
|
||||
// FIXME: make these locals?
|
||||
// FIXME: use delta rather than both right and left, like ASM?
|
||||
lightleft = r_lightptr[0];
|
||||
lightright = r_lightptr[1];
|
||||
r_lightptr += r_lightwidth;
|
||||
lightleftstep = (r_lightptr[0] - lightleft) >> 2;
|
||||
lightrightstep = (r_lightptr[1] - lightright) >> 2;
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
lighttemp = lightleft - lightright;
|
||||
lightstep = lighttemp >> 2;
|
||||
|
||||
light = lightright;
|
||||
|
||||
for (b=3; b>=0; b--)
|
||||
{
|
||||
pix = psource[b];
|
||||
prowdest[b] = ((unsigned char *)vid.colormap)
|
||||
[(light & 0xFF00) + pix];
|
||||
light += lightstep;
|
||||
}
|
||||
|
||||
psource += sourcetstep;
|
||||
lightright += lightrightstep;
|
||||
lightleft += lightleftstep;
|
||||
prowdest += surfrowbytes;
|
||||
}
|
||||
|
||||
if (psource >= r_sourcemax)
|
||||
psource -= r_stepback;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSurfaceBlock8_mip3
|
||||
================
|
||||
*/
|
||||
void R_DrawSurfaceBlock8_mip3 (void)
|
||||
{
|
||||
int v, i, b, lightstep, lighttemp, light;
|
||||
unsigned char pix, *psource, *prowdest;
|
||||
|
||||
psource = pbasesource;
|
||||
prowdest = prowdestbase;
|
||||
|
||||
for (v=0 ; v<r_numvblocks ; v++)
|
||||
{
|
||||
// FIXME: make these locals?
|
||||
// FIXME: use delta rather than both right and left, like ASM?
|
||||
lightleft = r_lightptr[0];
|
||||
lightright = r_lightptr[1];
|
||||
r_lightptr += r_lightwidth;
|
||||
lightleftstep = (r_lightptr[0] - lightleft) >> 1;
|
||||
lightrightstep = (r_lightptr[1] - lightright) >> 1;
|
||||
|
||||
for (i=0 ; i<2 ; i++)
|
||||
{
|
||||
lighttemp = lightleft - lightright;
|
||||
lightstep = lighttemp >> 1;
|
||||
|
||||
light = lightright;
|
||||
|
||||
for (b=1; b>=0; b--)
|
||||
{
|
||||
pix = psource[b];
|
||||
prowdest[b] = ((unsigned char *)vid.colormap)
|
||||
[(light & 0xFF00) + pix];
|
||||
light += lightstep;
|
||||
}
|
||||
|
||||
psource += sourcetstep;
|
||||
lightright += lightrightstep;
|
||||
lightleft += lightleftstep;
|
||||
prowdest += surfrowbytes;
|
||||
}
|
||||
|
||||
if (psource >= r_sourcemax)
|
||||
psource -= r_stepback;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_InitCaches
|
||||
|
||||
================
|
||||
*/
|
||||
void R_InitCaches (void)
|
||||
{
|
||||
int size;
|
||||
int pix;
|
||||
|
||||
// calculate size to allocate
|
||||
if (sw_surfcacheoverride->value)
|
||||
{
|
||||
size = sw_surfcacheoverride->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = SURFCACHE_SIZE_AT_320X240;
|
||||
|
||||
pix = vid.width*vid.height;
|
||||
if (pix > 64000)
|
||||
size += (pix-64000)*3;
|
||||
}
|
||||
|
||||
// round up to page size
|
||||
size = (size + 8191) & ~8191;
|
||||
|
||||
ri.Con_Printf (PRINT_ALL,"%ik surface cache\n", size/1024);
|
||||
|
||||
sc_size = size;
|
||||
sc_base = (surfcache_t *)malloc(size);
|
||||
sc_rover = sc_base;
|
||||
|
||||
sc_base->next = NULL;
|
||||
sc_base->owner = NULL;
|
||||
sc_base->size = sc_size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
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 size)
|
||||
{
|
||||
surfcache_t *new;
|
||||
qboolean wrapped_this_time;
|
||||
|
||||
if ((width < 0) || (width > 256))
|
||||
ri.Sys_Error (ERR_FATAL,"D_SCAlloc: bad cache width %d\n", width);
|
||||
|
||||
if ((size <= 0) || (size > 0x10000))
|
||||
ri.Sys_Error (ERR_FATAL,"D_SCAlloc: bad cache size %d\n", size);
|
||||
|
||||
size = (int)&((surfcache_t *)0)->data[size];
|
||||
size = (size + 3) & ~3;
|
||||
if (size > sc_size)
|
||||
ri.Sys_Error (ERR_FATAL,"D_SCAlloc: %i > cache size of %i",size, sc_size);
|
||||
|
||||
// if there is not size bytes after the rover, reset to the start
|
||||
wrapped_this_time = false;
|
||||
|
||||
if ( !sc_rover || (byte *)sc_rover - (byte *)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)
|
||||
ri.Sys_Error (ERR_FATAL,"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 *)( (byte *)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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
D_SCDump
|
||||
=================
|
||||
*/
|
||||
void D_SCDump (void)
|
||||
{
|
||||
surfcache_t *test;
|
||||
|
||||
for (test = sc_base ; test ; test = test->next)
|
||||
{
|
||||
if (test == sc_rover)
|
||||
ri.Con_Printf (PRINT_ALL,"ROVER:\n");
|
||||
ri.Con_Printf (PRINT_ALL,"%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;
|
||||
|
||||
//
|
||||
// if the surface is animating or flashing, flush the cache
|
||||
//
|
||||
r_drawsurf.image = R_TextureAnimation (surface->texinfo);
|
||||
r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white*128;
|
||||
r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white*128;
|
||||
r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white*128;
|
||||
r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white*128;
|
||||
|
||||
//
|
||||
// see if the cache holds apropriate data
|
||||
//
|
||||
cache = surface->cachespots[miplevel];
|
||||
|
||||
if (cache && !cache->dlight && surface->dlightframe != r_framecount
|
||||
&& cache->image == r_drawsurf.image
|
||||
&& 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;
|
||||
|
||||
//
|
||||
// allocate memory if needed
|
||||
//
|
||||
if (!cache) // if a texture just animated, don't reallocate it
|
||||
{
|
||||
cache = D_SCAlloc (r_drawsurf.surfwidth,
|
||||
r_drawsurf.surfwidth * r_drawsurf.surfheight);
|
||||
surface->cachespots[miplevel] = cache;
|
||||
cache->owner = &surface->cachespots[miplevel];
|
||||
cache->mipscale = surfscale;
|
||||
}
|
||||
|
||||
if (surface->dlightframe == r_framecount)
|
||||
cache->dlight = 1;
|
||||
else
|
||||
cache->dlight = 0;
|
||||
|
||||
r_drawsurf.surfdat = (pixel_t *)cache->data;
|
||||
|
||||
cache->image = r_drawsurf.image;
|
||||
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++;
|
||||
|
||||
// calculate the lightings
|
||||
R_BuildLightMap ();
|
||||
|
||||
// rasterize the surface into the cache
|
||||
R_DrawSurface ();
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
771
ref_soft/r_surf8.asm
Normal file
771
ref_soft/r_surf8.asm
Normal file
@@ -0,0 +1,771 @@
|
||||
.386P
|
||||
.model FLAT
|
||||
;
|
||||
; surf8.s
|
||||
; x86 assembly-language 8 bpp surface block drawing code.
|
||||
;
|
||||
|
||||
include qasm.inc
|
||||
|
||||
if id386
|
||||
|
||||
_DATA SEGMENT
|
||||
|
||||
sb_v dd 0
|
||||
|
||||
_DATA ENDS
|
||||
_TEXT SEGMENT
|
||||
|
||||
align 4
|
||||
public _R_Surf8Start
|
||||
_R_Surf8Start:
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; Surface block drawer for mip level 0
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
public _R_DrawSurfaceBlock8_mip0
|
||||
_R_DrawSurfaceBlock8_mip0:
|
||||
push ebp ; preserve caller's stack frame
|
||||
push edi
|
||||
push esi ; preserve register variables
|
||||
push ebx
|
||||
|
||||
; for (v=0 ; v<numvblocks ; v++)
|
||||
; {
|
||||
mov ebx,ds:dword ptr[_r_lightptr]
|
||||
mov eax,ds:dword ptr[_r_numvblocks]
|
||||
|
||||
mov ds:dword ptr[sb_v],eax
|
||||
mov edi,ds:dword ptr[_prowdestbase]
|
||||
|
||||
mov esi,ds:dword ptr[_pbasesource]
|
||||
|
||||
Lv_loop_mip0:
|
||||
|
||||
; lightleft = lightptr[0];
|
||||
; lightright = lightptr[1];
|
||||
; lightdelta = (lightleft - lightright) & 0xFFFFF;
|
||||
mov eax,ds:dword ptr[ebx] ; lightleft
|
||||
mov edx,ds:dword ptr[4+ebx] ; lightright
|
||||
|
||||
mov ebp,eax
|
||||
mov ecx,ds:dword ptr[_r_lightwidth]
|
||||
|
||||
mov ds:dword ptr[_lightright],edx
|
||||
sub ebp,edx
|
||||
|
||||
and ebp,0FFFFFh
|
||||
lea ebx,ds:dword ptr[ebx+ecx*4]
|
||||
|
||||
; lightptr += lightwidth;
|
||||
mov ds:dword ptr[_r_lightptr],ebx
|
||||
|
||||
; lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
|
||||
; lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
|
||||
; lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
|
||||
; 0xF0000000;
|
||||
mov ecx,ds:dword ptr[4+ebx] ; lightptr[1]
|
||||
mov ebx,ds:dword ptr[ebx] ; lightptr[0]
|
||||
|
||||
sub ebx,eax
|
||||
sub ecx,edx
|
||||
|
||||
sar ecx,4
|
||||
or ebp,0F0000000h
|
||||
|
||||
sar ebx,4
|
||||
mov ds:dword ptr[_lightrightstep],ecx
|
||||
|
||||
sub ebx,ecx
|
||||
and ebx,0FFFFFh
|
||||
|
||||
or ebx,0F0000000h
|
||||
sub ecx,ecx ; high word must be 0 in loop for addressing
|
||||
|
||||
mov ds:dword ptr[_lightdeltastep],ebx
|
||||
sub ebx,ebx ; high word must be 0 in loop for addressing
|
||||
|
||||
Lblockloop8_mip0:
|
||||
mov ds:dword ptr[_lightdelta],ebp
|
||||
mov cl,ds:byte ptr[14+esi]
|
||||
|
||||
sar ebp,4
|
||||
mov bh,dh
|
||||
|
||||
mov bl,ds:byte ptr[15+esi]
|
||||
add edx,ebp
|
||||
|
||||
mov ch,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch0:
|
||||
mov bl,ds:byte ptr[13+esi]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch1:
|
||||
mov cl,ds:byte ptr[12+esi]
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
ror eax,16
|
||||
mov ch,dh
|
||||
|
||||
add edx,ebp
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch2:
|
||||
|
||||
mov bl,ds:byte ptr[11+esi]
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch3:
|
||||
|
||||
mov cl,ds:byte ptr[10+esi]
|
||||
mov ds:dword ptr[12+edi],eax
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ch,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch4:
|
||||
mov bl,ds:byte ptr[9+esi]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch5:
|
||||
mov cl,ds:byte ptr[8+esi]
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
ror eax,16
|
||||
mov ch,dh
|
||||
|
||||
add edx,ebp
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch6:
|
||||
|
||||
mov bl,ds:byte ptr[7+esi]
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch7:
|
||||
|
||||
mov cl,ds:byte ptr[6+esi]
|
||||
mov ds:dword ptr[8+edi],eax
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ch,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch8:
|
||||
mov bl,ds:byte ptr[5+esi]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch9:
|
||||
mov cl,ds:byte ptr[4+esi]
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
ror eax,16
|
||||
mov ch,dh
|
||||
|
||||
add edx,ebp
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch10:
|
||||
|
||||
mov bl,ds:byte ptr[3+esi]
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch11:
|
||||
|
||||
mov cl,ds:byte ptr[2+esi]
|
||||
mov ds:dword ptr[4+edi],eax
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ch,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch12:
|
||||
mov bl,ds:byte ptr[1+esi]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch13:
|
||||
mov cl,ds:byte ptr[esi]
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
ror eax,16
|
||||
mov ch,dh
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch14:
|
||||
mov edx,ds:dword ptr[_lightright]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch15:
|
||||
mov ebp,ds:dword ptr[_lightdelta]
|
||||
|
||||
mov ds:dword ptr[edi],eax
|
||||
|
||||
add esi,ds:dword ptr[_sourcetstep]
|
||||
add edi,ds:dword ptr[_surfrowbytes]
|
||||
|
||||
add edx,ds:dword ptr[_lightrightstep]
|
||||
add ebp,ds:dword ptr[_lightdeltastep]
|
||||
|
||||
mov ds:dword ptr[_lightright],edx
|
||||
jc Lblockloop8_mip0
|
||||
|
||||
; if (pbasesource >= r_sourcemax)
|
||||
; pbasesource -= stepback;
|
||||
|
||||
cmp esi,ds:dword ptr[_r_sourcemax]
|
||||
jb LSkip_mip0
|
||||
sub esi,ds:dword ptr[_r_stepback]
|
||||
LSkip_mip0:
|
||||
|
||||
mov ebx,ds:dword ptr[_r_lightptr]
|
||||
dec ds:dword ptr[sb_v]
|
||||
|
||||
jnz Lv_loop_mip0
|
||||
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp ; restore the caller's stack frame
|
||||
ret
|
||||
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; Surface block drawer for mip level 1
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
public _R_DrawSurfaceBlock8_mip1
|
||||
_R_DrawSurfaceBlock8_mip1:
|
||||
push ebp ; preserve caller's stack frame
|
||||
push edi
|
||||
push esi ; preserve register variables
|
||||
push ebx
|
||||
|
||||
; for (v=0 ; v<numvblocks ; v++)
|
||||
; {
|
||||
mov ebx,ds:dword ptr[_r_lightptr]
|
||||
mov eax,ds:dword ptr[_r_numvblocks]
|
||||
|
||||
mov ds:dword ptr[sb_v],eax
|
||||
mov edi,ds:dword ptr[_prowdestbase]
|
||||
|
||||
mov esi,ds:dword ptr[_pbasesource]
|
||||
|
||||
Lv_loop_mip1:
|
||||
|
||||
; lightleft = lightptr[0];
|
||||
; lightright = lightptr[1];
|
||||
; lightdelta = (lightleft - lightright) & 0xFFFFF;
|
||||
mov eax,ds:dword ptr[ebx] ; lightleft
|
||||
mov edx,ds:dword ptr[4+ebx] ; lightright
|
||||
|
||||
mov ebp,eax
|
||||
mov ecx,ds:dword ptr[_r_lightwidth]
|
||||
|
||||
mov ds:dword ptr[_lightright],edx
|
||||
sub ebp,edx
|
||||
|
||||
and ebp,0FFFFFh
|
||||
lea ebx,ds:dword ptr[ebx+ecx*4]
|
||||
|
||||
; lightptr += lightwidth;
|
||||
mov ds:dword ptr[_r_lightptr],ebx
|
||||
|
||||
; lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
|
||||
; lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
|
||||
; lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
|
||||
; 0xF0000000;
|
||||
mov ecx,ds:dword ptr[4+ebx] ; lightptr[1]
|
||||
mov ebx,ds:dword ptr[ebx] ; lightptr[0]
|
||||
|
||||
sub ebx,eax
|
||||
sub ecx,edx
|
||||
|
||||
sar ecx,3
|
||||
or ebp,070000000h
|
||||
|
||||
sar ebx,3
|
||||
mov ds:dword ptr[_lightrightstep],ecx
|
||||
|
||||
sub ebx,ecx
|
||||
and ebx,0FFFFFh
|
||||
|
||||
or ebx,0F0000000h
|
||||
sub ecx,ecx ; high word must be 0 in loop for addressing
|
||||
|
||||
mov ds:dword ptr[_lightdeltastep],ebx
|
||||
sub ebx,ebx ; high word must be 0 in loop for addressing
|
||||
|
||||
Lblockloop8_mip1:
|
||||
mov ds:dword ptr[_lightdelta],ebp
|
||||
mov cl,ds:byte ptr[6+esi]
|
||||
|
||||
sar ebp,3
|
||||
mov bh,dh
|
||||
|
||||
mov bl,ds:byte ptr[7+esi]
|
||||
add edx,ebp
|
||||
|
||||
mov ch,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch22:
|
||||
mov bl,ds:byte ptr[5+esi]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch23:
|
||||
mov cl,ds:byte ptr[4+esi]
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
ror eax,16
|
||||
mov ch,dh
|
||||
|
||||
add edx,ebp
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch24:
|
||||
|
||||
mov bl,ds:byte ptr[3+esi]
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch25:
|
||||
|
||||
mov cl,ds:byte ptr[2+esi]
|
||||
mov ds:dword ptr[4+edi],eax
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ch,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch26:
|
||||
mov bl,ds:byte ptr[1+esi]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch27:
|
||||
mov cl,ds:byte ptr[esi]
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
ror eax,16
|
||||
mov ch,dh
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch28:
|
||||
mov edx,ds:dword ptr[_lightright]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch29:
|
||||
mov ebp,ds:dword ptr[_lightdelta]
|
||||
|
||||
mov ds:dword ptr[edi],eax
|
||||
mov eax,ds:dword ptr[_sourcetstep]
|
||||
|
||||
add esi,eax
|
||||
mov eax,ds:dword ptr[_surfrowbytes]
|
||||
|
||||
add edi,eax
|
||||
mov eax,ds:dword ptr[_lightrightstep]
|
||||
|
||||
add edx,eax
|
||||
mov eax,ds:dword ptr[_lightdeltastep]
|
||||
|
||||
add ebp,eax
|
||||
mov ds:dword ptr[_lightright],edx
|
||||
|
||||
jc Lblockloop8_mip1
|
||||
|
||||
; if (pbasesource >= r_sourcemax)
|
||||
; pbasesource -= stepback;
|
||||
|
||||
cmp esi,ds:dword ptr[_r_sourcemax]
|
||||
jb LSkip_mip1
|
||||
sub esi,ds:dword ptr[_r_stepback]
|
||||
LSkip_mip1:
|
||||
|
||||
mov ebx,ds:dword ptr[_r_lightptr]
|
||||
dec ds:dword ptr[sb_v]
|
||||
|
||||
jnz Lv_loop_mip1
|
||||
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp ; restore the caller's stack frame
|
||||
ret
|
||||
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; Surface block drawer for mip level 2
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
public _R_DrawSurfaceBlock8_mip2
|
||||
_R_DrawSurfaceBlock8_mip2:
|
||||
push ebp ; preserve caller's stack frame
|
||||
push edi
|
||||
push esi ; preserve register variables
|
||||
push ebx
|
||||
|
||||
; for (v=0 ; v<numvblocks ; v++)
|
||||
; {
|
||||
mov ebx,ds:dword ptr[_r_lightptr]
|
||||
mov eax,ds:dword ptr[_r_numvblocks]
|
||||
|
||||
mov ds:dword ptr[sb_v],eax
|
||||
mov edi,ds:dword ptr[_prowdestbase]
|
||||
|
||||
mov esi,ds:dword ptr[_pbasesource]
|
||||
|
||||
Lv_loop_mip2:
|
||||
|
||||
; lightleft = lightptr[0];
|
||||
; lightright = lightptr[1];
|
||||
; lightdelta = (lightleft - lightright) & 0xFFFFF;
|
||||
mov eax,ds:dword ptr[ebx] ; lightleft
|
||||
mov edx,ds:dword ptr[4+ebx] ; lightright
|
||||
|
||||
mov ebp,eax
|
||||
mov ecx,ds:dword ptr[_r_lightwidth]
|
||||
|
||||
mov ds:dword ptr[_lightright],edx
|
||||
sub ebp,edx
|
||||
|
||||
and ebp,0FFFFFh
|
||||
lea ebx,ds:dword ptr[ebx+ecx*4]
|
||||
|
||||
; lightptr += lightwidth;
|
||||
mov ds:dword ptr[_r_lightptr],ebx
|
||||
|
||||
; lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
|
||||
; lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
|
||||
; lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
|
||||
; 0xF0000000;
|
||||
mov ecx,ds:dword ptr[4+ebx] ; lightptr[1]
|
||||
mov ebx,ds:dword ptr[ebx] ; lightptr[0]
|
||||
|
||||
sub ebx,eax
|
||||
sub ecx,edx
|
||||
|
||||
sar ecx,2
|
||||
or ebp,030000000h
|
||||
|
||||
sar ebx,2
|
||||
mov ds:dword ptr[_lightrightstep],ecx
|
||||
|
||||
sub ebx,ecx
|
||||
|
||||
and ebx,0FFFFFh
|
||||
|
||||
or ebx,0F0000000h
|
||||
sub ecx,ecx ; high word must be 0 in loop for addressing
|
||||
|
||||
mov ds:dword ptr[_lightdeltastep],ebx
|
||||
sub ebx,ebx ; high word must be 0 in loop for addressing
|
||||
|
||||
Lblockloop8_mip2:
|
||||
mov ds:dword ptr[_lightdelta],ebp
|
||||
mov cl,ds:byte ptr[2+esi]
|
||||
|
||||
sar ebp,2
|
||||
mov bh,dh
|
||||
|
||||
mov bl,ds:byte ptr[3+esi]
|
||||
add edx,ebp
|
||||
|
||||
mov ch,dh
|
||||
add edx,ebp
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch18:
|
||||
mov bl,ds:byte ptr[1+esi]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch19:
|
||||
mov cl,ds:byte ptr[esi]
|
||||
|
||||
mov bh,dh
|
||||
add edx,ebp
|
||||
|
||||
ror eax,16
|
||||
mov ch,dh
|
||||
|
||||
mov ah,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch20:
|
||||
mov edx,ds:dword ptr[_lightright]
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch21:
|
||||
mov ebp,ds:dword ptr[_lightdelta]
|
||||
|
||||
mov ds:dword ptr[edi],eax
|
||||
mov eax,ds:dword ptr[_sourcetstep]
|
||||
|
||||
add esi,eax
|
||||
mov eax,ds:dword ptr[_surfrowbytes]
|
||||
|
||||
add edi,eax
|
||||
mov eax,ds:dword ptr[_lightrightstep]
|
||||
|
||||
add edx,eax
|
||||
mov eax,ds:dword ptr[_lightdeltastep]
|
||||
|
||||
add ebp,eax
|
||||
mov ds:dword ptr[_lightright],edx
|
||||
|
||||
jc Lblockloop8_mip2
|
||||
|
||||
; if (pbasesource >= r_sourcemax)
|
||||
; pbasesource -= stepback;
|
||||
|
||||
cmp esi,ds:dword ptr[_r_sourcemax]
|
||||
jb LSkip_mip2
|
||||
sub esi,ds:dword ptr[_r_stepback]
|
||||
LSkip_mip2:
|
||||
|
||||
mov ebx,ds:dword ptr[_r_lightptr]
|
||||
dec ds:dword ptr[sb_v]
|
||||
|
||||
jnz Lv_loop_mip2
|
||||
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp ; restore the caller's stack frame
|
||||
ret
|
||||
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; Surface block drawer for mip level 3
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
public _R_DrawSurfaceBlock8_mip3
|
||||
_R_DrawSurfaceBlock8_mip3:
|
||||
push ebp ; preserve caller's stack frame
|
||||
push edi
|
||||
push esi ; preserve register variables
|
||||
push ebx
|
||||
|
||||
; for (v=0 ; v<numvblocks ; v++)
|
||||
; {
|
||||
mov ebx,ds:dword ptr[_r_lightptr]
|
||||
mov eax,ds:dword ptr[_r_numvblocks]
|
||||
|
||||
mov ds:dword ptr[sb_v],eax
|
||||
mov edi,ds:dword ptr[_prowdestbase]
|
||||
|
||||
mov esi,ds:dword ptr[_pbasesource]
|
||||
|
||||
Lv_loop_mip3:
|
||||
|
||||
; lightleft = lightptr[0];
|
||||
; lightright = lightptr[1];
|
||||
; lightdelta = (lightleft - lightright) & 0xFFFFF;
|
||||
mov eax,ds:dword ptr[ebx] ; lightleft
|
||||
mov edx,ds:dword ptr[4+ebx] ; lightright
|
||||
|
||||
mov ebp,eax
|
||||
mov ecx,ds:dword ptr[_r_lightwidth]
|
||||
|
||||
mov ds:dword ptr[_lightright],edx
|
||||
sub ebp,edx
|
||||
|
||||
and ebp,0FFFFFh
|
||||
lea ebx,ds:dword ptr[ebx+ecx*4]
|
||||
|
||||
mov ds:dword ptr[_lightdelta],ebp
|
||||
; lightptr += lightwidth;
|
||||
mov ds:dword ptr[_r_lightptr],ebx
|
||||
|
||||
; lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
|
||||
; lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
|
||||
; lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
|
||||
; 0xF0000000;
|
||||
mov ecx,ds:dword ptr[4+ebx] ; lightptr[1]
|
||||
mov ebx,ds:dword ptr[ebx] ; lightptr[0]
|
||||
|
||||
sub ebx,eax
|
||||
sub ecx,edx
|
||||
|
||||
sar ecx,1
|
||||
|
||||
sar ebx,1
|
||||
mov ds:dword ptr[_lightrightstep],ecx
|
||||
|
||||
sub ebx,ecx
|
||||
and ebx,0FFFFFh
|
||||
|
||||
sar ebp,1
|
||||
or ebx,0F0000000h
|
||||
|
||||
mov ds:dword ptr[_lightdeltastep],ebx
|
||||
sub ebx,ebx ; high word must be 0 in loop for addressing
|
||||
|
||||
mov bl,ds:byte ptr[1+esi]
|
||||
sub ecx,ecx ; high word must be 0 in loop for addressing
|
||||
|
||||
mov bh,dh
|
||||
mov cl,ds:byte ptr[esi]
|
||||
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch16:
|
||||
mov edx,ds:dword ptr[_lightright]
|
||||
|
||||
mov ds:byte ptr[1+edi],al
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch17:
|
||||
|
||||
mov ds:byte ptr[edi],al
|
||||
mov eax,ds:dword ptr[_sourcetstep]
|
||||
|
||||
add esi,eax
|
||||
mov eax,ds:dword ptr[_surfrowbytes]
|
||||
|
||||
add edi,eax
|
||||
mov eax,ds:dword ptr[_lightdeltastep]
|
||||
|
||||
mov ebp,ds:dword ptr[_lightdelta]
|
||||
mov cl,ds:byte ptr[esi]
|
||||
|
||||
add ebp,eax
|
||||
mov eax,ds:dword ptr[_lightrightstep]
|
||||
|
||||
sar ebp,1
|
||||
add edx,eax
|
||||
|
||||
mov bh,dh
|
||||
mov bl,ds:byte ptr[1+esi]
|
||||
|
||||
add edx,ebp
|
||||
mov ch,dh
|
||||
|
||||
mov al,ds:byte ptr[12345678h+ebx]
|
||||
LBPatch30:
|
||||
mov edx,ds:dword ptr[_sourcetstep]
|
||||
|
||||
mov ds:byte ptr[1+edi],al
|
||||
mov al,ds:byte ptr[12345678h+ecx]
|
||||
LBPatch31:
|
||||
|
||||
mov ds:byte ptr[edi],al
|
||||
mov ebp,ds:dword ptr[_surfrowbytes]
|
||||
|
||||
add esi,edx
|
||||
add edi,ebp
|
||||
|
||||
; if (pbasesource >= r_sourcemax)
|
||||
; pbasesource -= stepback;
|
||||
|
||||
cmp esi,ds:dword ptr[_r_sourcemax]
|
||||
jb LSkip_mip3
|
||||
sub esi,ds:dword ptr[_r_stepback]
|
||||
LSkip_mip3:
|
||||
|
||||
mov ebx,ds:dword ptr[_r_lightptr]
|
||||
dec ds:dword ptr[sb_v]
|
||||
|
||||
jnz Lv_loop_mip3
|
||||
|
||||
pop ebx ; restore register variables
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp ; restore the caller's stack frame
|
||||
ret
|
||||
|
||||
|
||||
public _R_Surf8End
|
||||
_R_Surf8End:
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; Code patching routines
|
||||
;----------------------------------------------------------------------
|
||||
_TEXT ENDS
|
||||
_DATA SEGMENT
|
||||
|
||||
align 4
|
||||
LPatchTable8:
|
||||
dd LBPatch0-4
|
||||
dd LBPatch1-4
|
||||
dd LBPatch2-4
|
||||
dd LBPatch3-4
|
||||
dd LBPatch4-4
|
||||
dd LBPatch5-4
|
||||
dd LBPatch6-4
|
||||
dd LBPatch7-4
|
||||
dd LBPatch8-4
|
||||
dd LBPatch9-4
|
||||
dd LBPatch10-4
|
||||
dd LBPatch11-4
|
||||
dd LBPatch12-4
|
||||
dd LBPatch13-4
|
||||
dd LBPatch14-4
|
||||
dd LBPatch15-4
|
||||
dd LBPatch16-4
|
||||
dd LBPatch17-4
|
||||
dd LBPatch18-4
|
||||
dd LBPatch19-4
|
||||
dd LBPatch20-4
|
||||
dd LBPatch21-4
|
||||
dd LBPatch22-4
|
||||
dd LBPatch23-4
|
||||
dd LBPatch24-4
|
||||
dd LBPatch25-4
|
||||
dd LBPatch26-4
|
||||
dd LBPatch27-4
|
||||
dd LBPatch28-4
|
||||
dd LBPatch29-4
|
||||
dd LBPatch30-4
|
||||
dd LBPatch31-4
|
||||
|
||||
_DATA ENDS
|
||||
_TEXT SEGMENT
|
||||
|
||||
align 4
|
||||
public _R_Surf8Patch
|
||||
_R_Surf8Patch:
|
||||
push ebx
|
||||
|
||||
mov eax,ds:dword ptr[_colormap]
|
||||
mov ebx,offset LPatchTable8
|
||||
mov ecx,32
|
||||
LPatchLoop8:
|
||||
mov edx,ds:dword ptr[ebx]
|
||||
add ebx,4
|
||||
mov ds:dword ptr[edx],eax
|
||||
dec ecx
|
||||
jnz LPatchLoop8
|
||||
|
||||
pop ebx
|
||||
|
||||
ret
|
||||
|
||||
_TEXT ENDS
|
||||
endif ;id386
|
||||
|
||||
END
|
||||
|
||||
220
ref_soft/r_varsa.asm
Normal file
220
ref_soft/r_varsa.asm
Normal file
@@ -0,0 +1,220 @@
|
||||
.386P
|
||||
.model FLAT
|
||||
;
|
||||
; d_varsa.s
|
||||
;
|
||||
|
||||
include qasm.inc
|
||||
include d_if.inc
|
||||
|
||||
if id386
|
||||
|
||||
_DATA SEGMENT
|
||||
|
||||
;-------------------------------------------------------
|
||||
; ASM-only variables
|
||||
;-------------------------------------------------------
|
||||
public float_1, float_particle_z_clip, float_point5
|
||||
public float_minus_1, float_0
|
||||
float_0 dd 0.0
|
||||
float_1 dd 1.0
|
||||
float_minus_1 dd -1.0
|
||||
float_particle_z_clip dd PARTICLE_Z_CLIP
|
||||
float_point5 dd 0.5
|
||||
|
||||
public fp_16, fp_64k, fp_1m, fp_64kx64k
|
||||
public fp_1m_minus_1
|
||||
public fp_8
|
||||
fp_1m dd 1048576.0
|
||||
fp_1m_minus_1 dd 1048575.0
|
||||
fp_64k dd 65536.0
|
||||
fp_8 dd 8.0
|
||||
fp_16 dd 16.0
|
||||
fp_64kx64k dd 04f000000h ; (float)0x8000*0x10000
|
||||
|
||||
|
||||
public FloatZero, Float2ToThe31nd, FloatMinus2ToThe31nd
|
||||
FloatZero dd 0
|
||||
Float2ToThe31nd dd 04f000000h
|
||||
FloatMinus2ToThe31nd dd 0cf000000h
|
||||
|
||||
public _r_bmodelactive
|
||||
_r_bmodelactive dd 0
|
||||
|
||||
|
||||
;-------------------------------------------------------
|
||||
; global refresh variables
|
||||
;-------------------------------------------------------
|
||||
|
||||
; FIXME: put all refresh variables into one contiguous block. Make into one
|
||||
; big structure, like cl or sv?
|
||||
|
||||
align 4
|
||||
public _d_sdivzstepu
|
||||
public _d_tdivzstepu
|
||||
public _d_zistepu
|
||||
public _d_sdivzstepv
|
||||
public _d_tdivzstepv
|
||||
public _d_zistepv
|
||||
public _d_sdivzorigin
|
||||
public _d_tdivzorigin
|
||||
public _d_ziorigin
|
||||
_d_sdivzstepu dd 0
|
||||
_d_tdivzstepu dd 0
|
||||
_d_zistepu dd 0
|
||||
_d_sdivzstepv dd 0
|
||||
_d_tdivzstepv dd 0
|
||||
_d_zistepv dd 0
|
||||
_d_sdivzorigin dd 0
|
||||
_d_tdivzorigin dd 0
|
||||
_d_ziorigin dd 0
|
||||
|
||||
public _sadjust
|
||||
public _tadjust
|
||||
public _bbextents
|
||||
public _bbextentt
|
||||
_sadjust dd 0
|
||||
_tadjust dd 0
|
||||
_bbextents dd 0
|
||||
_bbextentt dd 0
|
||||
|
||||
public _cacheblock
|
||||
public _d_viewbuffer
|
||||
public _cachewidth
|
||||
public _d_pzbuffer
|
||||
public _d_zrowbytes
|
||||
public _d_zwidth
|
||||
_cacheblock dd 0
|
||||
_cachewidth dd 0
|
||||
_d_viewbuffer dd 0
|
||||
_d_pzbuffer dd 0
|
||||
_d_zrowbytes dd 0
|
||||
_d_zwidth dd 0
|
||||
|
||||
|
||||
;-------------------------------------------------------
|
||||
; ASM-only variables
|
||||
;-------------------------------------------------------
|
||||
public izi
|
||||
izi dd 0
|
||||
|
||||
public pbase, s, t, sfracf, tfracf, snext, tnext
|
||||
public spancountminus1, zi16stepu, sdivz16stepu, tdivz16stepu
|
||||
public zi8stepu, sdivz8stepu, tdivz8stepu, pz
|
||||
s dd 0
|
||||
t dd 0
|
||||
snext dd 0
|
||||
tnext dd 0
|
||||
sfracf dd 0
|
||||
tfracf dd 0
|
||||
pbase dd 0
|
||||
zi8stepu dd 0
|
||||
sdivz8stepu dd 0
|
||||
tdivz8stepu dd 0
|
||||
zi16stepu dd 0
|
||||
sdivz16stepu dd 0
|
||||
tdivz16stepu dd 0
|
||||
spancountminus1 dd 0
|
||||
pz dd 0
|
||||
|
||||
public izistep
|
||||
izistep dd 0
|
||||
|
||||
;-------------------------------------------------------
|
||||
; local variables for d_draw16.s
|
||||
;-------------------------------------------------------
|
||||
|
||||
public 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 dd 040000000h, 02aaaaaaah, 020000000h
|
||||
dd 019999999h, 015555555h, 012492492h
|
||||
dd 010000000h, 0e38e38eh, 0ccccccch, 0ba2e8bah
|
||||
dd 0aaaaaaah, 09d89d89h, 09249249h, 08888888h
|
||||
|
||||
externdef Entry2_16:dword
|
||||
externdef Entry3_16:dword
|
||||
externdef Entry4_16:dword
|
||||
externdef Entry5_16:dword
|
||||
externdef Entry6_16:dword
|
||||
externdef Entry7_16:dword
|
||||
externdef Entry8_16:dword
|
||||
externdef Entry9_16:dword
|
||||
externdef Entry10_16:dword
|
||||
externdef Entry11_16:dword
|
||||
externdef Entry12_16:dword
|
||||
externdef Entry13_16:dword
|
||||
externdef Entry14_16:dword
|
||||
externdef Entry15_16:dword
|
||||
externdef Entry16_16:dword
|
||||
|
||||
entryvec_table_16 dd 0, Entry2_16, Entry3_16, Entry4_16
|
||||
dd Entry5_16, Entry6_16, Entry7_16, Entry8_16
|
||||
dd Entry9_16, Entry10_16, Entry11_16, Entry12_16
|
||||
dd Entry13_16, Entry14_16, Entry15_16, Entry16_16
|
||||
|
||||
;-------------------------------------------------------
|
||||
; local variables for d_parta.s
|
||||
;-------------------------------------------------------
|
||||
public DP_Count, DP_u, DP_v, DP_32768, DP_Color, DP_Pix
|
||||
DP_Count dd 0
|
||||
DP_u dd 0
|
||||
DP_v dd 0
|
||||
DP_32768 dd 32768.0
|
||||
DP_Color dd 0
|
||||
DP_Pix dd 0
|
||||
|
||||
|
||||
;externdef DP_1x1:dword
|
||||
;externdef DP_2x2:dword
|
||||
;externdef DP_3x3:dword
|
||||
;externdef DP_4x4:dword
|
||||
|
||||
;DP_EntryTable dd 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
|
||||
;
|
||||
public advancetable, sstep, tstep, pspantemp, counttemp, jumptemp
|
||||
advancetable dd 0, 0
|
||||
sstep dd 0
|
||||
tstep dd 0
|
||||
|
||||
pspantemp dd 0
|
||||
counttemp dd 0
|
||||
jumptemp dd 0
|
||||
|
||||
; 1/2, 1/3, 1/4, 1/5, 1/6, and 1/7 in 0.32 form
|
||||
; public reciprocal_table, entryvec_table
|
||||
reciprocal_table dd 040000000h, 02aaaaaaah, 020000000h
|
||||
dd 019999999h, 015555555h, 012492492h
|
||||
|
||||
|
||||
; externdef Entry2_8:dword
|
||||
; externdef Entry3_8:dword
|
||||
; externdef Entry4_8:dword
|
||||
; externdef Entry5_8:dword
|
||||
; externdef Entry6_8:dword
|
||||
; externdef Entry7_8:dword
|
||||
; externdef Entry8_8:dword
|
||||
|
||||
;entryvec_table dd 0, Entry2_8, Entry3_8, Entry4_8
|
||||
; dd Entry5_8, Entry6_8, Entry7_8, Entry8_8
|
||||
|
||||
externdef Spr8Entry2_8:dword
|
||||
externdef Spr8Entry3_8:dword
|
||||
externdef Spr8Entry4_8:dword
|
||||
externdef Spr8Entry5_8:dword
|
||||
externdef Spr8Entry6_8:dword
|
||||
externdef Spr8Entry7_8:dword
|
||||
externdef Spr8Entry8_8:dword
|
||||
|
||||
public spr8entryvec_table
|
||||
spr8entryvec_table dd 0, Spr8Entry2_8, Spr8Entry3_8, Spr8Entry4_8
|
||||
dd Spr8Entry5_8, Spr8Entry6_8, Spr8Entry7_8, Spr8Entry8_8
|
||||
|
||||
|
||||
_DATA ENDS
|
||||
endif ; id386
|
||||
END
|
||||
123
ref_soft/rand1k.h
Normal file
123
ref_soft/rand1k.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// 1K random numbers in the range 0-255
|
||||
0, 144, 49, 207, 149, 122, 89, 229, 210, 191,
|
||||
44, 219, 181, 131, 77, 3, 23, 93, 37, 42,
|
||||
253, 114, 30, 1, 2, 96, 136, 146, 154, 155,
|
||||
42, 169, 115, 90, 14, 155, 200, 205, 133, 77,
|
||||
224, 186, 244, 236, 138, 36, 118, 60, 220, 53,
|
||||
199, 215, 255, 255, 156, 100, 68, 76, 215, 6,
|
||||
96, 23, 173, 14, 2, 235, 70, 69, 150, 176,
|
||||
214, 185, 124, 52, 190, 119, 117, 242, 190, 27,
|
||||
153, 98, 188, 155, 146, 92, 38, 57, 108, 205,
|
||||
132, 253, 192, 88, 43, 168, 125, 16, 179, 129,
|
||||
37, 243, 36, 231, 177, 77, 109, 18, 247, 174,
|
||||
39, 224, 210, 149, 48, 45, 209, 121, 39, 129,
|
||||
187, 103, 71, 145, 174, 193, 184, 121, 31, 94,
|
||||
213, 8, 132, 169, 109, 26, 243, 235, 140, 88,
|
||||
120, 95, 216, 81, 116, 69, 251, 76, 189, 145,
|
||||
50, 194, 214, 101, 128, 227, 7, 254, 146, 12,
|
||||
136, 49, 215, 160, 168, 50, 215, 31, 28, 190,
|
||||
80, 240, 73, 86, 35, 187, 213, 181, 153, 191,
|
||||
64, 36, 0, 15, 206, 218, 53, 29, 141, 3,
|
||||
29, 116, 192, 175, 139, 18, 111, 51, 178, 74,
|
||||
111, 59, 147, 136, 160, 41, 129, 246, 178, 236,
|
||||
48, 86, 45, 254, 117, 255, 24, 160, 24, 112,
|
||||
238, 12, 229, 74, 58, 196, 105, 51, 160, 154,
|
||||
115, 119, 153, 162, 218, 212, 159, 184, 144, 96,
|
||||
47, 188, 142, 231, 62, 48, 154, 178, 149, 89,
|
||||
126, 20, 189, 156, 158, 176, 205, 38, 147, 222,
|
||||
233, 157, 186, 11, 170, 249, 80, 145, 78, 44,
|
||||
27, 222, 217, 190, 39, 83, 20, 19, 164, 209,
|
||||
139, 114, 104, 76, 119, 128, 39, 82, 188, 80,
|
||||
211, 245, 223, 185, 76, 241, 32, 16, 200, 134,
|
||||
156, 244, 18, 224, 167, 82, 26, 129, 58, 74,
|
||||
235, 141, 169, 29, 126, 97, 127, 203, 130, 97,
|
||||
176, 136, 155, 101, 1, 181, 25, 159, 220, 125,
|
||||
191, 127, 97, 201, 141, 91, 244, 161, 45, 95,
|
||||
33, 190, 243, 156, 7, 84, 14, 163, 33, 216,
|
||||
221, 152, 184, 218, 3, 32, 181, 157, 55, 16,
|
||||
43, 159, 87, 81, 94, 169, 205, 206, 134, 156,
|
||||
204, 230, 37, 161, 103, 64, 34, 218, 16, 109,
|
||||
146, 77, 140, 57, 79, 28, 206, 34, 72, 201,
|
||||
229, 202, 190, 157, 92, 219, 58, 221, 58, 63,
|
||||
138, 252, 13, 20, 134, 109, 24, 66, 228, 59,
|
||||
37, 32, 238, 20, 12, 15, 86, 234, 102, 110,
|
||||
242, 214, 136, 215, 177, 101, 66, 1, 134, 244,
|
||||
102, 61, 149, 65, 175, 241, 111, 227, 1, 240,
|
||||
153, 201, 147, 36, 56, 98, 1, 106, 21, 168,
|
||||
218, 16, 207, 169, 177, 205, 135, 175, 36, 176,
|
||||
186, 199, 7, 222, 164, 180, 21, 141, 242, 15,
|
||||
70, 37, 251, 158, 74, 236, 94, 177, 55, 39,
|
||||
61, 133, 230, 27, 231, 113, 20, 200, 43, 249,
|
||||
198, 222, 53, 116, 0, 192, 29, 103, 79, 254,
|
||||
9, 64, 48, 63, 39, 158, 226, 240, 50, 199,
|
||||
165, 168, 232, 116, 235, 170, 38, 162, 145, 108,
|
||||
241, 138, 148, 137, 65, 101, 89, 9, 203, 50,
|
||||
17, 99, 151, 18, 50, 39, 164, 116, 154, 178,
|
||||
112, 175, 101, 213, 151, 51, 243, 224, 100, 252,
|
||||
47, 229, 147, 113, 160, 181, 12, 73, 66, 104,
|
||||
229, 181, 186, 229, 100, 101, 231, 79, 99, 146,
|
||||
90, 187, 190, 188, 189, 35, 51, 69, 174, 233,
|
||||
94, 132, 28, 232, 51, 132, 167, 112, 176, 23,
|
||||
20, 19, 7, 90, 78, 178, 36, 101, 17, 172,
|
||||
185, 50, 177, 157, 167, 139, 25, 139, 12, 249,
|
||||
118, 248, 186, 135, 174, 177, 95, 99, 12, 207,
|
||||
43, 15, 79, 200, 54, 82, 124, 2, 112, 130,
|
||||
155, 194, 102, 89, 215, 241, 159, 255, 13, 144,
|
||||
221, 99, 78, 72, 6, 156, 100, 4, 7, 116,
|
||||
219, 239, 102, 186, 156, 206, 224, 149, 152, 20,
|
||||
203, 118, 151, 150, 145, 208, 172, 87, 2, 68,
|
||||
87, 59, 197, 95, 222, 29, 185, 161, 228, 46,
|
||||
137, 230, 199, 247, 50, 230, 204, 244, 217, 227,
|
||||
160, 47, 157, 67, 64, 187, 201, 43, 182, 123,
|
||||
20, 206, 218, 31, 78, 146, 121, 195, 49, 186,
|
||||
254, 3, 165, 177, 44, 18, 70, 173, 214, 142,
|
||||
95, 199, 59, 163, 59, 52, 248, 72, 5, 196,
|
||||
38, 12, 2, 89, 164, 87, 106, 106, 23, 139,
|
||||
179, 86, 168, 224, 137, 145, 13, 119, 66, 109,
|
||||
221, 124, 22, 144, 181, 199, 221, 217, 75, 221,
|
||||
165, 191, 212, 195, 223, 232, 233, 133, 112, 27,
|
||||
90, 210, 109, 43, 0, 168, 198, 16, 22, 98,
|
||||
175, 206, 39, 36, 12, 88, 4, 250, 165, 13,
|
||||
234, 163, 110, 5, 62, 100, 167, 200, 5, 211,
|
||||
35, 162, 140, 251, 118, 54, 76, 200, 87, 123,
|
||||
155, 26, 252, 193, 38, 116, 182, 255, 198, 164,
|
||||
159, 242, 176, 74, 145, 74, 140, 182, 63, 139,
|
||||
126, 243, 171, 195, 159, 114, 204, 190, 253, 52,
|
||||
161, 232, 151, 235, 129, 125, 115, 227, 240, 46,
|
||||
64, 51, 187, 240, 160, 10, 164, 8, 142, 139,
|
||||
114, 15, 254, 32, 153, 12, 44, 169, 85, 80,
|
||||
167, 105, 109, 56, 173, 42, 127, 129, 205, 111,
|
||||
1, 86, 96, 32, 211, 187, 228, 164, 166, 131,
|
||||
187, 188, 245, 119, 92, 28, 231, 210, 116, 27,
|
||||
222, 194, 10, 106, 239, 17, 42, 54, 29, 151,
|
||||
30, 158, 148, 176, 187, 234, 171, 76, 207, 96,
|
||||
255, 197, 52, 43, 99, 46, 148, 50, 245, 48,
|
||||
97, 77, 30, 50, 11, 197, 194, 225, 0, 114,
|
||||
109, 205, 118, 126, 191, 61, 143, 23, 236, 228,
|
||||
219, 15, 125, 161, 191, 193, 65, 232, 202, 51,
|
||||
141, 13, 133, 202, 180, 6, 187, 141, 234, 224,
|
||||
204, 78, 101, 123, 13, 166, 0, 196, 193, 56,
|
||||
39, 14, 171, 8, 88, 178, 204, 111, 251, 162,
|
||||
75, 122, 223, 20, 25, 36, 36, 235, 79, 95,
|
||||
208, 11, 208, 61, 229, 65, 68, 53, 58, 216,
|
||||
223, 227, 216, 155, 10, 44, 47, 91, 115, 47,
|
||||
228, 159, 139, 233
|
||||
1498
ref_soft/ref_soft.001
Normal file
1498
ref_soft/ref_soft.001
Normal file
File diff suppressed because it is too large
Load Diff
2
ref_soft/ref_soft.def
Normal file
2
ref_soft/ref_soft.def
Normal file
@@ -0,0 +1,2 @@
|
||||
EXPORTS
|
||||
GetRefAPI
|
||||
1496
ref_soft/ref_soft.dsp
Normal file
1496
ref_soft/ref_soft.dsp
Normal file
File diff suppressed because it is too large
Load Diff
17
ref_soft/ref_soft.plg
Normal file
17
ref_soft/ref_soft.plg
Normal file
@@ -0,0 +1,17 @@
|
||||
--------------------Configuration: ref_soft - Win32 Release Alpha--------------------
|
||||
Begining build with project "G:\quake2\code\ref_soft\ref_soft.dsp", at root.
|
||||
Active configuration is Win32 (ALPHA) Dynamic-Link Library (based on Win32 (ALPHA) Dynamic-Link Library)
|
||||
|
||||
Project's tools are:
|
||||
"OLE Type Library Maker" with flags "/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 "
|
||||
"C/C++ Compiler for Alpha" with flags "/nologo /QA21164 /MT /Gt0 /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "C_ONLY" /Fp".\ReleaseAXP/ref_soft.pch" /YX /Fo".\ReleaseAXP/" /Fd".\ReleaseAXP/" /FD /QAieee1 /c "
|
||||
"Win32 Resource Compiler" with flags "/l 0x409 /d "NDEBUG" "
|
||||
"Browser Database Maker" with flags "/nologo /o"..\ReleaseAXP/ref_soft.bsc" "
|
||||
"COFF Linker for Alpha" with flags "kernel32.lib user32.lib gdi32.lib winmm.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"..\ReleaseAXP/ref_soft.pdb" /debug /machine:ALPHA /def:".\ref_soft.def" /out:"..\ReleaseAXP/ref_soft.dll" /implib:"..\ReleaseAXP/ref_soft.lib" "
|
||||
"Custom Build" with flags ""
|
||||
"<Component 0xa>" with flags ""
|
||||
|
||||
|
||||
|
||||
|
||||
ref_soft.dll - 0 error(s), 0 warning(s)
|
||||
Reference in New Issue
Block a user