// File: FreeSlave[P]vhlt/hlbsp/solidbsp.cpp
// Function: DivideSurface(surface_s*, plane_t const*, surface_s**, surface_s**)
static void     DivideSurface(surface_t* in, const dplane_t* const split, surface_t** front, surface_t** back)
{
    face_t*         facet;
    face_t*         next;
    face_t*         frontlist;
    face_t*         backlist;
    face_t*         frontfrag;
    face_t*         backfrag;
    surface_t*      news;
    dplane_t*       inplane;

    inplane = &g_dplanes[in->planenum];

    // parallel case is easy

    if (inplane->normal[0] == split->normal[0]
     && inplane->normal[1] == split->normal[1]
     && inplane->normal[2] == split->normal[2])
    {
        if (inplane->dist > split->dist)
        {
            *front = in;
            *back = NULL;
        }
        else if (inplane->dist < split->dist)
        {
            *front = NULL;
            *back = in;
        }
        else
        {                                                  // split the surface into front and back
            frontlist = NULL;
            backlist = NULL;
            for (facet = in->faces; facet; facet = next)
            {
                next = facet->next;
                if (facet->planenum & 1)
                {
                    facet->next = backlist;
                    backlist = facet;
                }
                else
                {
                    facet->next = frontlist;
                    frontlist = facet;
                }
            }
            goto makesurfs;
        }
        return;
    }

    // do a real split.  may still end up entirely on one side
    // OPTIMIZE: use bounding box for fast test
    frontlist = NULL;
    backlist = NULL;

    for (facet = in->faces; facet; facet = next)
    {
        next = facet->next;
        SplitFace(facet, split, &frontfrag, &backfrag);
        if (frontfrag)
        {
            frontfrag->next = frontlist;
            frontlist = frontfrag;
        }
        if (backfrag)
        {
            backfrag->next = backlist;
            backlist = backfrag;
        }
    }

    // if nothing actually got split, just move the in plane
makesurfs:
#ifdef HLBSP_REMOVECOLINEARPOINTS
	if (frontlist == NULL && backlist == NULL)
	{
		*front = NULL;
		*back = NULL;
		return;
	}
#endif
    if (frontlist == NULL)
    {
        *front = NULL;
        *back = in;
        in->faces = backlist;
        return;
    }

    if (backlist == NULL)
    {
        *front = in;
        *back = NULL;
        in->faces = frontlist;
        return;
    }

    // stuff got split, so allocate one new surface and reuse in
    news = AllocSurface();
    *news = *in;
    news->faces = backlist;
    *back = news;

    in->faces = frontlist;
    *front = in;

    // recalc bboxes and flags
    CalcSurfaceInfo(news);
    CalcSurfaceInfo(in);
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movq %rdx, 0x50(%rsp)
movq %rcx, 0x48(%rsp)
movq 0x60(%rsp), %rax
movslq 0x8(%rax), %rcx
leaq 0x20c1958(%rip), %rax   # 0x20efa30
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, 0x8(%rsp)
movq 0x8(%rsp), %rax
movsd (%rax), %xmm0
movq 0x58(%rsp), %rax
ucomisd (%rax), %xmm0
jne 0x2e23d
jp 0x2e23d
movq 0x8(%rsp), %rax
movsd 0x8(%rax), %xmm0
movq 0x58(%rsp), %rax
ucomisd 0x8(%rax), %xmm0
jne 0x2e23d
jp 0x2e23d
movq 0x8(%rsp), %rax
movsd 0x10(%rax), %xmm0
movq 0x58(%rsp), %rax
ucomisd 0x10(%rax), %xmm0
jne 0x2e23d
jp 0x2e23d
movq 0x8(%rsp), %rax
movsd 0x30(%rax), %xmm0
movq 0x58(%rsp), %rax
ucomisd 0x30(%rax), %xmm0
jbe 0x2e176
movq 0x60(%rsp), %rcx
movq 0x50(%rsp), %rax
movq %rcx, (%rax)
movq 0x48(%rsp), %rax
movq $0x0, (%rax)
jmp 0x2e238
movq 0x8(%rsp), %rax
movsd 0x30(%rax), %xmm1
movq 0x58(%rsp), %rax
movsd 0x30(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2e1ae
movq 0x50(%rsp), %rax
movq $0x0, (%rax)
movq 0x60(%rsp), %rcx
movq 0x48(%rsp), %rax
movq %rcx, (%rax)
jmp 0x2e236
movq $0x0, 0x30(%rsp)
movq $0x0, 0x28(%rsp)
movq 0x60(%rsp), %rax
movq 0x48(%rax), %rax
movq %rax, 0x40(%rsp)
cmpq $0x0, 0x40(%rsp)
je 0x2e231
movq 0x40(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x38(%rsp)
movq 0x40(%rsp), %rax
movl 0x8(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x2e20c
movq 0x28(%rsp), %rcx
movq 0x40(%rsp), %rax
movq %rcx, (%rax)
movq 0x40(%rsp), %rax
movq %rax, 0x28(%rsp)
jmp 0x2e223
movq 0x30(%rsp), %rcx
movq 0x40(%rsp), %rax
movq %rcx, (%rax)
movq 0x40(%rsp), %rax
movq %rax, 0x30(%rsp)
jmp 0x2e225
movq 0x38(%rsp), %rax
movq %rax, 0x40(%rsp)
jmp 0x2e1ce
jmp 0x2e2d9
jmp 0x2e238
jmp 0x2e3d3
movq $0x0, 0x30(%rsp)
movq $0x0, 0x28(%rsp)
movq 0x60(%rsp), %rax
movq 0x48(%rax), %rax
movq %rax, 0x40(%rsp)
cmpq $0x0, 0x40(%rsp)
je 0x2e2d7
movq 0x40(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x38(%rsp)
movq 0x40(%rsp), %rdi
movq 0x58(%rsp), %rsi
leaq 0x20(%rsp), %rdx
leaq 0x18(%rsp), %rcx
callq 0x23e20
cmpq $0x0, 0x20(%rsp)
je 0x2e2aa
movq 0x30(%rsp), %rcx
movq 0x20(%rsp), %rax
movq %rcx, (%rax)
movq 0x20(%rsp), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, 0x18(%rsp)
je 0x2e2c9
movq 0x28(%rsp), %rcx
movq 0x18(%rsp), %rax
movq %rcx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, 0x28(%rsp)
jmp 0x2e2cb
movq 0x38(%rsp), %rax
movq %rax, 0x40(%rsp)
jmp 0x2e25d
jmp 0x2e2d9
cmpq $0x0, 0x30(%rsp)
jne 0x2e306
cmpq $0x0, 0x28(%rsp)
jne 0x2e306
movq 0x50(%rsp), %rax
movq $0x0, (%rax)
movq 0x48(%rsp), %rax
movq $0x0, (%rax)
jmp 0x2e3d3
cmpq $0x0, 0x30(%rsp)
jne 0x2e33a
movq 0x50(%rsp), %rax
movq $0x0, (%rax)
movq 0x60(%rsp), %rcx
movq 0x48(%rsp), %rax
movq %rcx, (%rax)
movq 0x28(%rsp), %rcx
movq 0x60(%rsp), %rax
movq %rcx, 0x48(%rax)
jmp 0x2e3d3
cmpq $0x0, 0x28(%rsp)
jne 0x2e36b
movq 0x60(%rsp), %rcx
movq 0x50(%rsp), %rax
movq %rcx, (%rax)
movq 0x48(%rsp), %rax
movq $0x0, (%rax)
movq 0x30(%rsp), %rcx
movq 0x60(%rsp), %rax
movq %rcx, 0x48(%rax)
jmp 0x2e3d3
callq 0x24f10
movq %rax, 0x10(%rsp)
movq 0x60(%rsp), %rsi
movq 0x10(%rsp), %rdi
movl $0x58, %edx
callq 0x4260
movq 0x28(%rsp), %rcx
movq 0x10(%rsp), %rax
movq %rcx, 0x48(%rax)
movq 0x10(%rsp), %rcx
movq 0x48(%rsp), %rax
movq %rcx, (%rax)
movq 0x30(%rsp), %rcx
movq 0x60(%rsp), %rax
movq %rcx, 0x48(%rax)
movq 0x60(%rsp), %rcx
movq 0x50(%rsp), %rax
movq %rcx, (%rax)
movq 0x10(%rsp), %rdi
callq 0x2acd0
movq 0x60(%rsp), %rdi
callq 0x2acd0
addq $0x68, %rsp
retq
nopl (%rax,%rax)