// File: /workspace/github_cpp_makefile_star2_O3/FreeSlave[P]vhlt/hlbsp/brink.cpp
// Function: SplitTreeLeaf(int&, btreeleaf_s*, plane_t const*, int, double, btreeleaf_s*&, btreeleaf_s*&, bclipnode_s*, bclipnode_s*)
void SplitTreeLeaf (int &numobjects, btreeleaf_t *tl, const dplane_t *plane, int planenum, vec_t epsilon, btreeleaf_t *&front, btreeleaf_t *&back, bclipnode_t *c0, bclipnode_t *c1)
{
	btreeface_l::iterator fi;
	btreeedge_l::iterator ei;
	bool restart = false;

	// clear all the flags
	for (fi = tl->faces->begin (); fi != tl->faces->end (); fi++)
	{
		btreeface_t *tf = fi->f;
		tf->tmp_tested = false;
		for (ei = tf->edges->begin (); ei != tf->edges->end (); ei++)
		{
			btreeedge_t *te = ei->e;
			te->tmp_tested = false;
			for (int side = 0; side < 2; side++)
			{
				btreepoint_t *tp = GetPointFromEdge (te, side);
				tp->tmp_tested = false;
			}
		}
	}

	// split each point
	for (fi = tl->faces->begin (); fi != tl->faces->end (); fi++)
	{
		btreeface_t *tf = fi->f;
		for (ei = tf->edges->begin (); ei != tf->edges->end (); ei++)
		{
			btreeedge_t *te = ei->e;
			for (int side = 0; side < 2; side++)
			{
				btreepoint_t *tp = GetPointFromEdge (te, side);
				if (tp->tmp_tested)
				{
					continue;
				}
				tp->tmp_tested = true;
				vec_t dist = DotProduct (tp->v, plane->normal) - plane->dist;
				tp->tmp_dist = dist;
				if (dist > epsilon)
				{
					tp->tmp_side = SIDE_FRONT;
				}
				else if (dist < -epsilon)
				{
					tp->tmp_side = SIDE_BACK;
				}
				else
				{
					tp->tmp_side = SIDE_ON;
				}
#ifdef HLBSP_BRINKHACK_BUGFIX
#if 0
				// let's mess up something and see whether the code is fragile or robust
				static int randcounter = 0;
				if (randcounter++ % 8 == 0) tp->tmp_side = randcounter % 3;
#endif
#endif
			}
		}
	}

	// split each edge
	for (fi = tl->faces->begin (); fi != tl->faces->end (); fi++)
	{
		btreeface_t *tf = fi->f;
		for (ei = tf->edges->begin (); ei != tf->edges->end (); restart? restart = false, ei = tf->edges->begin (): ei++)
		{
			btreeedge_t *te = ei->e;
			if (te->tmp_tested) // splitted
			{
				continue;
			}
			te->tmp_tested = true;
			te->tmp_side = SIDE_ON;
			for (int side = 0; side < 2; side++)
			{
				btreepoint_t *tp = GetPointFromEdge (te, side);
				if (te->tmp_side == SIDE_ON)
				{
					te->tmp_side = tp->tmp_side;
				}
				else if (tp->tmp_side != SIDE_ON && tp->tmp_side != te->tmp_side)
				{
					te->tmp_side = SIDE_CROSS;
				}
			}
#ifdef HLBSP_BRINKNOTUSEDBYLEAF_FIX
			// The plane does not necessarily split the leaf into two, because of epsilon problem etc., and this will cause "Error: CollectBrinks_r: not leaf" on some maps.
			// In addition, by the time of this step (split edges), the plane has not splitted the leaf yet, so splitting the brink leafs now will break the integrety of the entire geometry. (We want the four steps to be as independent on each other as possible, that is, the entire geometry remains valid after each step.)
#else
			if (!te->infinite)
			{
				if (te->tmp_side == SIDE_ON)
				{
					// since the plane splits the leaf into two, it must also split the brink into two
					BrinkSplitClipnode (te->brink, plane, planenum, tl->clipnode, c0, c1);
				}
				else if (te->tmp_side == SIDE_FRONT)
				{
					BrinkReplaceClipnode (te->brink, tl->clipnode, c0);
				}
				else if (te->tmp_side == SIDE_BACK)
				{
					BrinkReplaceClipnode (te->brink, tl->clipnode, c1);
				}
			}
#endif
			if (te->tmp_side == SIDE_CROSS)
			{
				btreepoint_t *tp0 = GetPointFromEdge (te, false);
				btreepoint_t *tp1 = GetPointFromEdge (te, true);
				btreepoint_t *tpmid = AllocTreepoint (numobjects, te->infinite);
				tpmid->tmp_tested = true;
				tpmid->tmp_dist = 0;
				tpmid->tmp_side = SIDE_ON;
				vec_t frac = tp0->tmp_dist / (tp0->tmp_dist - tp1->tmp_dist);
				for (int k = 0; k < 3; k++)
				{
					tpmid->v[k] = tp0->v[k] + frac * (tp1->v[k] - tp0->v[k]);
				}
				btreeedge_t *te0 = AllocTreeedge (numobjects, te->infinite);
				SetEdgePoints (te0, tp0, tpmid);
				te0->tmp_tested = true;
				te0->tmp_side = tp0->tmp_side;
				if (!te0->infinite)
				{
					te0->brink = CopyBrink (te->brink);
					VectorCopy (tpmid->v, te0->brink->start);
					VectorCopy (tp0->v, te0->brink->stop);
#ifndef HLBSP_BRINKNOTUSEDBYLEAF_FIX
					BrinkReplaceClipnode (te0->brink, tl->clipnode, (tp0->tmp_side == SIDE_BACK? c1: c0));
#endif
				}
				btreeedge_t *te1 = AllocTreeedge (numobjects, te->infinite);
				SetEdgePoints (te1, tpmid, tp1);
				te1->tmp_tested = true;
				te1->tmp_side = tp1->tmp_side;
				if (!te1->infinite)
				{
					te1->brink = CopyBrink (te->brink);
					VectorCopy (tp1->v, te1->brink->start);
					VectorCopy (tpmid->v, te1->brink->stop);
#ifndef HLBSP_BRINKNOTUSEDBYLEAF_FIX
					BrinkReplaceClipnode (te1->brink, tl->clipnode, (tp1->tmp_side == SIDE_BACK? c1: c0));
#endif
				}
				btreeface_l::iterator fj;
				while ((fj = te->faces->begin ()) != te->faces->end ())
				{
					AttachEdgeToFace (fj->f, te0, fj->side);
					AttachEdgeToFace (fj->f, te1, fj->side);
					RemoveEdgeFromFace (fj->f, te, fj->side);
				}
				DeleteEdge (numobjects, te);
				restart = true;
			}
		}
	}

	// split each face
	for (fi = tl->faces->begin (); fi != tl->faces->end (); restart? restart = false, fi = tl->faces->begin (): fi++)
	{
		btreeface_t *tf = fi->f;
		if (tf->tmp_tested)
		{
			continue;
		}
		tf->tmp_tested = true;
		tf->tmp_side = SIDE_ON;
		for (ei = tf->edges->begin (); ei != tf->edges->end (); ei++)
		{
			if (tf->tmp_side == SIDE_ON)
			{
				tf->tmp_side = ei->e->tmp_side;
			}
			else if (ei->e->tmp_side != SIDE_ON && ei->e->tmp_side != tf->tmp_side)
			{
				tf->tmp_side = SIDE_CROSS;
			}
		}
		if (tf->tmp_side == SIDE_CROSS)
		{
			btreeface_t *frontface, *backface;
			frontface = AllocTreeface (numobjects, tf->infinite);
			if (!tf->infinite)
			{
				frontface->plane = tf->plane;
				frontface->planenum = tf->planenum;
				frontface->planeside = tf->planeside;
			}
			SetFaceLeafs (frontface, GetLeafFromFace (tf, false), GetLeafFromFace (tf, true));
			frontface->tmp_tested = true;
			frontface->tmp_side = SIDE_FRONT;
			backface = AllocTreeface (numobjects, tf->infinite);
			if (!tf->infinite)
			{
				backface->plane = tf->plane;
				backface->planenum = tf->planenum;
				backface->planeside = tf->planeside;
			}
			SetFaceLeafs (backface, GetLeafFromFace (tf, false), GetLeafFromFace (tf, true));
			backface->tmp_tested = true;
			backface->tmp_side = SIDE_BACK;

			std::map< btreepoint_t *, int > vertexes;
			std::map< btreepoint_t *, int >::iterator vertex, vertex2;
			for (ei = tf->edges->begin (); ei != tf->edges->end (); ei++)
			{
				if (ei->e->tmp_side != SIDE_BACK)
				{
					AttachEdgeToFace (frontface, ei->e, ei->side);
				}
				else
				{
					AttachEdgeToFace (backface, ei->e, ei->side);

					btreeedge_t *e = ei->e;
					for (int side = 0; side < 2; side++)
					{
						btreepoint_t *p = GetPointFromEdge (e, side);
						vertexes[p] += ((bool)side == ei->side? 1: -1); // the default value is 0 if vertexes[p] does not exist
						vertex = vertexes.find (p);
						if (vertex->second == 0)
						{
							vertexes.erase (vertex);
						}
					}
				}
			}
			if (vertexes.size () != 2)
			{
				Developer (DEVELOPER_LEVEL_WARNING, "SplitTreeLeaf: got invalid edge from split\n");
			}

			while (1)
			{
				for (vertex = vertexes.begin (); vertex != vertexes.end (); vertex++)
				{
					if (vertex->second > 0)
					{
						break;
					}
				}
				for (vertex2 = vertexes.begin (); vertex2 != vertexes.end (); vertex2++)
				{
					if (vertex2->second < 0)
					{
						break;
					}
				}
				if (vertex == vertexes.end () && vertex2 == vertexes.end ())
				{
					break;
				}
				if (vertex == vertexes.end () || vertex2 == vertexes.end ())
				{
					PrintOnce ("SplitTreeLeaf: internal error: couldn't link edges");
					hlassume (false, assume_first);
				}
				if (vertex->second != 1 || vertex2->second != -1)
				{
					Developer (DEVELOPER_LEVEL_WARNING, "SplitTreeLeaf: got deformed edge from split\n");
				}
				if (vertex->first->tmp_side != SIDE_ON || vertex2->first->tmp_side != SIDE_ON)
				{
					PrintOnce ("SplitTreeLeaf: internal error: tmp_side != SIDE_ON");
					hlassume (false, assume_first);
				}

				btreeedge_t *te;
				te = AllocTreeedge (numobjects, tf->infinite);
				SetEdgePoints (te, vertex->first, vertex2->first);
				if (!te->infinite)
				{
					te->brink = CreateBrink (vertex2->first->v, vertex->first->v);
					if (GetLeafFromFace (tf, tf->planeside)->infinite || GetLeafFromFace (tf, !tf->planeside)->infinite)
					{
						PrintOnce ("SplitTreeLeaf: internal error: an infinite object contains a finite object");
						hlassume (false, assume_first);
					}
					BrinkSplitClipnode (te->brink, tf->plane, tf->planenum, NULL, GetLeafFromFace (tf, tf->planeside)->clipnode, GetLeafFromFace (tf, !tf->planeside)->clipnode);
#ifndef HLBSP_BRINKNOTUSEDBYLEAF_FIX
					BrinkSplitClipnode (te->brink, plane, planenum, tl->clipnode, c0, c1);
#endif
				}
				te->tmp_tested = true;
				te->tmp_side = SIDE_ON;
				AttachEdgeToFace (frontface, te, false);
				AttachEdgeToFace (backface, te, true);

				vertex->second--;
				vertex2->second++;
			}

			for (int side = 0; side < 2; side++)
			{
				RemoveFaceFromLeaf (GetLeafFromFace (tf, side), tf, side);
			}
			DeleteFace (numobjects, tf);
			restart = true;
		}
	}

	// split the leaf
	{
		if (tl->infinite)
		{
			PrintOnce ("SplitTreeLeaf: internal error: splitting the infinite leaf");
			hlassume (false, assume_first);
		}
		front = AllocTreeleaf (numobjects, tl->infinite);
		back = AllocTreeleaf (numobjects, tl->infinite);
		front->clipnode = c0;
		back->clipnode = c1;

		int tmp_side = SIDE_ON;
		for (fi = tl->faces->begin (); fi != tl->faces->end (); fi++)
		{
			if (tmp_side == SIDE_ON)
			{
				tmp_side = fi->f->tmp_side;
			}
			else if (fi->f->tmp_side != SIDE_ON && fi->f->tmp_side != tmp_side)
			{
				tmp_side = SIDE_CROSS;
			}
		}
		
		std::map< btreeedge_t *, int > edges;
		std::map< btreeedge_t *, int >::iterator edge;

		while ((fi = tl->faces->begin ()) != tl->faces->end ())
		{
			btreeface_t *tf = fi->f;
			int side = fi->side;
			RemoveFaceFromLeaf (tl, tf, side); // because we can only store 2 leafs for a face
			
			// fi is unusable now
			if (tf->tmp_side == SIDE_FRONT || tf->tmp_side == SIDE_ON && tmp_side != SIDE_BACK)
			{
				AttachFaceToLeaf (front, tf, side);
			}
			else if (tf->tmp_side == SIDE_BACK || tf->tmp_side == SIDE_ON && tmp_side == SIDE_BACK)
			{
				AttachFaceToLeaf (back, tf, side);

				if (tmp_side == SIDE_CROSS)
				{
					for (ei = tf->edges->begin (); ei != tf->edges->end (); ei++)
					{
						edges[ei->e] += (ei->side == (bool)side? 1: -1);
						edge = edges.find (ei->e);
						if (edge->second == 0)
						{
							edges.erase (edge);
						}
					}
				}
			}
		}

		if (tmp_side == SIDE_CROSS)
		{
			btreeface_t *tf;
			tf = AllocTreeface (numobjects, tl->infinite);
			if (!tf->infinite)
			{
				tf->plane = plane;
				tf->planenum = planenum;
				tf->planeside = false;
			}
			tf->tmp_tested = true;
			tf->tmp_side = SIDE_ON;
			SetFaceLeafs (tf, front, back);
			for (edge = edges.begin (); edge != edges.end (); edge++)
			{
				if (edge->first->tmp_side != SIDE_ON)
				{
					PrintOnce ("SplitTreeLeaf: internal error");
					hlassume (false, assume_first);
				}
				while (edge->second > 0)
				{
					AttachEdgeToFace (tf, edge->first, false);
					edge->second--;
				}
				while (edge->second < 0)
				{
					AttachEdgeToFace (tf, edge->first, true);
					edge->second++;
				}
			}
		}

#ifndef HLBSP_BRINKHACK_BUGFIX
		DeleteLeaf (numobjects, tl);
#endif
#ifdef HLBSP_BRINKNOTUSEDBYLEAF_FIX
		btreeleaf_t *(frontback[2]) = {front, back};
		for (int side = 0; side < 2; side++)
		{
			for (fi = frontback[side]->faces->begin (); fi != frontback[side]->faces->end (); fi++)
			{
				for (ei = fi->f->edges->begin (); ei != fi->f->edges->end (); ei++)
				{
					ei->e->tmp_onleaf[0] = ei->e->tmp_onleaf[1] = false;
					ei->e->tmp_tested = false;
				}
			}
		}
		for (int side = 0; side < 2; side++)
		{
			for (fi = frontback[side]->faces->begin (); fi != frontback[side]->faces->end (); fi++)
			{
				for (ei = fi->f->edges->begin (); ei != fi->f->edges->end (); ei++)
				{
					ei->e->tmp_onleaf[side] = true;
				}
			}
		}
		for (int side = 0; side < 2; side++)
		{
			for (fi = frontback[side]->faces->begin (); fi != frontback[side]->faces->end (); fi++)
			{
				for (ei = fi->f->edges->begin (); ei != fi->f->edges->end (); ei++)
				{
					if (ei->e->tmp_tested)
					{
						continue;
					}
					ei->e->tmp_tested = true;
					if (!ei->e->infinite)
					{
						if (ei->e->tmp_onleaf[0] && ei->e->tmp_onleaf[1])
						{
							if (ei->e->tmp_side != SIDE_ON)
							{
								PrintOnce ("SplitTreeLeaf: internal error");
								hlassume (false, assume_first);
							}
							BrinkSplitClipnode (ei->e->brink, plane, planenum, tl->clipnode, c0, c1);
						}
						else if (ei->e->tmp_onleaf[0])
						{
							if (ei->e->tmp_side == SIDE_BACK)
							{
								PrintOnce ("SplitTreeLeaf: internal error");
								hlassume (false, assume_first);
							}
							BrinkReplaceClipnode (ei->e->brink, tl->clipnode, c0);
						}
						else if (ei->e->tmp_onleaf[1])
						{
							if (ei->e->tmp_side == SIDE_FRONT)
							{
								PrintOnce ("SplitTreeLeaf: internal error");
								hlassume (false, assume_first);
							}
							BrinkReplaceClipnode (ei->e->brink, tl->clipnode, c1);
						}
					}
				}
			}
		}
#endif
#ifdef HLBSP_BRINKHACK_BUGFIX
		DeleteLeaf (numobjects, tl);
#endif
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %r9, 0x38(%rsp)
movq %r8, 0x40(%rsp)
movapd %xmm0, 0x10(%rsp)
movl %ecx, 0x34(%rsp)
movq %rdx, %r15
movq %rdi, 0x8(%rsp)
movq %rsi, (%rsp)
movq (%rsi), %rax
movq (%rax), %rdx
cmpq %rax, %rdx
je 0xec58
xorl %ebp, %ebp
movq %rdx, %r13
movq 0x10(%rdx), %r14
movb $0x0, 0x3d(%r14)
movq (%r14), %rax
movq (%rax), %r12
cmpq %rax, %r12
je 0xec45
movq 0x10(%r12), %rbx
movb %bpl, 0x38(%rbx)
movq %rbx, %rdi
xorl %esi, %esi
callq 0xe75d
movb %bpl, 0x28(%rax)
movq %rbx, %rdi
movl $0x1, %esi
callq 0xe75d
movb %bpl, 0x28(%rax)
movq (%r12), %r12
cmpq (%r14), %r12
jne 0xec14
movq (%r13), %rdx
movq (%rsp), %rax
movq (%rax), %rax
cmpq %rax, %rdx
jne 0xebfd
movq (%rax), %rdx
cmpq %rax, %rdx
je 0xed41
movapd 0x11647(%rip), %xmm0    # 0x202b0
xorpd 0x10(%rsp), %xmm0
movapd %xmm0, 0x20(%rsp)
movq %rdx, %r13
movq 0x10(%rdx), %r14
movq (%r14), %rcx
movq (%rcx), %r12
cmpq %rcx, %r12
je 0xed31
movq 0x10(%r12), %rbx
movb $0x1, %bpl
xorl %eax, %eax
movzbl %al, %esi
andl $0x1, %esi
movq %rbx, %rdi
callq 0xe75d
cmpb $0x0, 0x28(%rax)
jne 0xed0c
movb $0x1, 0x28(%rax)
movsd (%rax), %xmm1
movsd 0x8(%rax), %xmm2
mulsd 0x8(%r15), %xmm2
mulsd (%r15), %xmm1
movsd 0x10(%rax), %xmm0
mulsd 0x10(%r15), %xmm0
addsd %xmm2, %xmm1
addsd %xmm1, %xmm0
subsd 0x30(%r15), %xmm0
movsd %xmm0, 0x30(%rax)
ucomisd 0x10(%rsp), %xmm0
jbe 0xecf0
movl $0x0, 0x38(%rax)
jmp 0xed0c
movapd 0x20(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0xed05
movl $0x1, 0x38(%rax)
jmp 0xed0c
movl $0x2, 0x38(%rax)
movb $0x1, %al
testb $0x1, %bpl
movl $0x0, %ebp
jne 0xec95
movq (%r12), %r12
cmpq (%r14), %r12
jne 0xec8b
movq (%rsp), %rax
movq (%rax), %rax
movq (%r13), %rdx
cmpq %rax, %rdx
jne 0xec75
movq (%rax), %rdx
cmpq %rax, %rdx
je 0xf54b
movq 0x10(%rdx), %rcx
movq %rcx, 0x10(%rsp)
movq (%rcx), %rcx
movq (%rcx), %rbx
cmpq %rcx, %rbx
je 0xeffa
movq %rdx, 0x20(%rsp)
movq (%rsp), %rax
movq 0x10(%rbx), %r14
cmpb $0x0, 0x38(%r14)
jne 0xefe6
movb $0x1, 0x38(%r14)
movl $0x2, 0x3c(%r14)
movb $0x1, %bpl
xorl %eax, %eax
movzbl %al, %esi
andl $0x1, %esi
movq %r14, %rdi
callq 0xe75d
movl 0x3c(%r14), %ecx
movl 0x38(%rax), %eax
cmpl $0x2, %ecx
jne 0xedae
movl %eax, 0x3c(%r14)
movl %eax, %ecx
jmp 0xedbd
cmpl $0x2, %eax
setne %dl
cmpl %ecx, %eax
setne %al
testb %al, %dl
jne 0xedcc
movb $0x1, %al
testb $0x1, %bpl
movl $0x0, %ebp
jne 0xed8c
jmp 0xede3
movl $0xfffffffe, 0x3c(%r14) # imm = 0xFFFFFFFE
movb $0x1, %al
testb $0x1, %bpl
movl $0x0, %ebp
jne 0xed8c
jmp 0xedec
cmpl $-0x2, %ecx
jne 0xefda
movq %r14, %rdi
xorl %esi, %esi
callq 0xe75d
movq %rax, %rbx
movq %r14, %rdi
movl $0x1, %esi
callq 0xe75d
movq %rax, %r13
movzbl 0x20(%r14), %esi
movq 0x8(%rsp), %rdi
callq 0xde38
movq %rax, %rbp
movb $0x1, 0x28(%rax)
movq $0x0, 0x30(%rax)
movl $0x2, 0x38(%rax)
movsd 0x30(%rbx), %xmm0
movapd %xmm0, %xmm1
subsd 0x30(%r13), %xmm1
divsd %xmm1, %xmm0
xorl %eax, %eax
movsd (%rbx,%rax,8), %xmm1
movsd (%r13,%rax,8), %xmm2
subsd %xmm1, %xmm2
mulsd %xmm0, %xmm2
addsd %xmm1, %xmm2
movsd %xmm2, (%rbp,%rax,8)
incq %rax
cmpq $0x3, %rax
jne 0xee43
movzbl 0x20(%r14), %esi
movq 0x8(%rsp), %rdi
callq 0xde8c
movq %rax, %r12
movq %rax, %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0xdeef
movq %r12, %rdi
movq %rbp, %rsi
movl $0x1, %edx
callq 0xdeef
movb $0x1, 0x38(%r12)
movl 0x38(%rbx), %eax
movl %eax, 0x3c(%r12)
cmpb $0x0, 0x20(%r12)
jne 0xeeeb
movq 0x30(%r14), %rdi
callq 0xda04
movq %rax, 0x30(%r12)
movups (%rbp), %xmm0
movups %xmm0, (%rax)
movsd 0x10(%rbp), %xmm0
movsd %xmm0, 0x10(%rax)
movsd (%rbx), %xmm0
movsd %xmm0, 0x18(%rax)
movsd 0x8(%rbx), %xmm0
movsd %xmm0, 0x20(%rax)
movsd 0x10(%rbx), %xmm0
movsd %xmm0, 0x28(%rax)
movzbl 0x20(%r14), %esi
movq 0x8(%rsp), %rdi
callq 0xde8c
movq %rax, %rbx
movq %rax, %rdi
movq %rbp, %rsi
xorl %edx, %edx
callq 0xdeef
movq %rbx, %rdi
movq %r13, %rsi
movl $0x1, %edx
callq 0xdeef
movb $0x1, 0x38(%rbx)
movl 0x38(%r13), %eax
movl %eax, 0x3c(%rbx)
cmpb $0x0, 0x20(%rbx)
jne 0xefb4
movq 0x30(%r14), %rdi
callq 0xda04
movq %rax, 0x30(%rbx)
movsd (%r13), %xmm0
movsd %xmm0, (%rax)
movsd 0x8(%r13), %xmm0
movsd %xmm0, 0x8(%rax)
movsd 0x10(%r13), %xmm0
movsd %xmm0, 0x10(%rax)
movups (%rbp), %xmm0
movups %xmm0, 0x18(%rax)
movsd 0x10(%rbp), %xmm0
movsd %xmm0, 0x28(%rax)
jmp 0xefb4
movq 0x10(%rbp), %rdi
movzbl 0x18(%rbp), %edx
movq %r12, %rsi
callq 0xe00b
movq 0x10(%rbp), %rdi
movzbl 0x18(%rbp), %edx
movq %rbx, %rsi
callq 0xe00b
movq 0x10(%rbp), %r13
movzbl 0x18(%rbp), %ebp
movq (%r13), %rdi
movq %r14, %rsi
movl %ebp, %edx
callq 0xe78d
movq 0x28(%r14), %rdi
movq %r13, %rsi
movl %ebp, %edx
callq 0xe8ad
movq 0x28(%r14), %rax
movq (%rax), %rbp
cmpq %rax, %rbp
jne 0xef70
movq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0xe920
movq 0x10(%rsp), %rax
movq (%rax), %rcx
movq %rcx, %rbx
jmp 0xefe2
movq 0x10(%rsp), %rax
movq (%rax), %rcx
movq (%rsp), %rax
movq (%rbx), %rbx
cmpq %rcx, %rbx
jne 0xed6b
movq (%rax), %rax
movq 0x20(%rsp), %rdx
movq (%rdx), %rdx
cmpq %rax, %rdx
jne 0xed4a
movq (%rax), %rcx
cmpq %rax, %rcx
je 0xf54b
leaq 0x58(%rsp), %r13
movq 0x10(%rcx), %rbx
cmpb $0x0, 0x3d(%rbx)
jne 0xf53f
movb $0x1, 0x3d(%rbx)
movl $0x2, 0x40(%rbx)
movq (%rbx), %rax
movq (%rax), %rdx
cmpq %rax, %rdx
je 0xf538
movl $0x2, %esi
movq 0x10(%rdx), %rdi
movl 0x3c(%rdi), %edi
cmpl $0x2, %esi
jne 0xf057
movl %edi, 0x40(%rbx)
movl %edi, %esi
jmp 0xf069
cmpl $0x2, %edi
setne %r8b
cmpl %esi, %edi
setne %dil
testb %dil, %r8b
jne 0xf073
movq (%rdx), %rdx
cmpq %rax, %rdx
jne 0xf044
jmp 0xf089
movl $0xfffffffe, 0x40(%rbx) # imm = 0xFFFFFFFE
movq (%rdx), %rdx
movl $0xfffffffe, %esi       # imm = 0xFFFFFFFE
cmpq %rax, %rdx
jne 0xf044
jmp 0xf092
cmpl $-0x2, %esi
jne 0xf538
movzbl 0x8(%rbx), %esi
movq 0x8(%rsp), %rdi
callq 0xdfa8
movq %rax, %r12
cmpb $0x0, 0x8(%rbx)
jne 0xf0c2
movq 0x30(%rbx), %rcx
movq %rcx, 0x30(%r12)
movl 0x38(%rbx), %ecx
movl %ecx, 0x38(%r12)
movb 0x3c(%rbx), %cl
movb %cl, 0x3c(%r12)
movq %rbx, %rdi
xorl %esi, %esi
callq 0xe9eb
movq %rbx, 0x10(%rsp)
movq %rax, %rbx
movq 0x10(%rsp), %rdi
movl $0x1, %esi
callq 0xe9eb
movq %rax, %r14
movq %rbx, %rdi
movq 0x10(%rsp), %rbx
movq %r12, %rsi
xorl %edx, %edx
callq 0xe099
movq %r14, %rdi
movq %r12, %rsi
movl $0x1, %edx
callq 0xe099
movb $0x1, 0x3d(%r12)
movq %r12, 0x20(%rsp)
movl $0x0, 0x40(%r12)
movzbl 0x8(%rbx), %esi
movq 0x8(%rsp), %rdi
callq 0xdfa8
movq %rax, %rbp
cmpb $0x0, 0x8(%rbx)
jne 0xf147
movq 0x30(%rbx), %rax
movq %rax, 0x30(%rbp)
movl 0x38(%rbx), %eax
movl %eax, 0x38(%rbp)
movb 0x3c(%rbx), %al
movb %al, 0x3c(%rbp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0xe9eb
movq %rbx, %r12
movq %rax, %rbx
movq %r12, %rdi
movl $0x1, %esi
callq 0xe9eb
movq %rax, %r14
movq %rbx, %rdi
movq %rbp, %rsi
xorl %edx, %edx
callq 0xe099
movq %r14, %rdi
movq %rbp, %rsi
movl $0x1, %edx
callq 0xe099
movb $0x1, 0x3d(%rbp)
movq %rbp, 0x48(%rsp)
movl $0x1, 0x40(%rbp)
movl $0x0, 0x58(%rsp)
xorl %eax, %eax
movq %rax, 0x60(%rsp)
movq %r13, 0x68(%rsp)
movq %r13, 0x70(%rsp)
movq %rax, 0x78(%rsp)
movq (%r12), %rax
movq (%rax), %rbx
cmpq %rax, %rbx
je 0xf2d7
movq 0x10(%rbx), %rsi
cmpl $0x1, 0x3c(%rsi)
movzbl 0x18(%rbx), %edx
jne 0xf2ab
movq 0x48(%rsp), %rdi
callq 0xe00b
movq 0x10(%rbx), %r12
xorl %eax, %eax
movb $0x1, %bpl
xorl %r14d, %r14d
movzbl %al, %esi
andl $0x1, %esi
movq %r12, %rdi
callq 0xe75d
movq %rax, 0x88(%rsp)
movzbl 0x18(%rbx), %r13d
leaq 0x50(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0x11824
xorl %ecx, %ecx
cmpl %r13d, %r14d
sete %cl
movl (%rax), %edx
leal -0x1(%rdx,%rcx,2), %ecx
movl %ecx, (%rax)
movq 0x60(%rsp), %r9
leaq 0x58(%rsp), %r10
movq %r10, %rsi
testq %r9, %r9
je 0xf282
movq 0x88(%rsp), %rax
movq %r10, %rdi
movq %rdi, %rcx
movq %r9, %rdx
movq 0x20(%r9), %r8
xorl %esi, %esi
cmpq %rax, %r8
setb %sil
movq %r9, %rdi
cmovbq %rcx, %rdi
movq 0x10(%r9,%rsi,8), %r9
testq %r9, %r9
jne 0xf244
movq %r10, %rsi
cmpq %r10, %rdi
je 0xf282
cmpq %rax, %r8
cmovbq %rcx, %rdx
cmpq 0x20(%rdx), %rax
cmovbq %r10, %rdi
movq %rdi, %rsi
cmpl $0x0, 0x28(%rsi)
jne 0xf292
leaq 0x50(%rsp), %rdi
callq 0x11f96
movl $0x1, %r14d
movb $0x1, %al
testb $0x1, %bpl
movl $0x0, %ebp
jne 0xf1ea
jmp 0xf2b5
movq 0x20(%rsp), %rdi
callq 0xe00b
movq (%rbx), %rbx
movq 0x10(%rsp), %rax
cmpq (%rax), %rbx
jne 0xf1c2
cmpq $0x2, 0x78(%rsp)
leaq 0x58(%rsp), %r13
je 0xf47e
movl $0x2, %edi
leaq 0x11630(%rip), %rsi     # 0x20913
xorl %eax, %eax
callq 0xa3ae
jmp 0xf47e
leaq 0x11649(%rip), %rdi     # 0x2093f
xorl %eax, %eax
callq 0xa10c
xorl %edi, %edi
xorl %esi, %esi
callq 0xa655
cmpl $0x1, 0x28(%rbp)
jne 0xf314
cmpl $-0x1, 0x28(%r12)
je 0xf327
movl $0x2, %edi
leaq 0x11652(%rip), %rsi     # 0x20972
xorl %eax, %eax
callq 0xa3ae
movq 0x20(%rbp), %rax
cmpl $0x2, 0x38(%rax)
jne 0xf33c
movq 0x20(%r12), %rax
cmpl $0x2, 0x38(%rax)
je 0xf353
leaq 0x1165c(%rip), %rdi     # 0x2099f
xorl %eax, %eax
callq 0xa10c
xorl %edi, %edi
xorl %esi, %esi
callq 0xa655
movzbl 0x8(%rbx), %esi
movq 0x8(%rsp), %rdi
callq 0xde8c
movq %rax, %r13
movq 0x20(%rbp), %rsi
movq 0x20(%r12), %rbx
movq %rax, %rdi
xorl %edx, %edx
callq 0xdeef
movq %r13, %rdi
movq %rbx, %rsi
movl $0x1, %edx
callq 0xdeef
cmpb $0x0, 0x20(%r13)
jne 0xf443
movq 0x20(%r12), %rdi
movq 0x20(%rbp), %rsi
callq 0xdade
movq %rax, 0x30(%r13)
movq 0x10(%rsp), %rdi
movzbl 0x3c(%rdi), %esi
callq 0xe9eb
cmpb $0x0, 0x8(%rax)
jne 0xf3cf
movq 0x10(%rsp), %rdi
movzbl 0x3c(%rdi), %esi
xorl $0x1, %esi
callq 0xe9eb
cmpb $0x1, 0x8(%rax)
jne 0xf3e6
leaq 0x115fc(%rip), %rdi     # 0x209d2
xorl %eax, %eax
callq 0xa10c
xorl %edi, %edi
xorl %esi, %esi
callq 0xa655
movq 0x30(%r13), %rax
movq %rax, 0x90(%rsp)
movq 0x10(%rsp), %rdi
movq 0x30(%rdi), %r14
movl 0x38(%rdi), %eax
movl %eax, 0x84(%rsp)
movzbl 0x3c(%rdi), %esi
callq 0xe9eb
movq 0x10(%rax), %rbx
movq 0x10(%rsp), %rdi
movzbl 0x3c(%rdi), %esi
xorl $0x1, %esi
callq 0xe9eb
movq 0x10(%rax), %r9
movq 0x90(%rsp), %rdi
movq %r14, %rsi
movl 0x84(%rsp), %edx
xorl %ecx, %ecx
movq %rbx, %r8
callq 0xdc7c
movb $0x1, 0x38(%r13)
movl $0x2, 0x3c(%r13)
movq 0x20(%rsp), %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0xe00b
movq 0x48(%rsp), %rdi
movq %r13, %rsi
movl $0x1, %edx
callq 0xe00b
decl 0x28(%rbp)
incl 0x28(%r12)
leaq 0x58(%rsp), %r13
movq 0x68(%rsp), %r12
cmpq %r13, %r12
movq 0x10(%rsp), %rbx
movq %r12, %rbp
je 0xf4c3
cmpl $0x0, 0x28(%rbp)
jg 0xf4a6
movq %rbp, %rdi
callq 0x4200
movq %rax, %rbp
cmpq %r13, %rax
jne 0xf490
cmpq %r13, %r12
je 0xf4c3
cmpl $0x0, 0x28(%r12)
js 0xf4c3
movq %r12, %rdi
callq 0x4200
movq %rax, %r12
cmpq %r13, %rax
jne 0xf4ab
cmpq %r13, %rbp
je 0xf4d6
cmpq %r13, %r12
jne 0xf306
jmp 0xf2ef
cmpq %r13, %r12
jne 0xf2ef
movb $0x1, %bpl
xorl %eax, %eax
movzbl %al, %ebx
andl $0x1, %ebx
movq 0x10(%rsp), %r14
movq %r14, %rdi
movl %ebx, %esi
callq 0xe9eb
movq %rax, %rdi
movq %r14, %rsi
movl %ebx, %edx
callq 0xea1e
movb $0x1, %al
testb $0x1, %bpl
movl $0x0, %ebp
jne 0xf4e4
movq 0x8(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0xea76
leaq 0x50(%rsp), %rdi
callq 0x11972
movq (%rsp), %rax
movq (%rax), %rax
movq %rax, %rcx
jmp 0xf53f
movq (%rsp), %rax
movq (%rax), %rax
movq (%rcx), %rcx
cmpq %rax, %rcx
jne 0xf017
movq 0xd0(%rsp), %r13
movq (%rsp), %rbx
cmpb $0x1, 0x8(%rbx)
jne 0xf579
leaq 0x114b9(%rip), %rdi     # 0x20a1d
xorl %eax, %eax
callq 0xa10c
xorl %edi, %edi
xorl %esi, %esi
callq 0xa655
movb 0x8(%rbx), %al
jmp 0xf57b
xorl %eax, %eax
movzbl %al, %esi
andl $0x1, %esi
movq 0x8(%rsp), %r14
movq %r14, %rdi
callq 0xe159
movq 0x40(%rsp), %r12
movq %rax, (%r12)
movzbl 0x8(%rbx), %esi
movq %r14, %rdi
callq 0xe159
movq 0x38(%rsp), %rcx
movq %rax, (%rcx)
movq (%r12), %rax
movq %r13, 0x10(%rax)
movq (%rcx), %rax
movq 0xd8(%rsp), %rcx
movq %rcx, 0x10(%rax)
movq (%rbx), %rax
movq (%rax), %rcx
cmpq %rax, %rcx
je 0xf5fb
movl $0x2, %esi
movl $0xfffffffe, %edx       # imm = 0xFFFFFFFE
movq 0x10(%rcx), %rdi
movl 0x40(%rdi), %edi
cmpl $0x2, %esi
je 0xf5ef
cmpl $0x2, %edi
je 0xf5ed
cmpl %esi, %edi
cmovnel %edx, %esi
movl %esi, %edi
movq (%rcx), %rcx
movl %edi, %esi
cmpq %rax, %rcx
jne 0xf5d7
jmp 0xf600
movl $0x2, %edi
movl %edi, 0x20(%rsp)
leaq 0x58(%rsp), %rdx
movl $0x0, (%rdx)
xorl %ecx, %ecx
movq %rcx, 0x8(%rdx)
movq %rdx, 0x10(%rdx)
movq %rdx, 0x18(%rdx)
movq %rcx, 0x20(%rdx)
movq (%rax), %rcx
cmpq %rax, %rcx
movq (%rsp), %rdi
je 0xf769
movl 0x20(%rsp), %eax
xorl $0x1, %eax
movl %eax, 0x48(%rsp)
movq 0x10(%rcx), %rbp
movzbl 0x18(%rcx), %edx
movq %rbp, %rsi
movl %edx, 0x10(%rsp)
callq 0xea1e
movl 0x40(%rbp), %eax
testl %eax, %eax
je 0xf663
cmpl $0x2, %eax
jne 0xf68b
cmpl $0x1, 0x20(%rsp)
je 0xf68b
movq 0x40(%rsp), %rax
movq (%rax), %rdi
movq %rbp, %rsi
movl 0x10(%rsp), %edx
callq 0xe099
movq (%rsp), %rdi
movq (%rdi), %rax
movq (%rax), %rcx
cmpq %rax, %rcx
jne 0xf63c
jmp 0xf769
movl %eax, %ecx
xorl $0x2, %ecx
orl 0x48(%rsp), %ecx
sete %cl
cmpl $0x1, %eax
je 0xf6a0
testb %cl, %cl
je 0xf677
movq 0x38(%rsp), %rax
movq (%rax), %rdi
movq %rbp, %rsi
movl 0x10(%rsp), %edx
callq 0xe099
cmpl $-0x2, 0x20(%rsp)
jne 0xf677
movq (%rbp), %rax
movq (%rax), %r12
cmpq %rax, %r12
je 0xf677
leaq 0x10(%r12), %rbx
movb 0x18(%r12), %r14b
leaq 0x50(%rsp), %rdi
movq %rbx, %rsi
callq 0x1188a
xorl %ecx, %ecx
cmpb 0x10(%rsp), %r14b
sete %cl
movl (%rax), %edx
leal -0x1(%rdx,%rcx,2), %ecx
movl %ecx, (%rax)
movq 0x60(%rsp), %r9
leaq 0x58(%rsp), %r10
movq %r10, %rsi
testq %r9, %r9
je 0xf746
movq (%rbx), %rax
movq %r10, %rdi
movq %rdi, %rcx
movq %r9, %rdx
movq 0x20(%r9), %r8
xorl %esi, %esi
cmpq %rax, %r8
setb %sil
movq %r9, %rdi
cmovbq %rcx, %rdi
movq 0x10(%r9,%rsi,8), %r9
testq %r9, %r9
jne 0xf708
movq %r10, %rsi
cmpq %r10, %rdi
je 0xf746
cmpq %rax, %r8
cmovbq %rcx, %rdx
cmpq 0x20(%rdx), %rax
cmovbq %r10, %rdi
movq %rdi, %rsi
cmpl $0x0, 0x28(%rsi)
jne 0xf756
leaq 0x50(%rsp), %rdi
callq 0x121e6
movq (%r12), %r12
cmpq (%rbp), %r12
jne 0xf6c7
jmp 0xf677
cmpl $-0x2, 0x20(%rsp)
jne 0xf865
movq (%rsp), %rax
movzbl 0x8(%rax), %esi
movq 0x8(%rsp), %rdi
callq 0xdfa8
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
jne 0xf7a0
movq %r15, 0x30(%r14)
movl 0x34(%rsp), %eax
movl %eax, 0x38(%r14)
movb $0x0, 0x3c(%r14)
movb $0x1, 0x3d(%r14)
movl $0x2, 0x40(%r14)
movq 0x40(%rsp), %rax
movq (%rax), %rdi
movq 0x38(%rsp), %rax
movq (%rax), %rbx
movq %r14, %rsi
xorl %edx, %edx
callq 0xe099
movq %rbx, %rdi
movq %r14, %rsi
movl $0x1, %edx
callq 0xe099
movq 0x68(%rsp), %rbp
leaq 0x58(%rsp), %rax
cmpq %rax, %rbp
je 0xf865
leaq 0x1126b(%rip), %rbx     # 0x20a58
movq 0x20(%rbp), %rax
cmpl $0x2, 0x3c(%rax)
je 0xf80a
movq %rbx, %rdi
xorl %eax, %eax
callq 0xa10c
xorl %edi, %edi
xorl %esi, %esi
callq 0xa655
movl 0x28(%rbp), %eax
testl %eax, %eax
jle 0xf82d
movq 0x20(%rbp), %rsi
movq %r14, %rdi
xorl %edx, %edx
callq 0xe00b
movl 0x28(%rbp), %ecx
leal -0x1(%rcx), %eax
movl %eax, 0x28(%rbp)
cmpl $0x1, %ecx
jg 0xf811
testl %eax, %eax
jns 0xf850
movq 0x20(%rbp), %rsi
movq %r14, %rdi
movl $0x1, %edx
callq 0xe00b
movl 0x28(%rbp), %eax
leal 0x1(%rax), %ecx
movl %ecx, 0x28(%rbp)
cmpl $-0x1, %eax
jl 0xf831
movq %rbp, %rdi
callq 0x4200
movq %rax, %rbp
leaq 0x58(%rsp), %rax
cmpq %rax, %rbp
jne 0xf7ed
movq 0x40(%rsp), %rax
movq (%rax), %rbp
movq 0x38(%rsp), %rax
movq (%rax), %r10
movb $0x1, %cl
xorl %eax, %eax
movq %rbp, %rdx
movq (%rdx), %rdi
movq (%rdi), %rsi
cmpq %rdi, %rsi
je 0xf8bf
movq 0x10(%rsi), %r8
movq (%r8), %r9
movq (%r9), %r8
cmpq %r9, %r8
je 0xf8ba
movq 0x10(%r8), %rdi
movb %al, 0x41(%rdi)
movq 0x10(%r8), %rdi
movb %al, 0x40(%rdi)
movq 0x10(%r8), %rdi
movb %al, 0x38(%rdi)
movq (%r8), %r8
movq 0x10(%rsi), %rdi
cmpq (%rdi), %r8
jne 0xf896
movq (%rdx), %rdi
movq (%rsi), %rsi
jmp 0xf882
movq %r10, %rdx
testb $0x1, %cl
movl $0x0, %ecx
jne 0xf87c
movb $0x1, %al
xorl %ecx, %ecx
movq %rbp, %rdx
movq (%rdx), %rdi
movq (%rdi), %rsi
cmpq %rdi, %rsi
je 0xf90a
movq 0x10(%rsi), %r8
movq (%r8), %r9
movq (%r9), %r8
cmpq %r9, %r8
je 0xf905
movq 0x10(%r8), %rdi
movb $0x1, 0x40(%rdi,%rcx)
movq (%r8), %r8
movq 0x10(%rsi), %rdi
cmpq (%rdi), %r8
jne 0xf8ed
movq (%rdx), %rdi
movq (%rsi), %rsi
jmp 0xf8d9
movl $0x1, %ecx
movq %r10, %rdx
testb $0x1, %al
movl $0x0, %eax
jne 0xf8d3
movb $0x1, %al
leaq 0x11134(%rip), %r14     # 0x20a58
movq %r10, 0x20(%rsp)
movl %eax, 0x10(%rsp)
movq (%rbp), %rax
movq (%rax), %rbx
cmpq %rax, %rbx
je 0xfa44
movq 0x10(%rbx), %rcx
movq (%rcx), %rcx
movq (%rcx), %r12
cmpq %rcx, %r12
je 0xfa3c
movq 0x10(%r12), %rax
cmpb $0x0, 0x38(%rax)
jne 0xfa27
movb $0x1, 0x38(%rax)
movq 0x10(%r12), %rax
cmpb $0x0, 0x20(%rax)
jne 0xfa27
movb 0x41(%rax), %dl
cmpb $0x1, 0x40(%rax)
jne 0xf9c4
movl 0x3c(%rax), %ecx
testb %dl, %dl
je 0xf9f3
cmpl $0x2, %ecx
je 0xf99f
movq %r14, %rdi
xorl %eax, %eax
callq 0xa10c
xorl %edi, %edi
xorl %esi, %esi
callq 0xa655
movq 0x10(%r12), %rax
movq 0x30(%rax), %rdi
movq (%rsp), %rax
movq 0x10(%rax), %rcx
movq %r15, %rsi
movl 0x34(%rsp), %edx
movq %r13, %r8
movq 0xd8(%rsp), %r9
callq 0xdc7c
jmp 0xfa27
testb %dl, %dl
je 0xfa27
cmpl $0x0, 0x3c(%rax)
movq 0xd8(%rsp), %rdx
jne 0xfa16
movq %r14, %rdi
xorl %eax, %eax
callq 0xa10c
xorl %edi, %edi
xorl %esi, %esi
callq 0xa655
movq 0xd8(%rsp), %rdx
jmp 0xfa11
movq %r13, %rdx
cmpl $0x1, %ecx
jne 0xfa16
movq %r14, %rdi
xorl %eax, %eax
callq 0xa10c
xorl %edi, %edi
xorl %esi, %esi
callq 0xa655
movq %r13, %rdx
movq 0x10(%r12), %rax
movq 0x30(%rax), %rdi
movq (%rsp), %rax
movq 0x10(%rax), %rsi
callq 0xdda3
movq (%r12), %r12
movq 0x10(%rbx), %rax
cmpq (%rax), %r12
jne 0xf950
movq (%rbp), %rax
movq (%rbx), %rbx
jmp 0xf934
movq 0x20(%rsp), %rbp
testb $0x1, 0x10(%rsp)
movl $0x0, %eax
jne 0xf929
movq 0x8(%rsp), %rdi
movq (%rsp), %rsi
callq 0xeb5e
leaq 0x50(%rsp), %rdi
callq 0x119c2
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xfaaa
jmp 0xfaaa
jmp 0xfa9b
jmp 0xfaaa
jmp 0xfaaa
jmp 0xfaaa
jmp 0xfa9b
jmp 0xfaaa
jmp 0xfa9b
jmp 0xfaaa
jmp 0xfa9b
jmp 0xfa9b
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x11972
jmp 0xfab7
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x119c2
movq %rbx, %rdi
callq 0x4540