// File: /workspace/github_cpp_makefile_star2_O3/FreeSlave[P]vhlt/hlvis/flow.cpp
// Function: RecursiveLeafFlow(int, threaddata_t const*, pstack_s const*)
inline static void     RecursiveLeafFlow(const int leafnum, const threaddata_t* const thread, const pstack_t* const prevstack)
{
    pstack_t        stack;
    leaf_t*         leaf;

    leaf = &g_leafs[leafnum];
#ifdef USE_CHECK_STACK
    CheckStack(leaf, thread);
#endif

    {
        const unsigned offset = leafnum >> 3;
        const unsigned bit = (1 << (leafnum & 7));
    
        // mark the leaf as visible
        if (!(thread->leafvis[offset] & bit))
        {
            thread->leafvis[offset] |= bit;
            thread->base->numcansee++;
        }
    }

#ifdef USE_CHECK_STACK
    prevstack->next = &stack;
    stack.next = NULL;
#endif
    stack.head = prevstack->head;
    stack.leaf = leaf;
    stack.portal = NULL;
#ifdef RVIS_LEVEL_2
    stack.clipPlaneCount = -1;
    stack.clipPlane = NULL;
#endif

    // check all portals for flowing into other leafs       
    unsigned i;
    portal_t** plist = leaf->portals;

    for (i = 0; i < leaf->numportals; i++, plist++)
    {
        portal_t* p = *plist;

#if ZHLT_ZONES
        portal_t * head_p = stack.head->portal;
        if (g_Zones->check(head_p->zone, p->zone))
        {
            continue;
        }
#endif

        {
            const unsigned offset = p->leaf >> 3;
            const unsigned bit = 1 << (p->leaf & 7);

            if (!(stack.head->mightsee[offset] & bit))
            {
                continue;                                      // can't possibly see it
            }
            if (!(prevstack->mightsee[offset] & bit))
            {
                continue;                                      // can't possibly see it
            }
        }

        // if the portal can't see anything we haven't allready seen, skip it
        {
            long* test;

            if (p->status == stat_done)
            {
                test = (long*)p->visbits;
            }
            else
            {
                test = (long*)p->mightsee;
            }
    
            {
                const int bitlongs = g_bitlongs;

                {
                    long* prevmight = (long*)prevstack->mightsee;
                    long* might = (long*)stack.mightsee;
                
                    unsigned j;
                    for (j = 0; j < bitlongs; j++, test++, might++, prevmight++)
                    {
                        (*might) = (*prevmight) & (*test);
                    }
                }
        
                {
                    long* might = (long*)stack.mightsee;
                    long* vis = (long*)thread->leafvis;
                    unsigned j;
                    for (j = 0; j < bitlongs; j++, might++, vis++)
                    {
                        if ((*might) & ~(*vis))
                        {
                            break;
                        }
                    }
            
                    if (j == g_bitlongs)
                    {                                                  // can't see anything new
                        continue;
                    }
                }
            }
        }

        // get plane of portal, point normal into the neighbor leaf
        stack.portalplane = &p->plane;
        plane_t             backplane;
        VectorSubtract(vec3_origin, p->plane.normal, backplane.normal);
        backplane.dist = -p->plane.dist;

        if (VectorCompare(prevstack->portalplane->normal, backplane.normal))
        {
            continue;                                      // can't go out a coplanar face
        }

        stack.portal = p;
#ifdef USE_CHECK_STACK
        stack.next = NULL;
#endif
        stack.freewindings[0] = 1;
        stack.freewindings[1] = 1;
        stack.freewindings[2] = 1;

        stack.pass = ChopWinding(p->winding, &stack, thread->pstack_head.portalplane);
        if (!stack.pass)
        {
            continue;
        }

        stack.source = ChopWinding(prevstack->source, &stack, &backplane);
        if (!stack.source)
        {
            continue;
        }

        if (!prevstack->pass)
        {                                                  // the second leaf can only be blocked if coplanar
            RecursiveLeafFlow(p->leaf, thread, &stack);
            continue;
        }

        stack.pass = ChopWinding(stack.pass, &stack, prevstack->portalplane);
        if (!stack.pass)
        {
            continue;
        }

#ifdef RVIS_LEVEL_2
        if (stack.clipPlaneCount == -1)
        {
            stack.clipPlaneCount = 0;
            stack.clipPlane = (plane_t*)alloca(sizeof(plane_t) * prevstack->source->numpoints * prevstack->pass->numpoints);

            ClipToSeperators(prevstack->source, prevstack->pass, NULL, false, &stack);
            ClipToSeperators(prevstack->pass, prevstack->source, NULL, true, &stack);
        }

        if (stack.clipPlaneCount > 0)
        {
            unsigned j;
            for (j = 0; j < stack.clipPlaneCount && stack.pass != NULL; j++)
            {
                stack.pass = ChopWinding(stack.pass, &stack, &(stack.clipPlane[j]));
            }

            if (stack.pass == NULL)
            continue;
        }
#else

        stack.pass = ClipToSeperators(stack.source, prevstack->pass, stack.pass, false, &stack);
        if (!stack.pass)
        {
            continue;
        }

        stack.pass = ClipToSeperators(prevstack->pass, stack.source, stack.pass, true, &stack);
        if (!stack.pass)
        {
            continue;
        }
#endif

        if (g_fullvis)
        {
            stack.source = ClipToSeperators(stack.pass, prevstack->pass, stack.source, false, &stack);
            if (!stack.source)
            {
                continue;
            }

            stack.source = ClipToSeperators(prevstack->pass, stack.pass, stack.source, true, &stack);
            if (!stack.source)
            {
                continue;
            }
        }

        // flow through it for real
        RecursiveLeafFlow(p->leaf, thread, &stack);
    }

#ifdef RVIS_LEVEL_2
#if 0
    if (stack.clipPlane != NULL)
    {
        free(stack.clipPlane);
    }
#endif
#endif
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1528, %rsp           # imm = 0x1528
movq %rdx, %rbx
movq %rsi, %r14
leaq 0x2092e93(%rip), %r8    # 0x209f770
movslq %edi, %rdi
imulq $0x810, %rdi, %r13      # imm = 0x810
movl %edi, %ecx
andb $0x7, %cl
movl $0x1, %eax
shll %cl, %eax
movl %edi, %ecx
sarl $0x3, %ecx
movq (%rsi), %rdx
movzbl (%rdx,%rcx), %esi
andl $0x7, %edi
addq (%r8), %r13
btl %edi, %esi
jb 0xc917
orb %sil, %al
movb %al, (%rdx,%rcx)
movq 0x8(%r14), %rax
incl 0x3c(%rax)
movq 0x1000(%rbx), %rax
movq %rax, -0x550(%rbp)
movq %r13, -0x548(%rbp)
xorl %r12d, %r12d
movq %r12, -0x540(%rbp)
movl $0xffffffff, -0x80(%rbp) # imm = 0xFFFFFFFF
movq %r12, -0x78(%rbp)
movl (%r13), %eax
testl %eax, %eax
je 0xcd76
leaq 0x10(%r13), %r15
leaq 0x7498(%rip), %rcx      # 0x13df0
movsd (%rcx), %xmm0
movaps %xmm0, -0x70(%rbp)
movss 0x8(%rcx), %xmm0
movss %xmm0, -0x34(%rbp)
leaq 0x2092e2b(%rip), %r8    # 0x209f79c
movaps 0x8938(%rip), %xmm2     # 0x152b0
movsd 0x8af0(%rip), %xmm3     # 0x15470
movq (%r15), %r9
movl 0x10(%r9), %edi
movl %edi, %edx
sarl $0x3, %edx
movl %edi, %ecx
andb $0x7, %cl
movl $0x1, %esi
shll %cl, %esi
movq -0x550(%rbp), %rcx
movzbl (%rcx,%rdx), %ecx
andl $0x7, %edi
btl %edi, %ecx
jae 0xcd66
movzbl (%rbx,%rdx), %ecx
testl %ecx, %esi
je 0xcd66
movl (%r8), %ecx
xorl %edx, %edx
testq %rcx, %rcx
je 0xca0d
cmpl $0x2, 0x20(%r9)
setne %dl
movq 0x28(%r9,%rdx,8), %rdx
xorl %esi, %esi
movq (%rdx,%rsi,8), %rdi
andq (%rbx,%rsi,8), %rdi
movq %rdi, -0x1550(%rbp,%rsi,8)
incq %rsi
cmpl %esi, %ecx
jne 0xc9d4
movq (%r14), %rsi
xorl %edx, %edx
movq (%rsi,%rdx,8), %rdi
notq %rdi
testq %rdi, -0x1550(%rbp,%rdx,8)
jne 0xca0d
incq %rdx
cmpl %edx, %ecx
jne 0xc9f0
jmp 0xcd66
cmpl %ecx, %edx
je 0xcd66
movq %r9, -0x88(%rbp)
movsd (%r9), %xmm0
movaps -0x70(%rbp), %xmm1
subps %xmm0, %xmm1
movlps %xmm1, -0x48(%rbp)
movss -0x34(%rbp), %xmm0
subss 0x8(%r9), %xmm0
movss %xmm0, -0x40(%rbp)
movss 0xc(%r9), %xmm0
xorps 0x5637(%rip), %xmm0     # 0x12080
movss %xmm0, -0x3c(%rbp)
movq 0x14c8(%rbx), %rax
movss (%rax), %xmm0
subss %xmm1, %xmm0
andps %xmm2, %xmm0
cvtss2sd %xmm0, %xmm0
ucomisd %xmm3, %xmm0
jbe 0xcd31
movq %r9, -0x540(%rbp)
movw $0x101, -0x90(%rbp)     # imm = 0x101
movb $0x1, -0x8e(%rbp)
movq 0x18(%r9), %rdi
movq 0x14d8(%r14), %rdx
leaq -0x1550(%rbp), %rsi
movq %r9, -0x30(%rbp)
callq 0xeafb
movsd 0x89c8(%rip), %xmm3     # 0x15470
movaps 0x8801(%rip), %xmm2     # 0x152b0
leaq 0x2092ce6(%rip), %r8    # 0x209f79c
movq %rax, -0x530(%rbp)
testq %rax, %rax
je 0xcd62
movq 0x1018(%rbx), %rdi
leaq -0x1550(%rbp), %rsi
leaq -0x48(%rbp), %rdx
callq 0xeafb
movq -0x30(%rbp), %rcx
movsd 0x8987(%rip), %xmm3     # 0x15470
movaps 0x87c0(%rip), %xmm2     # 0x152b0
leaq 0x2092ca5(%rip), %r8    # 0x209f79c
movq %rax, -0x538(%rbp)
testq %rax, %rax
je 0xcd62
cmpq $0x0, 0x1020(%rbx)
je 0xcd07
movq -0x530(%rbp), %rdi
movq 0x14c8(%rbx), %rdx
leaq -0x1550(%rbp), %rsi
callq 0xeafb
movq -0x30(%rbp), %rcx
movsd 0x8935(%rip), %xmm3     # 0x15470
movaps 0x876e(%rip), %xmm2     # 0x152b0
leaq 0x2092c53(%rip), %r8    # 0x209f79c
movq %rax, -0x530(%rbp)
testq %rax, %rax
je 0xcd62
movl -0x80(%rbp), %eax
cmpl $-0x1, %eax
jne 0xcbe5
movl $0x0, -0x80(%rbp)
movq 0x1018(%rbx), %rdi
movq 0x1020(%rbx), %rsi
movslq 0x4(%rdi), %rax
movslq 0x4(%rsi), %rcx
imulq %rax, %rcx
shlq $0x4, %rcx
movq %rsp, %rax
subq %rcx, %rax
movq %rax, %rsp
movq %rax, -0x78(%rbp)
xorl %edx, %edx
xorl %ecx, %ecx
leaq -0x1550(%rbp), %r8
callq 0xe65f
movq 0x1018(%rbx), %rsi
movq 0x1020(%rbx), %rdi
xorl %edx, %edx
movl $0x1, %ecx
leaq -0x1550(%rbp), %r8
callq 0xe65f
movq -0x30(%rbp), %rcx
movsd 0x889c(%rip), %xmm3     # 0x15470
movaps 0x86d5(%rip), %xmm2     # 0x152b0
leaq 0x2092bba(%rip), %r8    # 0x209f79c
movl -0x80(%rbp), %eax
testl %eax, %eax
jle 0xcc66
movq -0x530(%rbp), %rax
testq %rax, %rax
je 0xcd62
movq %r13, -0x50(%rbp)
movq %r14, -0x58(%rbp)
movl $0x1, %r14d
xorl %r13d, %r13d
movq -0x78(%rbp), %rdx
addq %r13, %rdx
movq %rax, %rdi
leaq -0x1550(%rbp), %rsi
callq 0xeafb
movq %rax, -0x530(%rbp)
movl -0x80(%rbp), %ecx
cmpq %rcx, %r14
jae 0xcc3b
addq $0x10, %r13
incq %r14
testq %rax, %rax
jne 0xcc0a
testq %rax, %rax
movq -0x58(%rbp), %r14
movq -0x50(%rbp), %r13
leaq 0x2092b4f(%rip), %r8    # 0x209f79c
movaps 0x865c(%rip), %xmm2     # 0x152b0
movsd 0x8814(%rip), %xmm3     # 0x15470
movq -0x30(%rbp), %rcx
je 0xcd62
leaq 0x2092b34(%rip), %rax   # 0x209f7a1
cmpb $0x1, (%rax)
jne 0xcd07
movq -0x538(%rbp), %rdx
movq -0x530(%rbp), %rdi
movq 0x1020(%rbx), %rsi
xorl %ecx, %ecx
leaq -0x1550(%rbp), %r8
callq 0xe65f
movsd 0x87cf(%rip), %xmm3     # 0x15470
movaps 0x8608(%rip), %xmm2     # 0x152b0
leaq 0x2092aed(%rip), %r8    # 0x209f79c
movq %rax, -0x538(%rbp)
testq %rax, %rax
je 0xcd62
movq 0x1020(%rbx), %rdi
movq -0x530(%rbp), %rsi
movq %rax, %rdx
movl $0x1, %ecx
leaq -0x1550(%rbp), %r8
callq 0xe65f
movq -0x30(%rbp), %rcx
movsd 0x8783(%rip), %xmm3     # 0x15470
movaps 0x85bc(%rip), %xmm2     # 0x152b0
leaq 0x2092aa1(%rip), %r8    # 0x209f79c
movq %rax, -0x538(%rbp)
testq %rax, %rax
je 0xcd62
movl 0x10(%rcx), %edi
movq %r14, %rsi
leaq -0x1550(%rbp), %rdx
callq 0xc8bc
movsd 0x874f(%rip), %xmm3     # 0x15470
movaps 0x8588(%rip), %xmm2     # 0x152b0
leaq 0x2092a6d(%rip), %r8    # 0x209f79c
jmp 0xcd62
xorl %ecx, %ecx
cmpq $0x2, %rcx
je 0xcd62
movss 0x4(%rax,%rcx,4), %xmm0
subss -0x44(%rbp,%rcx,4), %xmm0
andps %xmm2, %xmm0
cvtss2sd %xmm0, %xmm0
incq %rcx
ucomisd %xmm3, %xmm0
jbe 0xcd33
decq %rcx
cmpq $0x1, %rcx
jbe 0xca6e
movl (%r13), %eax
incl %r12d
addq $0x8, %r15
cmpl %eax, %r12d
jb 0xc980
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq