// File: /workspace/github_c_makefile_star2_O3/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 $0x943c8, %rsp          # imm = 0x943C8
movl %edx, %ebx
movq %rsi, %r13
movq %rdi, %r12
callq 0x4c49
movl $0x4, %eax
subl %ebx, %eax
leaq 0x4(%rsp), %rbx
movl %eax, (%rbx)
leaq 0x1287d(%rip), %rsi     # 0x18458
movl $0xb, %edx
movq %r12, %rdi
callq 0x21f0
movl $0x1, %edx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x21f0
leaq 0x190(%rsp), %rbx
movl $0x0, (%rbx)
movl $0x1, %edx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x21f0
movl $0x1, %edx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x21f0
movl $0x1, %edx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x21f0
movl (%r13), %eax
movl 0x4(%r13), %ebp
leaq 0x2198(%rsp), %rbx
movl %eax, (%rbx)
movl $0x4, %edx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x21f0
movl %ebp, (%rbx)
leaq 0x2198(%rsp), %rsi
movl $0x4, %edx
movq %r12, %rdi
callq 0x21f0
xorps %xmm0, %xmm0
movaps %xmm0, 0x90(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0xc0(%rsp)
movaps %xmm0, 0xb0(%rsp)
movl $0x188, %edi            # imm = 0x188
callq 0x2180
movq %rax, %r14
movq %rax, %rdi
callq 0x2110
movq %r14, 0x18(%rsp)
leaq 0x10(%r14), %rax
movl $0x0, 0x160(%rsp)
movq $0x0, 0x168(%rsp)
movq %rax, 0xe8(%rsp)
movq %rax, 0x170(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x178(%rsp)
movslq 0x4(%rsp), %r14
testq %r14, %r14
jle 0x5d23
xorl %r15d, %r15d
movl $0xc0, %edi
callq 0x2040
movq %rax, 0x80(%rsp,%r15,8)
movl (%r13), %ebx
leal (,%rbx,8), %edi
callq 0x2040
movq %rax, 0xb0(%rsp,%r15,8)
incq %r15
cmpq %r15, %r14
jne 0x5cef
jmp 0x5d27
movl (%r13), %ebx
movq %r12, 0x40(%rsp)
decl %ebx
shrl $0x3, %ebx
incl %ebx
movl 0x4(%r13), %ebp
leal -0x1(%rbp), %edi
shrl $0x3, %edi
incl %edi
imull %ebx, %edi
callq 0x2040
movq %rax, %r12
testl %ebp, %ebp
movq %rax, 0x48(%rsp)
jle 0x63f5
movq %rbp, %rcx
movq 0x80(%rsp), %rax
movq %rax, 0x110(%rsp)
movq 0x88(%rsp), %rax
movq %rax, 0x108(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x100(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, 0xe0(%rsp)
movq 0xb8(%rsp), %rax
movq %rax, 0xd8(%rsp)
movq $0x0, 0x50(%rsp)
movq 0xc0(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq $0x0, 0x30(%rsp)
movq $0x0, 0x10(%rsp)
xorl %ebp, %ebp
movq %rax, 0x38(%rsp)
movq %r13, 0x130(%rsp)
movl %ebp, %eax
leal 0x8(%rax), %ebp
cmpl %ecx, %ebp
movl %ecx, %edx
cmovll %ebp, %edx
movl %edx, 0x2c(%rsp)
movl (%r13), %r8d
testl %r8d, %r8d
jle 0x6343
movq %rax, 0x20(%rsp)
movq %rcx, 0x58(%rsp)
movq 0x10(%rsp), %rax
cltq
movq %rax, 0x10(%rsp)
movl $0x8, %edx
xorl %eax, %eax
xorl %ecx, %ecx
xorl %esi, %esi
xorl %edi, %edi
xorl %ebx, %ebx
movl %ebp, 0x74(%rsp)
movl %ebx, 0x8(%rsp)
movq %rax, 0xf8(%rsp)
andl $-0x20, %eax
movq %rax, 0x118(%rsp)
leaq 0x8(%rcx), %rax
cmpl %r8d, %eax
movslq %r8d, %r9
movq %rax, 0xf0(%rsp)
cmovll %eax, %r8d
movl %r8d, 0x7c(%rsp)
movl %r8d, %eax
subl %ecx, %eax
movl 0x2c(%rsp), %r14d
testb $0x1, %r14b
movl $0x0, %r8d
movl %edi, 0x28(%rsp)
cmovel %edi, %r8d
movl %r8d, 0x78(%rsp)
leal (,%rcx,4), %edi
andl $-0x20, %edi
movq %rdi, 0x128(%rsp)
movl %eax, 0xc(%rsp)
cltq
movq %rax, 0x138(%rsp)
cmpl %edx, %r9d
movl %edx, 0x6c(%rsp)
movq %r9, 0x158(%rsp)
cmovll %r9d, %edx
movl %esi, 0x68(%rsp)
addl %esi, %edx
movslq %edx, %rax
movq %rax, 0x120(%rsp)
movl $0x40, %edx
movb $0x1, %r11b
movl 0x4(%rsp), %r10d
testl %r10d, %r10d
jle 0x60b2
movq 0x118(%rsp), %rax
movq %rax, 0xa8(%rsp)
movq $0x0, 0x60(%rsp)
movq 0x20(%rsp), %rax
cmpl %eax, 0x58(%rsp)
jle 0x6091
movq 0x128(%rsp), %rax
movq 0x60(%rsp), %rdi
addq %rdi, %rax
movq %rax, 0x148(%rsp)
xorl %r8d, %r8d
cmpq $0x2, %rdi
movl %edi, %esi
movl $0x0, %r9d
cmovneq %rsi, %r9
testq %rdi, %rdi
movl $0x2, %eax
cmoveq %rax, %r9
movq %r9, 0x140(%rsp)
movq 0x50(%rsp), %rax
movl %eax, %r12d
movq 0x20(%rsp), %rbp
cmpq 0x158(%rsp), %rcx
jge 0x6074
movq 0x10(%r13), %rsi
movl (%r13), %r13d
leal -0x4(,%rbp,4), %r9d
imull %r13d, %r9d
movq 0x148(%rsp), %rax
addq %rsi, %r9
addq %rax, %r9
testl %ebp, %ebp
movl $0x0, %eax
cmoveq %rax, %r9
movq %r8, 0x150(%rsp)
movslq %r8d, %rbx
movq 0x140(%rsp), %rax
addq 0x80(%rsp,%rax,8), %rbx
addq 0xa8(%rsp), %rsi
imull %r12d, %r13d
addq %rsi, %r13
xorl %esi, %esi
movl %ecx, %r14d
addl %esi, %r14d
je 0x5fc1
movb -0x4(%r13,%rsi,4), %r8b
jmp 0x5fc4
xorl %r8d, %r8d
testq %r9, %r9
je 0x5fce
movb (%r9), %dil
jmp 0x5fd0
xorl %edi, %edi
movzbl %r8b, %r10d
movzbl %dil, %r8d
testb $0x1, %r11b
je 0x6027
testq %r9, %r9
sete %dil
testl %r14d, %r14d
sete %r15b
xorl %r14d, %r14d
orb %dil, %r15b
jne 0x5ff9
movzbl -0x4(%r9), %r14d
cmpb %r8b, %r10b
movl %r8d, %edi
movl %r8d, %r15d
cmoval %r10d, %r15d
cmovbl %r10d, %edi
movzbl %r15b, %eax
cmpl %eax, %r14d
jae 0x6033
movzbl %dil, %eax
cmpl %eax, %r14d
jb 0x6036
addl %r10d, %r8d
subl %r14d, %r8d
movl %r8d, %r15d
jmp 0x6036
leal (%r10,%r8), %r15d
incl %r15d
shrl %r15d
jmp 0x6036
movl %edi, %r15d
movb (%r13,%rsi,4), %al
subb %r15b, %al
leaq 0x4(%r9), %rdi
testq %r9, %r9
cmovneq %rdi, %r9
movb %al, (%rbx,%rsi)
incq %rsi
leal (%rsi,%rcx), %eax
cmpl 0x7c(%rsp), %eax
jl 0x5fb2
movq 0x150(%rsp), %r8
addl %esi, %r8d
movq 0x130(%rsp), %r13
movl 0x2c(%rsp), %r14d
incl %ebp
addl $0x4, %r12d
cmpl %r14d, %ebp
jl 0x5f4b
movl 0x4(%rsp), %r10d
movq 0x48(%rsp), %r12
movl 0x74(%rsp), %ebp
movq 0x60(%rsp), %rdi
incq %rdi
movslq %r10d, %rsi
incq 0xa8(%rsp)
movq %rdi, 0x60(%rsp)
cmpq %rsi, %rdi
jl 0x5ef0
xorl %r15d, %r15d
movq 0x20(%rsp), %rax
cmpl %eax, 0x58(%rsp)
jle 0x619a
xorl %r15d, %r15d
movl %eax, %r8d
movl %r8d, %eax
notl %eax
addl %r14d, %eax
movl %r8d, %esi
subl 0x20(%rsp), %esi
testb $0x1, 0x28(%rsp)
cmovnel %eax, %esi
movl 0xc(%rsp), %edi
imull %edi, %esi
movl %r8d, %eax
xorl 0x78(%rsp), %eax
testb $0x1, %al
je 0x6146
testl %edi, %edi
jle 0x618e
movslq %esi, %rsi
movslq %r15d, %r15
movq 0x120(%rsp), %rdi
leaq -0x1(%rdi), %r9
testl %r10d, %r10d
jle 0x6138
xorl %ebx, %ebx
movq 0x80(%rsp,%rbx,8), %rax
leaq (%rax,%r9), %r10
movb (%rsi,%r10), %r10b
addq %r15, %rax
movb %r10b, (%rdx,%rax)
incq %rbx
movslq 0x4(%rsp), %r10
cmpq %r10, %rbx
jl 0x6114
incq %r15
cmpq $0x1, %rdi
movq %r9, %rdi
jg 0x6109
jmp 0x618e
testl %edi, %edi
jle 0x618e
movslq %esi, %rsi
movslq %r15d, %r15
xorl %edi, %edi
testl %r10d, %r10d
jle 0x617e
xorl %r9d, %r9d
movq 0x80(%rsp,%r9,8), %rax
leaq (%rax,%rdi), %r10
movb (%rsi,%r10), %r10b
addq %r15, %rax
movb %r10b, (%rdx,%rax)
incq %r9
movslq 0x4(%rsp), %r10
cmpq %r10, %r9
jl 0x615a
incq %r15
incq %rdi
cmpq 0x138(%rsp), %rdi
jl 0x6152
incl %r8d
cmpl %r14d, %r8d
jl 0x60ca
movl $0x80, %edx
testb $0x1, %r11b
movl $0x0, %r11d
jne 0x5ece
movl $0x40, %edx
movb $0x1, %bl
movl 0xc(%rsp), %r11d
movl $0x0, 0x2198(%rsp)
xorl %eax, %eax
cmpl $0x3, 0x4(%rsp)
jl 0x6204
movq 0x110(%rsp), %rax
leaq (%rax,%rdx), %rdi
movq 0x108(%rsp), %rax
leaq (%rax,%rdx), %rsi
addq 0x100(%rsp), %rdx
movl %r15d, %ecx
leaq 0x2198(%rsp), %r8
callq 0x59b0
movl 0xc(%rsp), %r11d
movl 0x2198(%rsp), %esi
testb $0x1, %bl
je 0x6222
movl $0x80, %edx
xorl %ebx, %ebx
movq %rax, 0x38(%rsp)
movl %esi, 0x70(%rsp)
jmp 0x61bb
movl 0x70(%rsp), %edi
cmpl %esi, %edi
setge %cl
movq 0x38(%rsp), %rdx
cmovgel %eax, %edx
movq %rdx, 0x38(%rsp)
movq 0x20(%rsp), %r8
cmpl %r8d, 0x58(%rsp)
jle 0x62af
xorl %eax, %eax
cmpl %esi, %edi
setge %al
shll $0x6, %eax
movslq 0x8(%rsp), %rdx
xorl %r15d, %r15d
movl %r8d, %esi
testl %r11d, %r11d
jle 0x62a6
movslq %r15d, %r15
xorl %edi, %edi
movl 0x4(%rsp), %r8d
testl %r8d, %r8d
jle 0x629c
xorl %r9d, %r9d
movq 0x80(%rsp,%r9,8), %r8
addq %r15, %r8
movb 0x40(%rax,%r8), %r8b
movq 0xb0(%rsp,%r9,8), %r10
addq %r15, %r10
movb %r8b, (%rdx,%r10)
incq %r9
movslq 0x4(%rsp), %r8
cmpq %r8, %r9
jl 0x6270
incq %r15
incl %edi
cmpl %r11d, %edi
jl 0x6268
incl %esi
cmpl %r14d, %esi
jl 0x6259
jmp 0x62b7
movslq 0x8(%rsp), %rdx
xorl %r15d, %r15d
xorl %ebx, %ebx
movb %cl, %bl
movq 0xe0(%rsp), %rax
leaq (%rax,%rdx), %rdi
movq 0xd8(%rsp), %rax
leaq (%rax,%rdx), %rsi
addq 0xd0(%rsp), %rdx
movl %r15d, %ecx
movq 0x38(%rsp), %r14
movl %r14d, %r8d
callq 0x4efb
leal (%rbx,%r14,2), %eax
movq 0x10(%rsp), %rcx
movb %al, (%r12,%rcx)
incq %rcx
movq %rcx, 0x10(%rsp)
movl 0x8(%rsp), %ebx
addl %r15d, %ebx
movl 0x28(%rsp), %edi
incl %edi
movl (%r13), %r8d
movl 0x6c(%rsp), %edx
addl $0x8, %edx
movl 0x68(%rsp), %esi
addl $-0x8, %esi
movq 0xf8(%rsp), %rax
addq $0x20, %rax
movq 0xf0(%rsp), %rcx
cmpl %ecx, %r8d
jg 0x5e2a
movl 0x4(%rsp), %r14d
jmp 0x6345
xorl %ebx, %ebx
testl %r14d, %r14d
jle 0x63da
movl %ebx, %r15d
xorl %ebx, %ebx
movq 0xb0(%rsp,%rbx,8), %rsi
leaq 0x160(%rsp), %rdi
movl %r15d, %edx
callq 0x4cb2
movq 0x168(%rsp), %rax
movslq 0x160(%rsp), %rcx
leaq (%rcx,%rax,8), %rax
testl $0xc0000000, %eax       # imm = 0xC0000000
jne 0x65ae
movq 0x30(%rsp), %r14
cmpq %rax, %r14
cmovleq %rax, %r14
movl %eax, 0x2198(%rsp)
movl $0x4, %edx
movq 0xe8(%rsp), %rdi
leaq 0x2198(%rsp), %rsi
callq 0x21f0
leaq 0x160(%rsp), %rdi
callq 0x16e1c
movq %r14, 0x30(%rsp)
incq %rbx
movslq 0x4(%rsp), %r14
cmpq %r14, %rbx
jl 0x6353
movl 0x4(%r13), %ecx
movq 0x50(%rsp), %rax
addl $0x20, %eax
movq %rax, 0x50(%rsp)
cmpl %ecx, %ebp
jl 0x5de4
jmp 0x6407
movq $0x0, 0x10(%rsp)
movq $0x0, 0x30(%rsp)
leaq 0x2198(%rsp), %rsi
movq 0x30(%rsp), %rax
movl %eax, (%rsi)
movl $0x4, %edx
movq 0x40(%rsp), %rdi
callq 0x21f0
leaq 0x2198(%rsp), %rdi
callq 0x4574
xorl %eax, %eax
leaq 0x190(%rsp), %rdi
movq 0x10(%rsp), %r14
movzbl %al, %ecx
imull $0x1010101, %ecx, %ecx  # imm = 0x1010101
xorl %edx, %edx
movl %ecx, (%rdi)
movzbl %dl, %esi
imull $0x1010101, %esi, %esi  # imm = 0x1010101
movl %esi, 0x4(%rdi)
addq $0x8, %rdi
incq %rdx
cmpl $0x10, %edx
jne 0x644c
incl %eax
cmpl $0x20, %eax
jne 0x6441
leaq 0x2198(%rsp), %rdi
leaq 0x190(%rsp), %rsi
leaq 0x1190(%rsp), %rcx
leaq 0x188(%rsp), %r8
movl $0x1000, %edx           # imm = 0x1000
callq 0x481e
leal (%r14,%r14), %eax
movslq %eax, %rdi
callq 0x2040
movq %rax, %rbx
movslq %r14d, %rdx
leaq 0x2198(%rsp), %rdi
leaq 0x190(%rsp), %r14
movq %r12, %rsi
movq %rax, %rcx
movq %r14, %r8
callq 0x481e
movq (%r14), %r14
leaq 0x1190(%rsp), %rsi
movl %r14d, (%rsi)
movl $0x4, %edx
movq 0x40(%rsp), %r13
movq %r13, %rdi
callq 0x21f0
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x21f0
movq %rbx, %rdi
callq 0x21e0
movq 0x18(%rsp), %rsi
addq $0x18, %rsi
leaq 0x2198(%rsp), %rdi
callq 0x22a0
movq 0x2198(%rsp), %rsi
movl 0x21a0(%rsp), %edx
movq 0x40(%rsp), %rdi
callq 0x21f0
leaq 0x21a8(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x654d
movq 0x21a8(%rsp), %rsi
incq %rsi
callq 0x2190
leaq 0x160(%rsp), %rdi
callq 0x16e1c
xorl %ebx, %ebx
movq 0x80(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x656e
callq 0x21e0
movq 0xb0(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x6580
callq 0x21e0
incq %rbx
cmpq $0x4, %rbx
jne 0x655c
movq %r12, %rdi
callq 0x21e0
movq 0x18(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
addq $0x943c8, %rsp          # imm = 0x943C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x10, %edi
callq 0x20d0
movq %rax, %r14
leaq 0x1241d(%rip), %rsi     # 0x189df
movq %rax, %rdi
callq 0x20a0
movq 0x16a1f(%rip), %rsi     # 0x1cff0
movq 0x169f0(%rip), %rdx     # 0x1cfc8
movq %r14, %rdi
callq 0x22f0
jmp 0x6738
jmp 0x674a
movq %rax, %rbx
leaq 0x21a8(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x66ad
movq 0x21a8(%rsp), %rsi
incq %rsi
callq 0x2190
jmp 0x66ad
jmp 0x6619
movq %rax, %rbx
jmp 0x66ad
jmp 0x66cf
jmp 0x66b4
movq %rax, %rbx
movl $0x188, %esi            # imm = 0x188
movq %r14, %rdi
callq 0x2190
jmp 0x6640
movq %rax, %rbx
movq $0x0, 0x18(%rsp)
xorl %r12d, %r12d
jmp 0x66df
movq %rax, %rdi
callq 0x20b0
movq %rbx, %rdi
callq 0x21e0
movl $0x10, %edi
callq 0x20d0
movq %rax, %r14
leaq 0x12382(%rip), %rsi     # 0x189f7
movq %rax, %rdi
callq 0x20a0
movq 0x1696c(%rip), %rsi     # 0x1cff0
movq 0x1693d(%rip), %rdx     # 0x1cfc8
movq %r14, %rdi
callq 0x22f0
jmp 0x6738
movq %rax, %rbx
jmp 0x66a8
movq %rax, %rbx
movq %r14, %rdi
callq 0x2130
callq 0x22c0
movq 0x48(%rsp), %r12
jmp 0x66d2
movq %rax, %rbx
xorl %r12d, %r12d
jmp 0x66d2
jmp 0x66cf
movq %rax, %rbx
movq %r14, %rdi
callq 0x2130
jmp 0x66d2
jmp 0x66cf
jmp 0x66cf
movq %rax, %rbx
leaq 0x160(%rsp), %rdi
callq 0x16e1c
movq %rbx, %rdi
callq 0x20b0
xorl %ebx, %ebx
movq 0x80(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x66fb
callq 0x21e0
movq 0xb0(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x670d
callq 0x21e0
incq %rbx
cmpq $0x4, %rbx
jne 0x66e9
testq %r12, %r12
je 0x6723
movq %r12, %rdi
callq 0x21e0
movq 0x18(%rsp), %rdi
testq %rdi, %rdi
je 0x6733
movq (%rdi), %rax
callq *0x8(%rax)
callq 0x2240
jmp 0x674a
movq %rax, %rbx
callq 0x22c0
movq %rbx, %rdi
callq 0x2300
movq %rax, %rdi
callq 0x16e88