// File: FreeSlave[P]vhlt/hlbsp/surfaces.cpp
// Function: SubdivideFace(face_s*, face_s**)
void            SubdivideFace(face_t* f, face_t** prevptr)
{
    vec_t           mins, maxs;
    vec_t           v;
    int             axis;
    int             i;
    dplane_t        plane;
    face_t*         front;
    face_t*         back;
    face_t*         next;
    texinfo_t*      tex;
    vec3_t          temp;

    // special (non-surface cached) faces don't need subdivision

#ifdef HLCSG_HLBSP_VOIDTEXINFO
	if (f->texturenum == -1)
	{
		return;
	}
#endif
    tex = &g_texinfo[f->texturenum];

    if (tex->flags & TEX_SPECIAL) 
    {
        return;
    }

    if (f->facestyle == face_hint)
    {
        return;
    }
    if (f->facestyle == face_skip)
    {
        return;
    }

#ifdef ZHLT_NULLTEX    // AJM
    if (f->facestyle == face_null)
        return; // ideally these should have their tex_special flag set, so its here jic
#endif
#ifdef HLCSG_HLBSP_SOLIDHINT
	if (f->facestyle == face_discardable)
		return;
#endif
	
    for (axis = 0; axis < 2; axis++)
    {
        while (1)
        {
#ifdef HLBSP_SUBDIVIDE_INMID
			const int maxlightmapsize = g_subdivide_size / TEXTURE_STEP + 1;
			int lightmapmins, lightmapmaxs;
			if (f->numpoints == 0)
			{
				break;
			}
			for (i = 0; i < f->numpoints; i++)
			{
				v = DotProduct (f->pts[i], tex->vecs[axis]) + tex->vecs[axis][3];
				if (i == 0 || v < mins)
				{
					mins = v;
				}
				if (i == 0 || v > maxs)
				{
					maxs = v;
				}
			}
			lightmapmins = (int)floor (mins / TEXTURE_STEP - 0.05); // the worst case
			lightmapmaxs = (int)ceil (maxs / TEXTURE_STEP + 0.05); // the worst case
			if (lightmapmaxs - lightmapmins <= maxlightmapsize)
			{
				break;
			}
#else
#ifdef ZHLT_64BIT_FIX
			mins = 99999999;
			maxs = -99999999;
#else
            mins = 999999;
            maxs = -999999;
#endif

            for (i = 0; i < f->numpoints; i++)
            {
                v = DotProduct(f->pts[i], tex->vecs[axis]);
                if (v < mins)
                {
                    mins = v;
                }
                if (v > maxs)
                {
                    maxs = v;
                }
            }

            if ((maxs - mins) <= g_subdivide_size)
            {
                break;
            }
#endif
                
            // split it
            subdivides++;

            VectorCopy(tex->vecs[axis], temp);
            v = VectorNormalize(temp);

            VectorCopy(temp, plane.normal);
#ifdef HLBSP_SUBDIVIDE_INMID
			int splitpos;
			if ((lightmapmaxs - lightmapmins - 1) - (maxlightmapsize - 1) < (maxlightmapsize - 1) / 4) // don't create very thin face
			{
				splitpos = lightmapmins + (maxlightmapsize - 1) - (maxlightmapsize - 1) / 4;
			}
			else
			{
				splitpos = lightmapmins + (maxlightmapsize - 1);
			}
			plane.dist = ((splitpos + 0.5) * TEXTURE_STEP - tex->vecs[axis][3]) / v;
#else
            plane.dist = (mins + g_subdivide_size - TEXTURE_STEP) / v; //plane.dist = (mins + g_subdivide_size - 16) / v; //--vluzacn
#endif
            next = f->next;
            SplitFace(f, &plane, &front, &back);
            if (!front || !back)
            {
                Developer(DEVELOPER_LEVEL_SPAM, "SubdivideFace: didn't split the %d-sided polygon @(%.0f,%.0f,%.0f)",
                        f->numpoints, f->pts[0][0], f->pts[0][1], f->pts[0][2]);
#ifndef HLBSP_SubdivideFace_FIX
                break;
#endif
            }
#ifdef HLBSP_SubdivideFace_FIX
			f = next;
			if (front)
			{
				front->next = f;
				f = front;
			}
			if (back)
			{
				back->next = f;
				f = back;
			}
			*prevptr = f;
#else
            *prevptr = back;
            back->next = front;
            front->next = next;
            f = back;
#endif
        }
    }
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0xa0(%rsp)
movq %rsi, 0x98(%rsp)
movq 0xa0(%rsp), %rax
cmpl $-0x1, 0xc(%rax)
jne 0x2fa7a
jmp 0x2fe6e
movq 0xa0(%rsp), %rax
movslq 0xc(%rax), %rcx
leaq 0x117f933(%rip), %rax   # 0x11af3c0
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movl 0x24(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x2faae
jmp 0x2fe6e
movq 0xa0(%rsp), %rax
cmpl $0x1, 0x30(%rax)
jne 0x2fac1
jmp 0x2fe6e
movq 0xa0(%rsp), %rax
cmpl $0x2, 0x30(%rax)
jne 0x2fad4
jmp 0x2fe6e
movq 0xa0(%rsp), %rax
cmpl $0x3, 0x30(%rax)
jne 0x2fae7
jmp 0x2fe6e
movq 0xa0(%rsp), %rax
cmpl $0x4, 0x30(%rax)
jne 0x2fafa
jmp 0x2fe6e
movl $0x0, 0x7c(%rsp)
cmpl $0x2, 0x7c(%rsp)
jge 0x2fe6e
jmp 0x2fb0f
movsd 0xc219(%rip), %xmm0     # 0x3bd30
movsd %xmm0, 0x90(%rsp)
movsd 0xc200(%rip), %xmm0     # 0x3bd28
movsd %xmm0, 0x88(%rsp)
movl $0x0, 0x78(%rsp)
movl 0x78(%rsp), %eax
movq 0xa0(%rsp), %rcx
cmpl 0x2c(%rcx), %eax
jge 0x2fc70
movq 0xa0(%rsp), %rax
addq $0x38, %rax
movslq 0x78(%rsp), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movsd (%rax), %xmm1
movq 0x18(%rsp), %rax
movslq 0x7c(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movss (%rax), %xmm0
cvtss2sd %xmm0, %xmm2
movq 0xa0(%rsp), %rax
addq $0x38, %rax
movslq 0x78(%rsp), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movsd 0x8(%rax), %xmm0
movq 0x18(%rsp), %rax
movslq 0x7c(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movss 0x4(%rax), %xmm3
cvtss2sd %xmm3, %xmm3
mulsd %xmm3, %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movq 0xa0(%rsp), %rax
addq $0x38, %rax
movslq 0x78(%rsp), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movsd 0x10(%rax), %xmm0
movq 0x18(%rsp), %rax
movslq 0x7c(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movss 0x8(%rax), %xmm2
cvtss2sd %xmm2, %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x80(%rsp), %xmm1
movsd 0x90(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2fc38
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x90(%rsp)
movsd 0x80(%rsp), %xmm0
ucomisd 0x88(%rsp), %xmm0
jbe 0x2fc5e
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x88(%rsp)
jmp 0x2fc60
movl 0x78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x78(%rsp)
jmp 0x2fb39
movsd 0x88(%rsp), %xmm1
subsd 0x90(%rsp), %xmm1
leaq 0x1776b(%rip), %rax     # 0x473f4
cvtsi2sdl (%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x2fc98
jmp 0x2fe5c
movl 0x32bfde2(%rip), %eax   # 0x32efa80
addl $0x1, %eax
movl %eax, 0x32bfdd9(%rip)   # 0x32efa80
movq 0x18(%rsp), %rax
movslq 0x7c(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movss (%rax), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, (%rsp)
movq 0x18(%rsp), %rax
movslq 0x7c(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movss 0x4(%rax), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x8(%rsp)
movq 0x18(%rsp), %rax
movslq 0x7c(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movss 0x8(%rax), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x10(%rsp)
movq %rsp, %rdi
callq 0x11bc0
movsd %xmm0, 0x80(%rsp)
movsd (%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
movsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
movsd 0x90(%rsp), %xmm0
leaq 0x176ab(%rip), %rax     # 0x473f4
cvtsi2sdl (%rax), %xmm1
addsd %xmm1, %xmm0
movsd 0xbfdf(%rip), %xmm1     # 0x3bd38
subsd %xmm1, %xmm0
divsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x68(%rsp)
movq 0xa0(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x20(%rsp)
movq 0xa0(%rsp), %rdi
leaq 0x38(%rsp), %rsi
leaq 0x30(%rsp), %rdx
leaq 0x28(%rsp), %rcx
callq 0x23e20
cmpq $0x0, 0x30(%rsp)
je 0x2fda8
cmpq $0x0, 0x28(%rsp)
jne 0x2fded
movq 0xa0(%rsp), %rax
movl 0x2c(%rax), %edx
movq 0xa0(%rsp), %rax
movsd 0x38(%rax), %xmm0
movq 0xa0(%rsp), %rax
movsd 0x40(%rax), %xmm1
movq 0xa0(%rsp), %rax
movsd 0x48(%rax), %xmm2
movl $0x5, %edi
leaq 0xbf7a(%rip), %rsi      # 0x3bd60
movb $0x3, %al
callq 0xbb80
movq 0x20(%rsp), %rax
movq %rax, 0xa0(%rsp)
cmpq $0x0, 0x30(%rsp)
je 0x2fe1f
movq 0xa0(%rsp), %rcx
movq 0x30(%rsp), %rax
movq %rcx, (%rax)
movq 0x30(%rsp), %rax
movq %rax, 0xa0(%rsp)
cmpq $0x0, 0x28(%rsp)
je 0x2fe44
movq 0xa0(%rsp), %rcx
movq 0x28(%rsp), %rax
movq %rcx, (%rax)
movq 0x28(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rcx
movq 0x98(%rsp), %rax
movq %rcx, (%rax)
jmp 0x2fb0f
jmp 0x2fe5e
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x2fb02
addq $0xa8, %rsp
retq
nopw %cs:(%rax,%rax)