📄 r_edgea.pas
字号:
unit r_edgea;
{----------------------------------------------------------------------------}
{ }
{ File(s): r_edgea.asm }
{ }
{ Initial conversion by : CodeFusion (michael@skovslund.dk) }
{ Initial conversion on : 16-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: }
{ r_local, }
{ r_main, }
{ cvar, }
{ r_model, }
{----------------------------------------------------------------------------}
{ These variables has been moved from Edge.pas to this one because otherwise}
{ we would have had circular references. }
{ }
{ edge_head : edge_t; }
{ edge_tail : edge_t; }
{ edge_aftertail : edge_t; }
{ edge_head_u_shift20 : Integer; }
{ edge_tail_u_shift20 : Integer; }
{ current_iv : Integer; }
{ fv : Single; }
{ span_p : espan_p; }
{ surfaces : surf_p; }
{----------------------------------------------------------------------------}
{ * TODO: }
{ Types and variables has been created here for the source to compile. }
{ Remove all lines marked with (*R*). }
{----------------------------------------------------------------------------}
interface
uses
qasm_inc,
r_local,
r_main,
r_model,
r_varsa;
type
TEdgeCode = procedure;
var
edge_head: edge_t;
edge_tail: edge_t;
edge_aftertail: edge_t;
edge_head_u_shift20: Integer;
edge_tail_u_shift20: Integer;
current_iv: Integer;
fv: Single;
span_p: espan_p;
surfaces: surf_p;
{$IFDEF id386}
var
R_EdgeCodeStart: TEdgeCode;
R_EdgeCodeEnd: TEdgeCode;
procedure R_InsertNewEdges(edgestoadd: edge_p; edgelist: edge_p);
procedure R_RemoveEdges(pedge: edge_p);
procedure R_StepActiveU(pedge: edge_p);
procedure R_GenerateSpans;
procedure R_SurfacePatch;
{$ENDIF}
implementation
{$IFDEF id386}
var
Ltemp: Integer; // 0
float_1_div_0100000h: Single; //035800000h ; 1.0/(float)0x100000
float_point_999: Single; // 0.999
float_1_point_001: Single; // 1.001
// FIX, for code self modification, used in original asm code.
LPatch0_Value: Pointer;
LPatch2_Value: Pointer;
LPatch3_Value: Pointer;
LPatch4_Value: Pointer;
procedure R_InsertNewEdges(edgestoadd: edge_p; edgelist: edge_p);
const
edgestoadd_ = 4 + 8; //note odd stack offsets because of interleaving
edgelist_ = 8 + 12; //with pushes
asm
@_R_EdgeCodeStart:
push edi
push esi // preserve register variables
mov edx,ds:dword ptr[edgestoadd_+ebp]
push ebx
mov ecx,ds:dword ptr[edgelist_+ebp]
@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
end;
procedure R_RemoveEdges(pedge: edge_p);
const
predge = 4 + 4;
asm
push ebx
mov eax,ds:dword ptr[predge+ebp]
@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
jmp @Done
@Lre_done:
mov ds:dword ptr[et_next+edx],ecx
@Done:
pop ebx
end;
procedure R_StepActiveU(pedge: edge_p);
const
pedgelist = 4 + 4; // note odd stack offset because of interleaving
// with pushes
asm
push edi
mov edx,ds:dword ptr[pedgelist+ebp]
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
end;
procedure R_GenerateSpans;
const
surf = 4; // note this is loaded before any pushes
asm
jmp @_R_GenerateSpans
{$align 4}
// Called within this function
@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
mov edx,ds:dword ptr[LPatch0_Value] // 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
// Entry point for this function.
{$align 4}
@_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -