// File: /workspace/github_c_makefile_star2_O2/zhiyb[P]png2tlg/png2tlg.cpp
// Function: SaveTLG6(std::ostream*, tTVPBaseBitmap const*, bool)
void SaveTLG6( std::ostream* stream, const tTVPBaseBitmap* bmp, bool is24 )
{
	std::ostream *out = stream;

	// DWORD medstart, medend;
#ifdef WRITE_ENTROPY_VALUES
	FILE *vs = fopen("vs.bin", "wb");
#endif

	int colors;

	TVPTLG6InitGolombTable();

	// check pixel format
	if( bmp->Is32BPP() ) {
		if( is24 ) colors = 3;
		else colors = 4;
	} else {
		colors = 1;
	}
	int stride = colors;
	if( stride == 3 ) stride = 4;

	// output stream header
	{
		out->write("TLG6.0\x00raw\x1a\x00", 11);
		out->write((const char *)&colors, 1);
		int n = 0;
		out->write((const char *)&n, 1); // data flag (0)
		out->write((const char *)&n, 1); // color type (0)
		out->write((const char *)&n, 1); // external golomb table (0)
		int width = bmp->GetWidth();
		int height = bmp->GetHeight();
		WriteInt32(width, out);
		WriteInt32(height, out);
	}

	// compress
	long max_bit_length = 0;

	unsigned char *buf[MAX_COLOR_COMPONENTS];
	for(int i = 0; i < MAX_COLOR_COMPONENTS; i++) buf[i] = NULL;
	char *block_buf[MAX_COLOR_COMPONENTS];
	for(int i = 0; i < MAX_COLOR_COMPONENTS; i++) block_buf[i] = NULL;
	unsigned char *filtertypes = NULL;
	std::stringstream *memstream = NULL;

	try
	{
		memstream = new std::stringstream();

		TLG6BitStream bs(memstream);

//		int buf_size = bmp->Width * bmp->Height;

		// allocate buffer
		for(int c = 0; c < colors; c++)
		{
			buf[c] = new unsigned char [W_BLOCK_SIZE * H_BLOCK_SIZE * 3];
			block_buf[c] = new char [H_BLOCK_SIZE * bmp->GetWidth()];
		}
		int w_block_count = (int)((bmp->GetWidth() - 1) / W_BLOCK_SIZE) + 1;
		int h_block_count = (int)((bmp->GetHeight() - 1) / H_BLOCK_SIZE) + 1;
		filtertypes = new unsigned char [w_block_count * h_block_count];

		int fc = 0;
		for(int y = 0; y < (int)bmp->GetHeight(); y += H_BLOCK_SIZE)
		{
			int ylim = y + H_BLOCK_SIZE;
			if(ylim > (int)bmp->GetHeight()) ylim = bmp->GetHeight();
			int gwp = 0;
			int xp = 0;
			for(int x = 0; x < (int)bmp->GetWidth(); x += W_BLOCK_SIZE, xp++)
			{
				int xlim = x + W_BLOCK_SIZE;
				if(xlim > (int)bmp->GetWidth()) xlim = bmp->GetWidth();
				int bw = xlim - x;

				int p0size; // size of MED method (p=0)
				int minp = 0; // most efficient method (0:MED, 1:AVG)
				int ft; // filter type
				int wp; // write point
				for(int p = 0; p < 2; p++)
				{
					int dbofs = (p+1) * (H_BLOCK_SIZE * W_BLOCK_SIZE);

					// do med(when p=0) or take average of upper and left pixel(p=1)
					for(int c = 0; c < colors; c++)
					{
						int wp = 0;
						for(int yy = y; yy < ylim; yy++)
						{
							const unsigned char * sl = x*stride +
								c + (const unsigned char *)bmp->GetScanLine(yy);
							const unsigned char * usl;
							if(yy >= 1)
								usl = x*stride + c + (const unsigned char *)bmp->GetScanLine(yy-1);
							else
								usl = NULL;
							for(int xx = x; xx < xlim; xx++)
							{
								unsigned char pa = xx > 0 ? sl[-stride] : 0;
								unsigned char pb = usl ? *usl : 0;
								unsigned char px = *sl;

								unsigned char py;

//								py = 0;
								if(p == 0)
								{
									unsigned char pc = (xx > 0 && usl) ? usl[-stride] : 0;
									unsigned char min_a_b = pa>pb?pb:pa;
									unsigned char max_a_b = pa<pb?pb:pa;

									if(pc >= max_a_b)
										py = min_a_b;
									else if(pc < min_a_b)
										py = max_a_b;
									else
										py = pa + pb - pc;
								}
								else
								{
									py = (pa+pb+1)>>1;
								}
								
								// stbi_image format is RGBA, so swap to BGRA
								int wc = c == 0 ? 2 : c == 2 ? 0 : c;
								buf[wc][wp] = (unsigned char)(px - py);

								wp++;
								sl += stride;
								if(usl) usl += stride;
							}
						}
					}

					// reordering
					// Transfer the data into block_buf (block buffer).
					// Even lines are stored forward (left to right),
					// Odd lines are stored backward (right to left).

					wp = 0;
					for(int yy = y; yy < ylim; yy++)
					{
						int ofs;
						if(!(xp&1))
							ofs = (yy - y)*bw;
						else
							ofs = (ylim - yy - 1) * bw;
						bool dir; // false for forward, true for backward
						if(!((ylim-y)&1))
						{
							// vertical line count per block is even
							dir = ((yy&1) ^ (xp&1)) ? true : false;
						}
						else
						{
							// otherwise;
							if(xp & 1)
							{
								dir = (yy&1);
							}
							else
							{
								dir = ((yy&1) ^ (xp&1)) ? true : false;
							}
						}

						if(!dir)
						{
							// forward
							for(int xx = 0; xx < bw; xx++)
							{
								for(int c = 0; c < colors; c++)
									buf[c][wp + dbofs] =
									buf[c][ofs + xx];
								wp++;
							}
						}
						else
						{
							// backward
							for(int xx = bw - 1; xx >= 0; xx--)
							{
								for(int c = 0; c < colors; c++)
									buf[c][wp + dbofs] =
									buf[c][ofs + xx];
								wp++;
							}
						}
					}
				}


				for(int p = 0; p < 2; p++)
				{
					int dbofs = (p+1) * (H_BLOCK_SIZE * W_BLOCK_SIZE);
					// detect color filter
					int size = 0;
					int ft_;
					if(colors >= 3)
						ft_ = DetectColorFilter(
							reinterpret_cast<char*>(buf[0] + dbofs),
							reinterpret_cast<char*>(buf[1] + dbofs),
							reinterpret_cast<char*>(buf[2] + dbofs), wp, size);
					else
						ft_ = 0;

					// select efficient mode of p (MED or average)
					if(p == 0)
					{
						p0size = size;
						ft = ft_;
					}
					else
					{
						if(p0size >= size)
							minp = 1, ft = ft_;
					}
				}

				// Apply most efficient color filter / prediction method
				wp = 0;
				int dbofs = (minp + 1)  * (H_BLOCK_SIZE * W_BLOCK_SIZE);
				for(int yy = y; yy < ylim; yy++)
				{
					for(int xx = 0; xx < bw; xx++)
					{
						for(int c = 0; c < colors; c++)
							block_buf[c][gwp + wp] = buf[c][wp + dbofs];
						wp++;
					}
				}

				ApplyColorFilter(block_buf[0] + gwp,
					block_buf[1] + gwp, block_buf[2] + gwp, wp, ft);

				filtertypes[fc++] = (ft<<1) + minp;
//				ftfreq[ft]++;
				gwp += wp;
			}

			// compress values (entropy coding)
			for(int c = 0; c < colors; c++)
			{
				int method;
				CompressValuesGolomb(bs, block_buf[c], gwp);
				method = 0;
#ifdef WRITE_ENTROPY_VALUES
				fwrite(block_buf[c], 1, gwp, vs);
#endif
				long bitlength = bs.GetBitLength();
				if(bitlength & 0xc0000000)
					throw std::runtime_error("TVPTlgTooLargeBitLength");
				// two most significant bits of bitlength are
				// entropy coding method;
				// 00 means Golomb method,
				// 01 means Gamma method (implemented but not used),
				// 10 means modified LZSS method (not yet implemented),
				// 11 means raw (uncompressed) data (not yet implemented).
				if(max_bit_length < bitlength) max_bit_length = bitlength;
				bitlength |= (method << 30);
				WriteInt32(bitlength, memstream);
				bs.Flush();
			}

		}


		// write max bit length
		WriteInt32(max_bit_length, out);

		// output filter types
		{
			SlideCompressor comp;
			TLG6InitializeColorFilterCompressor(comp);
			unsigned char *outbuf = new unsigned char[fc * 2];
			try
			{
				long outlen;
				comp.Encode(filtertypes, fc, outbuf, outlen);
				WriteInt32(outlen, out);
				out->write((const char *)outbuf, outlen);
			}
			catch(...)
			{
				delete [] outbuf;
				throw std::runtime_error("Encoding error");
			}
			delete [] outbuf;

		}

		// copy memory stream to output stream
		std::string str(memstream->str());
		out->write((const char *)str.data(), (tjs_uint)str.size() );
	}
	catch(...)
	{
		for(int i = 0; i < MAX_COLOR_COMPONENTS; i++)
		{
			if(buf[i]) delete [] (buf[i]);
			if(block_buf[i]) delete [] (block_buf[i]);
		}
		if(filtertypes) delete [] filtertypes;
		if(memstream) delete memstream;
		throw;
	}

	for(int i = 0; i < MAX_COLOR_COMPONENTS; i++)
	{
		if(buf[i]) delete [] (buf[i]);
		if(block_buf) delete [] (block_buf[i]);
	}
	if(filtertypes) delete [] filtertypes;
	if(memstream) delete memstream;

#ifdef WRITE_ENTROPY_VALUES
	fclose(vs);
#endif
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x943b8, %rsp          # imm = 0x943B8
movl %edx, %ebx
movq %rsi, %r15
movq %rdi, %r12
callq 0x46a1
pushq $0x4
popq %rax
subl %ebx, %eax
leaq 0xc(%rsp), %rbx
movl %eax, (%rbx)
leaq 0xaee0(%rip), %rsi      # 0x10388
pushq $0xb
popq %rdx
movq %r12, %rdi
callq 0x21e0
pushq $0x1
popq %r14
movq %r12, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x21e0
leaq 0x2188(%rsp), %rbx
andl $0x0, (%rbx)
movq %r12, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x21e0
movq %r12, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x21e0
movq %r12, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x21e0
movslq (%r15), %rdi
movq %r15, 0x18(%rsp)
movslq 0x4(%r15), %rbx
movq %r12, %rsi
callq 0x5f06
movq %rbx, %rdi
movq %r12, %rsi
callq 0x5f06
xorl %eax, %eax
cmpq $0x4, %rax
je 0x552f
andq $0x0, 0x90(%rsp,%rax,8)
incq %rax
jmp 0x551b
xorl %eax, %eax
cmpq $0x4, %rax
je 0x5545
andq $0x0, 0xb0(%rsp,%rax,8)
incq %rax
jmp 0x5531
movl $0x188, %edi            # imm = 0x188
callq 0x2170
movq %rax, %r15
movq %rax, %rdi
callq 0x2100
andl $0x0, 0x150(%rsp)
leaq 0x10(%r15), %rax
andq $0x0, 0x158(%rsp)
movq %rax, 0xe0(%rsp)
movq %rax, 0x160(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x168(%rsp)
movl 0xc(%rsp), %ebx
xorl %r14d, %r14d
testl %ebx, %ebx
cmovlel %r14d, %ebx
cmpq %r14, %rbx
je 0x55ca
movl $0xc0, %edi
callq 0x2040
movq %rax, 0x90(%rsp,%r14,8)
movq 0x18(%rsp), %rax
movl (%rax), %edi
shll $0x3, %edi
callq 0x2040
movq %rax, 0xb0(%rsp,%r14,8)
incq %r14
jmp 0x5597
movq %r12, 0xd8(%rsp)
movq 0x18(%rsp), %rcx
movl (%rcx), %eax
movl 0x4(%rcx), %ecx
decl %eax
shrl $0x3, %eax
incl %eax
movq %rcx, %rbx
leal -0x1(%rcx), %edi
shrl $0x3, %edi
incl %edi
imull %eax, %edi
callq 0x2040
movq %rax, %r12
movq 0x90(%rsp), %rax
movq 0x98(%rsp), %rcx
movq 0xa0(%rsp), %rdx
movq 0xb0(%rsp), %rsi
movq %rsi, 0xf8(%rsp)
movq 0xb8(%rsp), %rsi
movq %rsi, 0xf0(%rsp)
movq 0xc0(%rsp), %rsi
movq %rsi, 0xe8(%rsp)
addq $0x40, %rdx
movq %rdx, 0x108(%rsp)
addq $0x40, %rcx
movq %rcx, 0x110(%rsp)
addq $0x40, %rax
movq %rax, 0x118(%rsp)
movl $0x0, 0x20(%rsp)
movq %rax, 0x40(%rsp)
xorl %ecx, %ecx
xorl %r13d, %r13d
movq $0x0, 0x38(%rsp)
movq %r15, 0x28(%rsp)
movq %r12, 0x50(%rsp)
movslq %r13d, %rax
movq %rax, 0x30(%rsp)
cmpl %ebx, %ecx
jge 0x5c09
movq %rcx, 0x48(%rsp)
leal 0x8(%rcx), %eax
cmpl %ebx, %eax
movl %eax, 0x60(%rsp)
cmovll %eax, %ebx
movq %rbx, 0x58(%rsp)
xorl %eax, %eax
xorl %esi, %esi
pushq $0x8
popq %rdi
movl $0x0, 0x10(%rsp)
movl $0x0, 0x14(%rsp)
movq 0x18(%rsp), %rcx
movslq (%rcx), %r9
cmpq %r9, %rax
jge 0x5b74
movl 0x14(%rsp), %ecx
movl %ecx, %edx
shll $0x5, %edx
addq $-0x4, %rdx
movq %rdx, 0x120(%rsp)
leaq 0x8(%rax), %r8
cmpl %r9d, %r8d
movl %r9d, %edx
movq %r8, 0x100(%rsp)
cmovll %r8d, %edx
movl %edx, %r8d
subl %eax, %r8d
movq 0x58(%rsp), %r14
testb $0x1, %r14b
movl $0x0, %r10d
cmovel %ecx, %r10d
movl %r10d, 0x70(%rsp)
leal (,%rax,4), %ecx
andl $-0x20, %ecx
movq %rcx, 0x130(%rsp)
cmpl %edi, %r9d
movl %edi, 0x64(%rsp)
cmovgel %edi, %r9d
movl %r8d, 0x74(%rsp)
movslq %r8d, %rcx
movq %rcx, 0x140(%rsp)
movl %esi, 0x68(%rsp)
addl %esi, %r9d
movq %r9, 0x78(%rsp)
movslq %r9d, %rcx
movq %rcx, 0x128(%rsp)
xorl %r11d, %r11d
movq 0x48(%rsp), %rbx
cmpq $0x2, %r11
je 0x59f8
leaq 0x1(%r11), %rcx
movq %rcx, 0x80(%rsp)
movq 0x120(%rsp), %rcx
movq %rcx, 0x88(%rsp)
xorl %esi, %esi
movslq 0xc(%rsp), %rdi
cmpq %rdi, %rsi
jge 0x5919
cmpq $0x2, %rsi
movl %esi, %r10d
movl $0x0, %ecx
cmoveq %rcx, %r10
testq %rsi, %rsi
pushq $0x2
popq %rcx
cmoveq %rcx, %r10
movq 0x130(%rsp), %rcx
movq %rsi, 0x138(%rsp)
addq %rsi, %rcx
movq %rcx, 0x148(%rsp)
movl 0x20(%rsp), %ecx
movl %ecx, 0x24(%rsp)
xorl %esi, %esi
cmpl %r14d, %ebx
jge 0x58fc
movq 0x18(%rsp), %rdi
movq 0x10(%rdi), %rcx
movl (%rdi), %r8d
leal -0x4(,%rbx,4), %r15d
imull %r8d, %r15d
movq 0x148(%rsp), %rdi
addq %rcx, %r15
addq %rdi, %r15
testl %ebx, %ebx
movl $0x0, %edi
cmoveq %rdi, %r15
movslq %esi, %rsi
addq 0x88(%rsp), %rcx
imull 0x24(%rsp), %r8d
addq %rcx, %r8
xorl %ecx, %ecx
leaq (%rax,%rcx), %r12
cmpl %edx, %r12d
jge 0x58e6
testl %r12d, %r12d
je 0x584a
movb (%r8,%rcx,4), %r9b
jmp 0x584d
xorl %r9d, %r9d
testq %r15, %r15
je 0x5857
movb (%r15), %bpl
jmp 0x5859
xorl %ebp, %ebp
movzbl %r9b, %r14d
movzbl %bpl, %r9d
testq %r11, %r11
je 0x5870
leal (%r14,%r9), %ebp
incl %ebp
shrl %ebp
jmp 0x58bc
testq %r15, %r15
sete %bpl
testl %r12d, %r12d
sete %r13b
xorl %r12d, %r12d
orb %bpl, %r13b
jne 0x588b
movzbl -0x4(%r15), %r12d
cmpb %r9b, %r14b
movl %r9d, %r13d
movl %r9d, %ebp
cmoval %r14d, %ebp
cmovbl %r14d, %r13d
movzbl %bpl, %edi
cmpl %edi, %r12d
jae 0x58b9
movzbl %r13b, %edi
cmpl %edi, %r12d
jb 0x58bc
addl %r14d, %r9d
subl %r12d, %r9d
movl %r9d, %ebp
jmp 0x58bc
movl %r13d, %ebp
movb 0x4(%r8,%rcx,4), %dil
subb %bpl, %dil
movq 0x90(%rsp,%r10,8), %r9
movb %dil, (%r9,%rsi)
incq %rsi
leaq 0x4(%r15), %rdi
testq %r15, %r15
cmovneq %rdi, %r15
incq %rcx
jmp 0x5832
incl %ebx
addl $0x4, 0x24(%rsp)
movq 0x50(%rsp), %r12
movq 0x58(%rsp), %r14
jmp 0x57e2
movq 0x138(%rsp), %rsi
incq %rsi
incq 0x88(%rsp)
movq 0x48(%rsp), %rbx
jmp 0x5795
movq 0x80(%rsp), %rcx
shlq $0x6, %rcx
xorl %ebp, %ebp
movl %ebx, %esi
cmpl %r14d, %esi
jge 0x59eb
movl %esi, %r8d
notl %r8d
addl %r14d, %r8d
movl %esi, %r9d
subl %ebx, %r9d
testb $0x1, 0x14(%rsp)
cmovnel %r8d, %r9d
imull 0x74(%rsp), %r9d
movl %esi, %r10d
xorl 0x70(%rsp), %r10d
movslq %ebp, %rbp
movslq %r9d, %r8
testb $0x1, %r10b
je 0x59a4
movq 0x128(%rsp), %r9
testq %r9, %r9
jle 0x59e4
decq %r9
xorl %r10d, %r10d
movslq %edi, %r11
cmpq %r11, %r10
jge 0x599f
movq 0x90(%rsp,%r10,8), %rdi
leaq (%rdi,%r9), %r11
movb (%r8,%r11), %r11b
addq %rbp, %rdi
movb %r11b, (%rcx,%rdi)
incq %r10
movl 0xc(%rsp), %edi
jmp 0x5977
incq %rbp
jmp 0x596c
xorl %r9d, %r9d
cmpq 0x140(%rsp), %r9
jge 0x59e4
xorl %r10d, %r10d
movslq %edi, %r11
cmpq %r11, %r10
jge 0x59dc
movq 0x90(%rsp,%r10,8), %rdi
leaq (%rdi,%r9), %r11
movb (%r8,%r11), %r11b
addq %rbp, %rdi
movb %r11b, (%rcx,%rdi)
incq %r10
movl 0xc(%rsp), %edi
jmp 0x59b4
incq %rbp
incq %r9
jmp 0x59a7
incl %esi
jmp 0x5929
movq 0x80(%rsp), %r11
jmp 0x576d
xorl %r15d, %r15d
xorl %ebx, %ebx
movl 0x6c(%rsp), %r11d
movq 0x78(%rsp), %r14
cmpq $0x80, %r15
je 0x5a9c
andl $0x0, 0x2188(%rsp)
xorl %eax, %eax
cmpl $0x3, 0xc(%rsp)
jl 0x5a63
movl %r11d, %r14d
movq 0x118(%rsp), %rax
leaq (%rax,%r15), %rdi
movq 0x110(%rsp), %rax
leaq (%rax,%r15), %rsi
movq 0x108(%rsp), %rax
leaq (%rax,%r15), %rdx
movl %ebp, %ecx
leaq 0x2188(%rsp), %r8
callq 0x52c2
movl %r14d, %r11d
movq 0x78(%rsp), %r14
movl 0x2188(%rsp), %ecx
cmpl %ecx, %r11d
setl %dl
movq 0x40(%rsp), %rsi
cmovgel %eax, %esi
testb $0x1, %dl
pushq $0x1
popq %rdx
cmovnel %ebx, %edx
testq %r15, %r15
cmovel %ecx, %r11d
cmovnel %edx, %ebx
cmovel %eax, %esi
movq %rsi, 0x40(%rsp)
addq $0x40, %r15
jmp 0x5a07
movl %ebx, %eax
shlq $0x6, %rax
movslq 0x10(%rsp), %rdx
xorl %ebp, %ebp
testl %r14d, %r14d
cmovlel %ebp, %r14d
movq 0x48(%rsp), %rcx
movq 0x28(%rsp), %r15
cmpl 0x58(%rsp), %ecx
jge 0x5b08
movslq %ebp, %rsi
addl %r14d, %ebp
movslq %ebp, %rdi
cmpq %rdi, %rsi
je 0x5b04
xorl %r8d, %r8d
movslq 0xc(%rsp), %r9
cmpq %r9, %r8
jge 0x5aff
movq 0x90(%rsp,%r8,8), %r9
addq %rsi, %r9
movb 0x40(%rax,%r9), %r9b
movq 0xb0(%rsp,%r8,8), %r10
addq %rsi, %r10
movb %r9b, (%rdx,%r10)
incq %r8
jmp 0x5ad1
incq %rsi
jmp 0x5ac9
incl %ecx
jmp 0x5aba
movl %r11d, 0x6c(%rsp)
movq 0xf8(%rsp), %rax
leaq (%rax,%rdx), %rdi
movq 0xf0(%rsp), %rax
leaq (%rax,%rdx), %rsi
addq 0xe8(%rsp), %rdx
movl %ebp, %ecx
movq 0x40(%rsp), %r14
movl %r14d, %r8d
callq 0x48ff
leal (%rbx,%r14,2), %eax
movq 0x30(%rsp), %rcx
movb %al, (%r12,%rcx)
incq %rcx
movq %rcx, 0x30(%rsp)
addl %ebp, 0x10(%rsp)
incl 0x14(%rsp)
movl 0x64(%rsp), %edi
addl $0x8, %edi
movl 0x68(%rsp), %esi
addl $-0x8, %esi
movq 0x100(%rsp), %rax
jmp 0x56c7
movq 0x30(%rsp), %rax
movl %eax, %r13d
xorl %ebx, %ebx
movslq 0xc(%rsp), %rax
cmpq %rax, %rbx
jge 0x5bf1
movq 0xb0(%rsp,%rbx,8), %rsi
leaq 0x150(%rsp), %rdi
movl 0x10(%rsp), %edx
callq 0x471d
movq 0x158(%rsp), %rax
movslq 0x150(%rsp), %rcx
leaq (%rcx,%rax,8), %rdi
testl $0xc0000000, %edi       # imm = 0xC0000000
jne 0x5d7e
movq 0x38(%rsp), %rax
cmpq %rdi, %rax
cmovleq %rdi, %rax
movq %rax, 0x38(%rsp)
movq 0xe0(%rsp), %rsi
callq 0x5f06
leaq 0x150(%rsp), %rdi
callq 0xf3a2
incq %rbx
jmp 0x5b7e
movq 0x18(%rsp), %rax
movl 0x4(%rax), %ebx
addl $0x20, 0x20(%rsp)
movl 0x60(%rsp), %eax
movl %eax, %ecx
jmp 0x568a
movq 0x38(%rsp), %rdi
movq 0xd8(%rsp), %rbp
movq %rbp, %rsi
callq 0x5f06
leaq 0x2188(%rsp), %rdi
callq 0x4134
xorl %eax, %eax
leaq 0x180(%rsp), %rcx
cmpl $0x20, %eax
je 0x5c66
movzbl %al, %edx
imull $0x1010101, %edx, %edx  # imm = 0x1010101
xorl %esi, %esi
cmpl $0x10, %esi
je 0x5c62
movl %edx, (%rcx)
movzbl %sil, %edi
imull $0x1010101, %edi, %edi  # imm = 0x1010101
movl %edi, 0x4(%rcx)
addq $0x8, %rcx
incq %rsi
jmp 0x5c45
incl %eax
jmp 0x5c35
leaq 0x2188(%rsp), %rdi
leaq 0x180(%rsp), %rsi
leaq 0x1180(%rsp), %rcx
leaq 0x178(%rsp), %r8
movl $0x1000, %edx           # imm = 0x1000
callq 0x437c
addl %r13d, %r13d
movslq %r13d, %rdi
callq 0x2040
movq %rax, %rbx
leaq 0x2188(%rsp), %rdi
leaq 0x180(%rsp), %r14
movq %r12, %rsi
movq 0x30(%rsp), %rdx
movq %rax, %rcx
movq %r14, %r8
callq 0x437c
movq (%r14), %r14
movq %r14, %rdi
movq %rbp, %rsi
callq 0x5f06
movq %rbp, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x21e0
movq %rbx, %rdi
callq 0x21d0
movq %r15, %rsi
addq $0x18, %rsi
leaq 0x2188(%rsp), %rdi
callq 0x2290
movq 0x2188(%rsp), %rsi
movl 0x2190(%rsp), %edx
movq %rbp, %rdi
callq 0x21e0
leaq 0x2188(%rsp), %rdi
callq 0x20b0
leaq 0x150(%rsp), %rdi
callq 0xf414
xorl %ebx, %ebx
cmpq $0x4, %rbx
je 0x5d5b
movq 0x90(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x5d44
callq 0x21d0
movq 0xb0(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x5d56
callq 0x21d0
incq %rbx
jmp 0x5d2c
movq %r12, %rdi
callq 0x21d0
movq (%r15), %rax
movq %r15, %rdi
callq *0x8(%rax)
addq $0x943b8, %rsp          # imm = 0x943B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x10
popq %rdi
callq 0x20d0
movq %rax, %r14
leaq 0xab7f(%rip), %rsi      # 0x1090f
movq %rax, %rdi
callq 0x2080
movq 0xf251(%rip), %rsi      # 0x14ff0
movq 0xf222(%rip), %rdx      # 0x14fc8
movq %r14, %rdi
callq 0x22d0
jmp 0x5eee
movq %rax, %rbx
leaq 0x2188(%rsp), %rdi
callq 0x20b0
jmp 0x5e56
jmp 0x5dca
movq %rax, %rbx
jmp 0x5e56
jmp 0x5e7b
jmp 0x5e62
movq %rax, %rbx
movl $0x188, %esi            # imm = 0x188
movq %r15, %rdi
callq 0x2180
jmp 0x5df1
movq %rax, %rbx
xorl %r15d, %r15d
xorl %r12d, %r12d
jmp 0x5e95
movq %rax, %rdi
callq 0x2090
movq %rbx, %rdi
callq 0x21d0
pushq $0x10
popq %rdi
callq 0x20d0
movq %rax, %r14
leaq 0xab09(%rip), %rsi      # 0x10927
movq %rax, %rdi
callq 0x2080
movq 0xf1c3(%rip), %rsi      # 0x14ff0
movq 0xf194(%rip), %rdx      # 0x14fc8
movq %r14, %rdi
callq 0x22d0
jmp 0x5eee
movq %rax, %rbx
jmp 0x5e51
movq %rax, %rbx
movq %r14, %rdi
callq 0x2120
callq 0x22b0
movq 0x28(%rsp), %r15
movq 0x50(%rsp), %r12
jmp 0x5e88
movq %rax, %rbx
xorl %r12d, %r12d
jmp 0x5e88
jmp 0x5e7b
movq %rax, %rbx
movq %r14, %rdi
callq 0x2120
jmp 0x5e88
jmp 0x5e7b
movq %rax, %rbx
jmp 0x5e88
movq %rax, %rbx
movq 0x28(%rsp), %r15
leaq 0x150(%rsp), %rdi
callq 0xf414
movq %rbx, %rdi
callq 0x2090
xorl %ebx, %ebx
cmpq $0x4, %rbx
je 0x5ece
movq 0x90(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x5eb7
callq 0x21d0
movq 0xb0(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x5ec9
callq 0x21d0
incq %rbx
jmp 0x5e9f
testq %r12, %r12
je 0x5edb
movq %r12, %rdi
callq 0x21d0
testq %r15, %r15
je 0x5ee9
movq (%r15), %rax
movq %r15, %rdi
callq *0x8(%rax)
callq 0x2230
movq %rax, %rbx
callq 0x22b0
movq %rbx, %rdi
callq 0x22e0
movq %rax, %rdi
callq 0xf408