// File: FreeSlave[P]vhlt/hlrad/trace.cpp
// Function: TestLine_r(int, float const*, float const*, int&, float*)
int             TestLine_r(const int node, const vec3_t start, const vec3_t stop
#ifdef HLRAD_WATERBLOCKLIGHT
						   , int &linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
						   , vec_t *skyhit
#endif
						   )
{
    tnode_t*        tnode;
    float           front, back;
    vec3_t          mid;
    float           frac;
    int             side;
    int             r;

#ifdef HLRAD_WATERBLOCKLIGHT
	if (node < 0)
	{
		if (node == linecontent)
			return CONTENTS_EMPTY;
#ifdef HLRAD_OPAQUEINSKY_FIX
		if (node == CONTENTS_SOLID)
		{
			return CONTENTS_SOLID;
		}
		if (node == CONTENTS_SKY)
		{
			if (skyhit)
			{
				VectorCopy (start, skyhit);
			}
			return CONTENTS_SKY;
		}
#else
		if (node == CONTENTS_SOLID || node == CONTENTS_SKY)
			return node;
#endif
		if (linecontent)
		{
			return CONTENTS_SOLID;
		}
		linecontent = node;
		return CONTENTS_EMPTY;
	}
#else
#ifdef HLRAD_OPAQUEINSKY_FIX
	if (node == CONTENTS_SKY)
	{
		VectorCopy (start, skyhit);
	}
#endif
	if (   (node == CONTENTS_SOLID) 
        || (node == CONTENTS_SKY  ) 
      /*|| (node == CONTENTS_NULL ) */
       )
		return node;

    if (node < 0)
        return CONTENTS_EMPTY; 
#endif

    tnode = &tnodes[node];
    switch (tnode->type)
    {
    case plane_x:
        front = start[0] - tnode->dist;
        back = stop[0] - tnode->dist;
        break;
    case plane_y:
        front = start[1] - tnode->dist;
        back = stop[1] - tnode->dist;
        break;
    case plane_z:
        front = start[2] - tnode->dist;
        back = stop[2] - tnode->dist;
        break;
    default:
        front = (start[0] * tnode->normal[0] + start[1] * tnode->normal[1] + start[2] * tnode->normal[2]) - tnode->dist;
        back = (stop[0] * tnode->normal[0] + stop[1] * tnode->normal[1] + stop[2] * tnode->normal[2]) - tnode->dist;
        break;
    }

#ifdef HLRAD_TestLine_EDGE_FIX
	if (front > ON_EPSILON/2 && back > ON_EPSILON/2)
	{
		return TestLine_r(tnode->children[0], start, stop
#ifdef HLRAD_WATERBLOCKLIGHT
			, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
			, skyhit
#endif
			);
	}
	if (front < -ON_EPSILON/2 && back < -ON_EPSILON/2)
	{
		return TestLine_r(tnode->children[1], start, stop
#ifdef HLRAD_WATERBLOCKLIGHT
			, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
			, skyhit
#endif
			);
	}
	if (fabs(front) <= ON_EPSILON && fabs(back) <= ON_EPSILON)
	{
		int r1 = TestLine_r(tnode->children[0], start, stop
#ifdef HLRAD_WATERBLOCKLIGHT
			, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
			, skyhit
#endif
			);
		if (r1 == CONTENTS_SOLID)
			return CONTENTS_SOLID;
		int r2 = TestLine_r(tnode->children[1], start, stop
#ifdef HLRAD_WATERBLOCKLIGHT
			, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
			, skyhit
#endif
			);
		if (r2 == CONTENTS_SOLID)
			return CONTENTS_SOLID;
		if (r1 == CONTENTS_SKY || r2 == CONTENTS_SKY)
			return CONTENTS_SKY;
		return CONTENTS_EMPTY;
	}
	side = (front - back) < 0;
	frac = front / (front - back);
	if (frac < 0) frac = 0;
	if (frac > 1) frac = 1;
	mid[0] = start[0] + (stop[0] - start[0]) * frac;
	mid[1] = start[1] + (stop[1] - start[1]) * frac;
	mid[2] = start[2] + (stop[2] - start[2]) * frac;
	r = TestLine_r(tnode->children[side], start, mid
#ifdef HLRAD_WATERBLOCKLIGHT
		, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
		, skyhit
#endif
		);
	if (r != CONTENTS_EMPTY)
		return r;
	return TestLine_r(tnode->children[!side], mid, stop
#ifdef HLRAD_WATERBLOCKLIGHT
		, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
		, skyhit
#endif
		);
#else //bug: light can go through edges of solid brushes
    if (front >= -ON_EPSILON && back >= -ON_EPSILON)
        return TestLine_r(tnode->children[0], start, stop
#ifdef HLRAD_WATERBLOCKLIGHT
		, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
		, skyhit
#endif
		);

    if (front < ON_EPSILON && back < ON_EPSILON)
        return TestLine_r(tnode->children[1], start, stop
#ifdef HLRAD_WATERBLOCKLIGHT
		, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
		, skyhit
#endif
		);

    side = front < 0;

    frac = front / (front - back);

    mid[0] = start[0] + (stop[0] - start[0]) * frac;
    mid[1] = start[1] + (stop[1] - start[1]) * frac;
    mid[2] = start[2] + (stop[2] - start[2]) * frac;

    r = TestLine_r(tnode->children[side], start, mid
#ifdef HLRAD_WATERBLOCKLIGHT
		, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
		, skyhit
#endif
		);
    if (r != CONTENTS_EMPTY)
        return r;
    return TestLine_r(tnode->children[!side], mid, stop
#ifdef HLRAD_WATERBLOCKLIGHT
		, linecontent
#endif
#ifdef HLRAD_OPAQUEINSKY_FIX
		, skyhit
#endif
		);
#endif
}

// Assembly:
subq $0x68, %rsp
movl %edi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movq %rdx, 0x50(%rsp)
movq %rcx, 0x48(%rsp)
movq %r8, 0x40(%rsp)
cmpl $0x0, 0x60(%rsp)
jge 0x626ba
movl 0x60(%rsp), %eax
movq 0x48(%rsp), %rcx
cmpl (%rcx), %eax
jne 0x62621
movl $0xffffffff, 0x64(%rsp) # imm = 0xFFFFFFFF
jmp 0x62b5f
cmpl $-0x2, 0x60(%rsp)
jne 0x62635
movl $0xfffffffe, 0x64(%rsp) # imm = 0xFFFFFFFE
jmp 0x62b5f
cmpl $-0x6, 0x60(%rsp)
jne 0x6268b
cmpq $0x0, 0x40(%rsp)
je 0x6267e
movq 0x58(%rsp), %rax
movss (%rax), %xmm0
movq 0x40(%rsp), %rax
movss %xmm0, (%rax)
movq 0x58(%rsp), %rax
movss 0x4(%rax), %xmm0
movq 0x40(%rsp), %rax
movss %xmm0, 0x4(%rax)
movq 0x58(%rsp), %rax
movss 0x8(%rax), %xmm0
movq 0x40(%rsp), %rax
movss %xmm0, 0x8(%rax)
movl $0xfffffffa, 0x64(%rsp) # imm = 0xFFFFFFFA
jmp 0x62b5f
movq 0x48(%rsp), %rax
cmpl $0x0, (%rax)
je 0x626a2
movl $0xfffffffe, 0x64(%rsp) # imm = 0xFFFFFFFE
jmp 0x62b5f
movl 0x60(%rsp), %ecx
movq 0x48(%rsp), %rax
movl %ecx, (%rax)
movl $0xffffffff, 0x64(%rsp) # imm = 0xFFFFFFFF
jmp 0x62b5f
movq 0x66cd427(%rip), %rax   # 0x672fae8
movslq 0x60(%rsp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xc(%rsp)
testl %eax, %eax
je 0x626fc
jmp 0x626e3
movl 0xc(%rsp), %eax
subl $0x1, %eax
je 0x62733
jmp 0x626ee
movl 0xc(%rsp), %eax
subl $0x2, %eax
je 0x6276c
jmp 0x627a5
movq 0x58(%rsp), %rax
movss (%rax), %xmm0
movq 0x38(%rsp), %rax
subss 0x10(%rax), %xmm0
movss %xmm0, 0x34(%rsp)
movq 0x50(%rsp), %rax
movss (%rax), %xmm0
movq 0x38(%rsp), %rax
subss 0x10(%rax), %xmm0
movss %xmm0, 0x30(%rsp)
jmp 0x6285b
movq 0x58(%rsp), %rax
movss 0x4(%rax), %xmm0
movq 0x38(%rsp), %rax
subss 0x10(%rax), %xmm0
movss %xmm0, 0x34(%rsp)
movq 0x50(%rsp), %rax
movss 0x4(%rax), %xmm0
movq 0x38(%rsp), %rax
subss 0x10(%rax), %xmm0
movss %xmm0, 0x30(%rsp)
jmp 0x6285b
movq 0x58(%rsp), %rax
movss 0x8(%rax), %xmm0
movq 0x38(%rsp), %rax
subss 0x10(%rax), %xmm0
movss %xmm0, 0x34(%rsp)
movq 0x50(%rsp), %rax
movss 0x8(%rax), %xmm0
movq 0x38(%rsp), %rax
subss 0x10(%rax), %xmm0
movss %xmm0, 0x30(%rsp)
jmp 0x6285b
movq 0x58(%rsp), %rax
movss (%rax), %xmm1
movq 0x38(%rsp), %rax
movss 0x4(%rax), %xmm2
movq 0x58(%rsp), %rax
movss 0x4(%rax), %xmm0
movq 0x38(%rsp), %rax
mulss 0x8(%rax), %xmm0
mulss %xmm2, %xmm1
addss %xmm0, %xmm1
movq 0x58(%rsp), %rax
movss 0x8(%rax), %xmm0
movq 0x38(%rsp), %rax
movss 0xc(%rax), %xmm2
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movq 0x38(%rsp), %rax
subss 0x10(%rax), %xmm0
movss %xmm0, 0x34(%rsp)
movq 0x50(%rsp), %rax
movss (%rax), %xmm1
movq 0x38(%rsp), %rax
movss 0x4(%rax), %xmm2
movq 0x50(%rsp), %rax
movss 0x4(%rax), %xmm0
movq 0x38(%rsp), %rax
mulss 0x8(%rax), %xmm0
mulss %xmm2, %xmm1
addss %xmm0, %xmm1
movq 0x50(%rsp), %rax
movss 0x8(%rax), %xmm0
movq 0x38(%rsp), %rax
movss 0xc(%rax), %xmm2
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movq 0x38(%rsp), %rax
subss 0x10(%rax), %xmm0
movss %xmm0, 0x30(%rsp)
movss 0x34(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0xafdb(%rip), %xmm1     # 0x6d848
ucomisd %xmm1, %xmm0
jbe 0x628b5
movss 0x30(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0xafc3(%rip), %xmm1     # 0x6d848
ucomisd %xmm1, %xmm0
jbe 0x628b5
movq 0x38(%rsp), %rax
movl 0x14(%rax), %edi
movq 0x58(%rsp), %rsi
movq 0x50(%rsp), %rdx
movq 0x48(%rsp), %rcx
movq 0x40(%rsp), %r8
callq 0x625e0
movl %eax, 0x64(%rsp)
jmp 0x62b5f
movss 0x34(%rsp), %xmm0
cvtss2sd %xmm0, %xmm1
movsd 0xf349(%rip), %xmm0     # 0x71c10
ucomisd %xmm1, %xmm0
jbe 0x6290f
movss 0x30(%rsp), %xmm0
cvtss2sd %xmm0, %xmm1
movsd 0xf331(%rip), %xmm0     # 0x71c10
ucomisd %xmm1, %xmm0
jbe 0x6290f
movq 0x38(%rsp), %rax
movl 0x18(%rax), %edi
movq 0x58(%rsp), %rsi
movq 0x50(%rsp), %rdx
movq 0x48(%rsp), %rcx
movq 0x40(%rsp), %r8
callq 0x625e0
movl %eax, 0x64(%rsp)
jmp 0x62b5f
movss 0x34(%rsp), %xmm0
callq 0x11ce0
cvtss2sd %xmm0, %xmm1
movsd 0xaeba(%rip), %xmm0     # 0x6d7e0
ucomisd %xmm1, %xmm0
jb 0x629eb
movss 0x30(%rsp), %xmm0
callq 0x11ce0
cvtss2sd %xmm0, %xmm1
movsd 0xae99(%rip), %xmm0     # 0x6d7e0
ucomisd %xmm1, %xmm0
jb 0x629eb
movq 0x38(%rsp), %rax
movl 0x14(%rax), %edi
movq 0x58(%rsp), %rsi
movq 0x50(%rsp), %rdx
movq 0x48(%rsp), %rcx
movq 0x40(%rsp), %r8
callq 0x625e0
movl %eax, 0x14(%rsp)
cmpl $-0x2, 0x14(%rsp)
jne 0x6298a
movl $0xfffffffe, 0x64(%rsp) # imm = 0xFFFFFFFE
jmp 0x62b5f
movq 0x38(%rsp), %rax
movl 0x18(%rax), %edi
movq 0x58(%rsp), %rsi
movq 0x50(%rsp), %rdx
movq 0x48(%rsp), %rcx
movq 0x40(%rsp), %r8
callq 0x625e0
movl %eax, 0x10(%rsp)
cmpl $-0x2, 0x10(%rsp)
jne 0x629c3
movl $0xfffffffe, 0x64(%rsp) # imm = 0xFFFFFFFE
jmp 0x62b5f
cmpl $-0x6, 0x14(%rsp)
je 0x629d1
cmpl $-0x6, 0x10(%rsp)
jne 0x629de
movl $0xfffffffa, 0x64(%rsp) # imm = 0xFFFFFFFA
jmp 0x62b5f
movl $0xffffffff, 0x64(%rsp) # imm = 0xFFFFFFFF
jmp 0x62b5f
movss 0x34(%rsp), %xmm1
subss 0x30(%rsp), %xmm1
xorps %xmm0, %xmm0
ucomiss %xmm1, %xmm0
seta %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x1c(%rsp)
movss 0x34(%rsp), %xmm0
movss 0x34(%rsp), %xmm1
subss 0x30(%rsp), %xmm1
divss %xmm1, %xmm0
movss %xmm0, 0x20(%rsp)
xorps %xmm0, %xmm0
ucomiss 0x20(%rsp), %xmm0
jbe 0x62a38
xorps %xmm0, %xmm0
movss %xmm0, 0x20(%rsp)
movss 0x20(%rsp), %xmm0
movss 0x7606(%rip), %xmm1     # 0x6a04c
ucomiss %xmm1, %xmm0
jbe 0x62a59
movss 0x75f9(%rip), %xmm0     # 0x6a04c
movss %xmm0, 0x20(%rsp)
movq 0x58(%rsp), %rax
movss (%rax), %xmm1
movq 0x50(%rsp), %rax
movss (%rax), %xmm0
movq 0x58(%rsp), %rax
subss (%rax), %xmm0
movss 0x20(%rsp), %xmm2
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x24(%rsp)
movq 0x58(%rsp), %rax
movss 0x4(%rax), %xmm1
movq 0x50(%rsp), %rax
movss 0x4(%rax), %xmm0
movq 0x58(%rsp), %rax
subss 0x4(%rax), %xmm0
movss 0x20(%rsp), %xmm2
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x28(%rsp)
movq 0x58(%rsp), %rax
movss 0x8(%rax), %xmm1
movq 0x50(%rsp), %rax
movss 0x8(%rax), %xmm0
movq 0x58(%rsp), %rax
subss 0x8(%rax), %xmm0
movss 0x20(%rsp), %xmm2
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x2c(%rsp)
movq 0x38(%rsp), %rax
movslq 0x1c(%rsp), %rcx
movl 0x14(%rax,%rcx,4), %edi
movq 0x58(%rsp), %rsi
leaq 0x24(%rsp), %rdx
movq 0x48(%rsp), %rcx
movq 0x40(%rsp), %r8
callq 0x625e0
movl %eax, 0x18(%rsp)
cmpl $-0x1, 0x18(%rsp)
je 0x62b28
movl 0x18(%rsp), %eax
movl %eax, 0x64(%rsp)
jmp 0x62b5f
movq 0x38(%rsp), %rax
cmpl $0x0, 0x1c(%rsp)
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movzbl %cl, %ecx
movl 0x14(%rax,%rcx,4), %edi
leaq 0x24(%rsp), %rsi
movq 0x50(%rsp), %rdx
movq 0x48(%rsp), %rcx
movq 0x40(%rsp), %r8
callq 0x625e0
movl %eax, 0x64(%rsp)
movl 0x64(%rsp), %eax
addq $0x68, %rsp
retq
nopl (%rax,%rax)