📄 r_spr8.pas
字号:
unit r_spr8;
{----------------------------------------------------------------------------}
{ }
{ File(s): block16.inc }
{ }
{ Initial conversion by : CodeFusion (Michael@Skovslund.dk) }
{ Initial conversion on : 22-July-2002 }
{ }
{ This File contains part of convertion of Quake2 source to ObjectPascal. }
{ More information about this project can be found at: }
{ http://www.sulaco.co.za/quake2/ }
{ }
{ 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. }
{ }
{----------------------------------------------------------------------------}
{ Updated on : }
{ Updated by : }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ None. }
{----------------------------------------------------------------------------}
{ * TODO/NOTES: }
{ 1) I have added a new procedure which (in time) will fill the array: }
{ spr8entryvec_table. }
{----------------------------------------------------------------------------}
interface
uses
qasm_inc,
d_if_inc,
r_varsa;
{$IFDEF id386}
procedure D_SpriteDrawSpansXXX; cdecl;
{$ENDIF}
implementation
uses
r_misc;
{$IFNDEF id386}
procedure D_SpriteDrawSpansXXX(pspans); cdecl;
const
pspans = 4 + 16;
asm
{$align 4}
jmp @EntryPoint
// 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
@EntryPoint:
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]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -