// File: /workspace/github_cpp_makefile_star2_O2/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 $0xb8, %rsp
movq %r9, 0x48(%rsp)
movq %r8, 0x50(%rsp)
movaps %xmm0, 0x10(%rsp)
movl %ecx, 0x44(%rsp)
movq %rdx, %r15
movq %rsi, %r13
movq %rdi, 0x8(%rsp)
movq (%rsi), %rax
pushq $0x2
popq %rbp
movq %rax, %rcx
movq %rsi, 0x28(%rsp)
movq (%rcx), %rcx
cmpq %rax, %rcx
je 0xd18b
movq %rcx, 0x30(%rsp)
movq 0x10(%rcx), %r12
movb $0x0, 0x3d(%r12)
movq (%r12), %rax
movq %rax, %r13
movq (%r13), %r13
cmpq %rax, %r13
je 0xd17b
movq 0x10(%r13), %rbx
movb $0x0, 0x38(%rbx)
movl %ebp, %eax
movl %ebp, %r14d
subl $0x1, %r14d
jb 0xd175
xorl %esi, %esi
cmpl $0x2, %eax
setne %sil
movq %rbx, %rdi
callq 0xcd13
movb $0x0, 0x28(%rax)
movl %r14d, %eax
jmp 0xd155
movq (%r12), %rax
jmp 0xd13f
movq 0x28(%rsp), %r13
movq (%r13), %rax
movq 0x30(%rsp), %rcx
jmp 0xd121
movapd 0x1106d(%rip), %xmm0    # 0x1e200
xorpd 0x10(%rsp), %xmm0
movapd %xmm0, 0x30(%rsp)
pushq $0x2
popq %rbp
movq %rax, %rcx
movq (%rcx), %rcx
cmpq %rax, %rcx
je 0xd288
movq %rcx, 0x58(%rsp)
movq 0x10(%rcx), %r12
movq (%r12), %rax
movq %rax, %r13
movq (%r13), %r13
cmpq %rax, %r13
je 0xd275
movq 0x10(%r13), %rbx
movl %ebp, %ecx
movl %ecx, %r14d
subl $0x1, %r14d
jb 0xd26c
xorl %esi, %esi
cmpl $0x2, %ecx
setne %sil
movq %rbx, %rdi
callq 0xcd13
cmpb $0x0, 0x28(%rax)
movl %r14d, %ecx
jne 0xd1d4
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 0xd242
andl $0x0, 0x38(%rax)
movl %r14d, %ecx
jmp 0xd1d4
movapd 0x30(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0xd25d
movl $0x1, 0x38(%rax)
movl %r14d, %ecx
jmp 0xd1d4
movl $0x2, 0x38(%rax)
movl %r14d, %ecx
jmp 0xd1d4
movq (%r12), %rax
jmp 0xd1c1
movq 0x28(%rsp), %r13
movq (%r13), %rax
movq 0x58(%rsp), %rcx
jmp 0xd1a5
pushq $0x2
popq %r12
movq %rax, %rcx
movq (%rcx), %rcx
cmpq %rax, %rcx
je 0xd50b
movq 0x10(%rcx), %rbp
movq (%rbp), %rax
movq %rax, %rbx
movq (%rbx), %rbx
cmpq %rax, %rbx
je 0xd502
movq 0x10(%rbx), %r14
cmpb $0x0, 0x38(%r14)
jne 0xd2a6
movq %rbp, 0x30(%rsp)
movq %rcx, 0x10(%rsp)
movb $0x1, 0x38(%r14)
movl $0x2, 0x3c(%r14)
movl %r12d, %eax
movl %r12d, %ecx
movl %r12d, %ebp
subl $0x1, %ebp
jb 0xd31b
xorl %esi, %esi
cmpl $0x2, %eax
setne %sil
movq %r14, %rdi
callq 0xcd13
movl 0x3c(%r14), %ecx
movl 0x38(%rax), %eax
cmpl $0x2, %ecx
je 0xd311
cmpl $0x2, %eax
sete %dl
cmpl %ecx, %eax
sete %al
orb %dl, %al
pushq $-0x2
popq %rax
jne 0xd317
movl %eax, 0x3c(%r14)
movl %eax, %ecx
movl %ebp, %eax
jmp 0xd2dd
cmpl $-0x2, %ecx
jne 0xd39b
movq %r14, %rdi
xorl %esi, %esi
callq 0xcd13
movq %rax, %rbx
movq %r14, %rdi
pushq $0x1
popq %rsi
callq 0xcd13
movq %rax, %r12
movzbl 0x20(%r14), %esi
movq 0x8(%rsp), %rdi
callq 0xc53f
movq %rax, %rbp
movb $0x1, 0x28(%rax)
andq $0x0, 0x30(%rax)
movl $0x2, 0x38(%rax)
movsd 0x30(%rbx), %xmm0
movapd %xmm0, %xmm1
subsd 0x30(%r12), %xmm1
divsd %xmm1, %xmm0
xorl %eax, %eax
cmpq $0x3, %rax
je 0xd3ae
movsd (%rbx,%rax,8), %xmm1
movsd (%r12,%rax,8), %xmm2
subsd %xmm1, %xmm2
mulsd %xmm0, %xmm2
addsd %xmm1, %xmm2
movsd %xmm2, (%rbp,%rax,8)
incq %rax
jmp 0xd373
movq 0x30(%rsp), %rbp
movq (%rbp), %rax
movq 0x10(%rsp), %rcx
jmp 0xd2a6
movzbl 0x20(%r14), %esi
movq 0x8(%rsp), %rdi
callq 0xc58a
movq %rax, %r13
movq %rax, %rdi
movq %rbx, %rsi
movq %rbp, %rdx
callq 0xc669
movb $0x1, 0x38(%r13)
movl 0x38(%rbx), %eax
movl %eax, 0x3c(%r13)
cmpb $0x0, 0x20(%r13)
jne 0xd41c
movq 0x30(%r14), %rdi
callq 0xc140
movq %rax, 0x30(%r13)
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 0xc58a
movq %rax, %rbx
movq %rax, %rdi
movq %rbp, %rsi
movq %r12, %rdx
callq 0xc669
movb $0x1, 0x38(%rbx)
movl 0x38(%r12), %eax
movl %eax, 0x3c(%rbx)
cmpb $0x0, 0x20(%rbx)
jne 0xd48f
movq 0x30(%r14), %rdi
callq 0xc140
movq %rax, 0x30(%rbx)
movsd (%r12), %xmm0
movsd %xmm0, (%rax)
movsd 0x8(%r12), %xmm0
movsd %xmm0, 0x8(%rax)
movsd 0x10(%r12), %xmm0
movsd %xmm0, 0x10(%rax)
movups (%rbp), %xmm0
movups %xmm0, 0x18(%rax)
movsd 0x10(%rbp), %xmm0
movsd %xmm0, 0x28(%rax)
movq 0x30(%rsp), %rbp
movq 0x28(%r14), %rax
movq (%rax), %r12
cmpq %rax, %r12
je 0xd4db
movq 0x10(%r12), %rdi
movzbl 0x18(%r12), %edx
movq %r13, %rsi
callq 0xc6ed
movq 0x10(%r12), %rdi
movzbl 0x18(%r12), %edx
movq %rbx, %rsi
callq 0xc6ed
movq 0x10(%r12), %rdi
movzbl 0x18(%r12), %edx
movq %r14, %rsi
callq 0xce62
jmp 0xd494
movq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0xce8a
movq (%rbp), %rax
movq %rax, %rbx
movq 0x28(%rsp), %r13
pushq $0x2
popq %r12
movq 0x10(%rsp), %rcx
jmp 0xd2a6
movq (%r13), %rax
jmp 0xd28f
pushq $-0x2
popq %r9
movq %rax, %rcx
movq (%rcx), %rcx
cmpq %rax, %rcx
je 0xd9a0
movq 0x10(%rcx), %r14
cmpb $0x0, 0x3d(%r14)
jne 0xd512
movb $0x1, 0x3d(%r14)
movl $0x2, 0x40(%r14)
movq (%r14), %rax
pushq $0x2
popq %rsi
movq %rax, %rdx
movq (%rdx), %rdx
cmpq %rax, %rdx
je 0xd570
movq 0x10(%rdx), %rdi
movl 0x3c(%rdi), %edi
cmpl $0x2, %esi
je 0xd568
cmpl $0x2, %edi
sete %r8b
cmpl %esi, %edi
sete %dil
orb %r8b, %dil
jne 0xd53f
movl %r9d, %edi
movl %edi, 0x40(%r14)
movl %edi, %esi
jmp 0xd53f
cmpl $-0x2, %esi
jne 0xd73d
movzbl 0x8(%r14), %esi
movq 0x8(%rsp), %rdi
callq 0xc68f
movq %rax, %r12
cmpb $0x0, 0x8(%r14)
jne 0xd5ad
movq 0x30(%r14), %rax
movq %rax, 0x30(%r12)
movl 0x38(%r14), %eax
movl %eax, 0x38(%r12)
movb 0x3c(%r14), %al
movb %al, 0x3c(%r12)
movq %r14, %rdi
xorl %esi, %esi
callq 0xcf42
movq %rax, %rbx
movq %r14, %rdi
pushq $0x1
popq %rsi
callq 0xcf42
movq %r12, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0xc7d3
movb $0x1, 0x3d(%r12)
movq %r12, 0x30(%rsp)
andl $0x0, 0x40(%r12)
movzbl 0x8(%r14), %esi
movq 0x8(%rsp), %rdi
callq 0xc68f
movq %rax, %r12
cmpb $0x0, 0x8(%r14)
jne 0xd618
movq 0x30(%r14), %rax
movq %rax, 0x30(%r12)
movl 0x38(%r14), %eax
movl %eax, 0x38(%r12)
movb 0x3c(%r14), %al
movb %al, 0x3c(%r12)
movq %r14, %rdi
xorl %esi, %esi
callq 0xcf42
movq %rax, %rbx
movq %r14, %rdi
pushq $0x1
popq %rsi
callq 0xcf42
movq %r12, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0xc7d3
andl $0x0, 0x80(%rsp)
andq $0x0, 0x88(%rsp)
leaq 0x80(%rsp), %rbx
movq %rbx, 0x90(%rsp)
movq %rbx, 0x98(%rsp)
andq $0x0, 0xa0(%rsp)
movb $0x1, 0x3d(%r12)
movq %r12, 0x58(%rsp)
movl $0x1, 0x40(%r12)
movq %r14, 0x10(%rsp)
movq (%r14), %rax
movq %rax, %r14
movq (%r14), %r14
cmpq %rax, %r14
je 0xd746
movq 0x10(%r14), %rsi
cmpl $0x1, 0x3c(%rsi)
movzbl 0x18(%r14), %edx
jne 0xd71e
movq 0x58(%rsp), %rdi
callq 0xc6ed
movq 0x10(%r14), %rbx
xorl %ebp, %ebp
cmpl $0x2, %ebp
je 0xd728
xorl %esi, %esi
testl %ebp, %ebp
setne %sil
movq %rbx, %rdi
callq 0xcd13
movq %rax, 0x60(%rsp)
movzbl 0x18(%r14), %r12d
leaq 0x78(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0xfa52
xorl %ecx, %ecx
cmpl %r12d, %ebp
sete %cl
movl (%rax), %edx
leal -0x1(%rdx,%rcx,2), %ecx
movl %ecx, (%rax)
leaq 0x78(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x10422
cmpl $0x0, 0x28(%rax)
jne 0xd71a
leaq 0x78(%rsp), %rdi
movq %rax, %rsi
callq 0x10458
incl %ebp
jmp 0xd6ba
movq 0x30(%rsp), %rdi
callq 0xc6ed
movq 0x10(%rsp), %rax
movq (%rax), %rax
leaq 0x80(%rsp), %rbx
jmp 0xd68f
movq (%r13), %rax
jmp 0xd512
cmpq $0x2, 0xa0(%rsp)
je 0xd8f1
pushq $0x2
popq %rdi
leaq 0x11114(%rip), %rsi     # 0x1e873
xorl %eax, %eax
callq 0x9035
jmp 0xd8f1
leaq 0x1112d(%rip), %rdi     # 0x1e89f
xorl %eax, %eax
callq 0x8d93
xorl %edi, %edi
xorl %esi, %esi
callq 0x92bb
cmpl $0x1, 0x28(%r14)
jne 0xd78f
cmpl $-0x1, 0x28(%rbp)
je 0xd7a0
pushq $0x2
popq %rdi
leaq 0x11139(%rip), %rsi     # 0x1e8d2
xorl %eax, %eax
callq 0x9035
movq 0x20(%r14), %rax
cmpl $0x2, 0x38(%rax)
jne 0xd7b4
movq 0x20(%rbp), %rax
cmpl $0x2, 0x38(%rax)
je 0xd7cb
leaq 0x11144(%rip), %rdi     # 0x1e8ff
xorl %eax, %eax
callq 0x8d93
xorl %edi, %edi
xorl %esi, %esi
callq 0x92bb
movq 0x10(%rsp), %rax
movzbl 0x8(%rax), %esi
movq 0x8(%rsp), %rdi
callq 0xc58a
movq %rax, %r12
movq 0x20(%r14), %rsi
movq 0x20(%rbp), %rdx
movq %rax, %rdi
callq 0xc669
cmpb $0x0, 0x20(%r12)
jne 0xd8af
movq 0x20(%rbp), %rdi
movq 0x20(%r14), %rsi
callq 0xc204
movq %rax, 0x30(%r12)
movq 0x10(%rsp), %rdi
movzbl 0x3c(%rdi), %esi
callq 0xcf42
cmpb $0x0, 0x8(%rax)
jne 0xd83a
movq 0x10(%rsp), %rdi
movzbl 0x3c(%rdi), %esi
xorl $0x1, %esi
callq 0xcf42
cmpb $0x1, 0x8(%rax)
jne 0xd851
leaq 0x110f1(%rip), %rdi     # 0x1e932
xorl %eax, %eax
callq 0x8d93
xorl %edi, %edi
xorl %esi, %esi
callq 0x92bb
movq 0x30(%r12), %rax
movq %rax, 0xb0(%rsp)
movq 0x10(%rsp), %rdi
movq 0x30(%rdi), %r13
movl 0x38(%rdi), %eax
movl %eax, 0xac(%rsp)
movzbl 0x3c(%rdi), %esi
callq 0xcf42
movq 0x10(%rax), %rbx
movq 0x10(%rsp), %rdi
movzbl 0x3c(%rdi), %esi
xorl $0x1, %esi
callq 0xcf42
movq 0x10(%rax), %r9
movq 0xb0(%rsp), %rdi
movq %r13, %rsi
movl 0xac(%rsp), %edx
xorl %ecx, %ecx
movq %rbx, %r8
callq 0xc394
movb $0x1, 0x38(%r12)
movl $0x2, 0x3c(%r12)
movq 0x30(%rsp), %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0xc6ed
movq 0x58(%rsp), %rdi
movq %r12, %rsi
pushq $0x1
popq %rdx
callq 0xc6ed
decl 0x28(%r14)
incl 0x28(%rbp)
movq 0x28(%rsp), %r13
leaq 0x80(%rsp), %rbx
movq 0x90(%rsp), %rbp
movq %rbp, %r14
cmpq %rbx, %r14
je 0xd920
cmpl $0x0, 0x28(%r14)
jg 0xd920
movq %r14, %rdi
callq 0x4200
movq %rax, %r14
jmp 0xd8fc
movq %rbp, %rdi
callq 0x4200
movq %rax, %rbp
cmpq %rbx, %rbp
je 0xd939
cmpl $0x0, 0x28(%rbp)
jns 0xd915
cmpq %rbx, %r14
jne 0xd782
jmp 0xd76b
cmpq %rbx, %r14
jne 0xd76b
pushq $0x2
popq %rbp
movl %ebp, %ebx
movq 0x10(%rsp), %r14
subl $0x1, %ebx
jb 0xd979
xorl %esi, %esi
cmpl $0x2, %ebp
setne %sil
movq %r14, %rdi
callq 0xcf42
xorl %edx, %edx
cmpl $0x2, %ebp
setne %dl
movq %rax, %rdi
movq %r14, %rsi
callq 0xcf75
movl %ebx, %ebp
jmp 0xd94c
movq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0xcfca
leaq 0x78(%rsp), %rdi
callq 0xfbb6
movq (%r13), %rax
movq %rax, %rcx
pushq $-0x2
popq %r9
jmp 0xd512
cmpb $0x1, 0x8(%r13)
jne 0xd9c4
leaq 0x10fcf(%rip), %rdi     # 0x1e97d
xorl %eax, %eax
callq 0x8d93
xorl %edi, %edi
xorl %esi, %esi
callq 0x92bb
movb 0x8(%r13), %al
jmp 0xd9c6
xorl %eax, %eax
movzbl %al, %esi
andl $0x1, %esi
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0xc7ff
movq 0x50(%rsp), %r14
movq %rax, (%r14)
movzbl 0x8(%r13), %esi
movq %rbx, %rdi
callq 0xc7ff
movq 0x48(%rsp), %rdx
movq %rax, (%rdx)
movq (%r14), %rax
movq 0xf0(%rsp), %rcx
movq %rcx, 0x10(%rax)
movq (%rdx), %rax
movq 0xf8(%rsp), %rcx
movq %rcx, 0x10(%rax)
movq (%r13), %rax
pushq $0x2
popq %rcx
movl %ecx, 0x10(%rsp)
pushq $-0x2
popq %rcx
movq %rax, %rdx
leaq 0x80(%rsp), %rbx
movq (%rdx), %rdx
cmpq %rax, %rdx
je 0xda5d
movq 0x10(%rdx), %rsi
movl 0x40(%rsi), %esi
cmpl $0x2, 0x10(%rsp)
je 0xda57
cmpl $0x2, %esi
je 0xda2d
movl 0x10(%rsp), %edi
cmpl %edi, %esi
cmovnel %ecx, %edi
movl %edi, 0x10(%rsp)
jmp 0xda2d
movl %esi, 0x10(%rsp)
jmp 0xda2d
leaq 0x78(%rsp), %rcx
andl $0x0, 0x8(%rcx)
andq $0x0, 0x10(%rcx)
movq %rbx, 0x18(%rcx)
movq %rbx, 0x20(%rcx)
andq $0x0, 0x28(%rcx)
movl 0x10(%rsp), %ecx
xorl $0x1, %ecx
movl %ecx, 0x30(%rsp)
movq (%rax), %rcx
cmpq %rax, %rcx
je 0xdb67
movq 0x10(%rcx), %r12
movzbl 0x18(%rcx), %ebp
movq %r13, %rdi
movq %r12, %rsi
movl %ebp, %edx
callq 0xcf75
movl 0x40(%r12), %eax
testl %eax, %eax
je 0xdab9
cmpl $0x2, %eax
jne 0xdad6
cmpl $0x1, 0x10(%rsp)
je 0xdad6
movq 0x50(%rsp), %rax
movq (%rax), %rdi
movq %r12, %rsi
movl %ebp, %edx
callq 0xc754
movq 0x28(%rsp), %r13
movq (%r13), %rax
jmp 0xda83
movl %eax, %ecx
xorl $0x2, %ecx
orl 0x30(%rsp), %ecx
sete %cl
cmpl $0x1, %eax
je 0xdaeb
testb %cl, %cl
je 0xdacb
movq 0x48(%rsp), %rax
movq (%rax), %rdi
movq %r12, %rsi
movl %ebp, %edx
callq 0xc754
cmpl $-0x2, 0x10(%rsp)
jne 0xdacb
movq (%r12), %rax
movq %rax, %r13
movq (%r13), %r13
cmpq %rax, %r13
je 0xdacb
leaq 0x10(%r13), %rbx
movb 0x18(%r13), %r14b
leaq 0x78(%rsp), %rdi
movq %rbx, %rsi
callq 0xfaa2
xorl %ecx, %ecx
cmpb %bpl, %r14b
sete %cl
movl (%rax), %edx
leal -0x1(%rdx,%rcx,2), %ecx
movl %ecx, (%rax)
leaq 0x78(%rsp), %rdi
movq %rbx, %rsi
callq 0x10728
cmpl $0x0, 0x28(%rax)
jne 0xdb59
leaq 0x78(%rsp), %rdi
movq %rax, %rsi
callq 0x1075e
movq (%r12), %rax
leaq 0x80(%rsp), %rbx
jmp 0xdb0b
cmpl $-0x2, 0x10(%rsp)
jne 0xdc43
movq 0x28(%rsp), %rax
movzbl 0x8(%rax), %esi
movq 0x8(%rsp), %rdi
callq 0xc68f
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
jne 0xdb9f
movq %r15, 0x30(%r14)
movl 0x44(%rsp), %eax
movl %eax, 0x38(%r14)
movb $0x0, 0x3c(%r14)
movb $0x1, 0x3d(%r14)
movl $0x2, 0x40(%r14)
movq 0x50(%rsp), %rax
movq (%rax), %rsi
movq 0x48(%rsp), %rax
movq (%rax), %rdx
movq %r14, %rdi
callq 0xc7d3
movq 0x90(%rsp), %r13
pushq $0x1
popq %rbp
leaq 0x10de2(%rip), %r12     # 0x1e9b8
cmpq %rbx, %r13
je 0xdc43
movq 0x20(%r13), %rax
cmpl $0x2, 0x3c(%rax)
je 0xdbf8
movq %r12, %rdi
xorl %eax, %eax
callq 0x8d93
xorl %edi, %edi
xorl %esi, %esi
callq 0x92bb
movl 0x28(%r13), %eax
testl %eax, %eax
jle 0xdc32
movq 0x20(%r13), %rsi
movq %r14, %rdi
xorl %edx, %edx
callq 0xc6ed
movl 0x28(%r13), %eax
decl %eax
movl %eax, 0x28(%r13)
jmp 0xdbfc
movq 0x20(%r13), %rsi
movq %r14, %rdi
movl %ebp, %edx
callq 0xc6ed
movl 0x28(%r13), %eax
incl %eax
movl %eax, 0x28(%r13)
testl %eax, %eax
js 0xdc1a
movq %r13, %rdi
callq 0x4200
movq %rax, %r13
jmp 0xdbd6
movq 0x50(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x60(%rsp)
movq 0x48(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x68(%rsp)
xorl %eax, %eax
xorl %ecx, %ecx
cmpq $0x2, %rcx
je 0xdcb7
movq 0x60(%rsp,%rcx,8), %rdx
movq (%rdx), %rdi
movq %rdi, %rsi
movq (%rsi), %rsi
cmpq %rdi, %rsi
je 0xdcb2
movq 0x10(%rsi), %rdi
movq (%rdi), %r8
movq %r8, %rdi
movq (%rdi), %rdi
cmpq %r8, %rdi
je 0xdcad
movq 0x10(%rdi), %r8
movb %al, 0x41(%r8)
movq 0x10(%rdi), %r8
movb %al, 0x40(%r8)
movq 0x10(%rdi), %r8
movb %al, 0x38(%r8)
movq 0x10(%rsi), %r8
movq (%r8), %r8
jmp 0xdc84
movq (%rdx), %rdi
jmp 0xdc72
incq %rcx
jmp 0xdc61
xorl %eax, %eax
movq 0x28(%rsp), %rsi
cmpq $0x2, %rax
je 0xdd05
movq 0x60(%rsp,%rax,8), %rcx
movq (%rcx), %rdi
movq %rdi, %rdx
movq (%rdx), %rdx
cmpq %rdi, %rdx
je 0xdd00
movq 0x10(%rdx), %rdi
movq (%rdi), %rdi
movq %rdi, %r8
movq (%r8), %r8
cmpq %rdi, %r8
je 0xdcfb
movq 0x10(%r8), %rdi
movb $0x1, 0x40(%rdi,%rax)
movq 0x10(%rdx), %rdi
movq (%rdi), %rdi
jmp 0xdce1
movq (%rcx), %rdi
jmp 0xdccf
incq %rax
jmp 0xdcbe
leaq 0x10cac(%rip), %r14     # 0x1e9b8
xorl %ebx, %ebx
cmpq $0x2, %rbx
je 0xde4e
movq 0x60(%rsp,%rbx,8), %r12
movq (%r12), %rax
movq %rax, %r13
movq (%r13), %r13
cmpq %rax, %r13
je 0xde41
movq 0x10(%r13), %rax
movq (%rax), %rax
movq %rax, %rbp
movq (%rbp), %rbp
cmpq %rax, %rbp
je 0xde38
movq 0x10(%rbp), %rax
cmpb $0x0, 0x38(%rax)
jne 0xde2c
movb $0x1, 0x38(%rax)
movq 0x10(%rbp), %rax
cmpb $0x0, 0x20(%rax)
jne 0xde2c
movb 0x41(%rax), %dl
cmpb $0x1, 0x40(%rax)
jne 0xddbf
movl 0x3c(%rax), %ecx
testb %dl, %dl
je 0xddee
cmpl $0x2, %ecx
je 0xdd94
movq %r14, %rdi
xorl %eax, %eax
callq 0x8d93
xorl %edi, %edi
xorl %esi, %esi
callq 0x92bb
movq 0x10(%rbp), %rax
movq 0x30(%rax), %rdi
movq 0x28(%rsp), %rax
movq 0x10(%rax), %rcx
movq %r15, %rsi
movl 0x44(%rsp), %edx
movq 0xf0(%rsp), %r8
movq 0xf8(%rsp), %r9
callq 0xc394
jmp 0xde2c
testb %dl, %dl
je 0xde2c
cmpl $0x0, 0x3c(%rax)
movq 0xf8(%rsp), %rdx
jne 0xde1a
movq %r14, %rdi
xorl %eax, %eax
callq 0x8d93
xorl %edi, %edi
xorl %esi, %esi
callq 0x92bb
movq 0xf8(%rsp), %rdx
jmp 0xde16
movq 0xf0(%rsp), %rdx
cmpl $0x1, %ecx
jne 0xde1a
movq %r14, %rdi
xorl %eax, %eax
callq 0x8d93
xorl %edi, %edi
xorl %esi, %esi
callq 0x92bb
movq 0xf0(%rsp), %rdx
movq 0x10(%rbp), %rax
movq 0x30(%rax), %rdi
movq 0x28(%rsp), %rax
movq 0x10(%rax), %rsi
callq 0xc4af
movq 0x10(%r13), %rax
movq (%rax), %rax
jmp 0xdd3b
movq (%r12), %rax
jmp 0xdd24
incq %rbx
movq 0x28(%rsp), %rsi
jmp 0xdd0e
movq 0x8(%rsp), %rdi
callq 0xd07d
leaq 0x78(%rsp), %rdi
callq 0xfc0e
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xde90
jmp 0xde9f
jmp 0xde9f
jmp 0xde90
jmp 0xde9f
jmp 0xde90
jmp 0xde9f
jmp 0xde9f
jmp 0xde9f
jmp 0xde90
jmp 0xde90
jmp 0xde90
jmp 0xde9f
jmp 0xde9f
movq %rax, %rbx
leaq 0x78(%rsp), %rdi
callq 0xfbb6
jmp 0xdeac
movq %rax, %rbx
leaq 0x78(%rsp), %rdi
callq 0xfc0e
movq %rbx, %rdi
callq 0x4550