// File: /workspace/github_cpp_makefile_star2_O3/Alcaro[P]bridges/arlib/image-png-decode.cpp
// Function: oimage::init_decode_png(arrayview<unsigned char>)
bool oimage::init_decode_png(arrayview<uint8_t> pngdata)
{
	struct pngchunk : public bytestream {
		uint32_t type;
		uint32_t len;
	};
	class pngreader : public bytestream {
	public:
		pngreader(arrayview<uint8_t> bytes) : bytestream(bytes) {}
		
		pngchunk chunk_raw()
		{
			pngchunk ret;
			ret.type = 0; // invalid value, looks like an unrecognized critical chunk and will propagate outwards
			
			if (remaining() < 12) return ret;
			ret.len = u32b();
			
			if (ret.len >= 0x80000000 || remaining()-8 < ret.len) return ret;
			
			uint32_t crc32_actual = crc32(peekbytes(4+ret.len));
			
			ret.type = u32b();
			ret.init(bytes(ret.len));
			
			uint32_t crc32_exp = u32b();
			if (crc32_actual != crc32_exp) ret.type = 0;
			
			return ret;
		}
		
		//Returns the next recognized or critical chunk. (Only tRNS is recognized.)
		pngchunk chunk()
		{
			while (true)
			{
				pngchunk ret = chunk_raw();
				if (ret.type == 0x74524E53) return ret; // tRNS
				if (!(ret.type&0x20000000)) return ret; // critical
			}
		}
	};
	
	
	pngreader reader(pngdata);
	
	if (reader.remaining() < 8 || !reader.signature("\x89PNG\r\n\x1A\n"))
	{
	fail: // putting this up here to avoid 99999 'jump to label foo crosses initialization of bar' errors
		this->storage = NULL; // forcibly deallocate - this can leave this->pixels as a dead pointer, but caller won't use that.
		return false;
	}
	
	pngchunk IHDR = reader.chunk_raw(); // no ancillary chunks allowed before IHDR
	if (IHDR.type != 0x49484452) goto fail; // IHDR must be the first chunk
	if (IHDR.len != 13) goto fail; // the IHDR chunk is always 13 bytes
	
	uint32_t width  = this->width  = IHDR.u32b();
	uint32_t height = this->height = IHDR.u32b();
	
	// Greyscale             - 0
	// Truecolour            - 2
	// Indexed-colour        - 3
	// Greyscale with alpha  - 4
	// Truecolour with alpha - 6
	
	uint8_t bits_per_sample = IHDR.u8();
	uint8_t color_type = IHDR.u8();
	uint8_t comp_meth = IHDR.u8();
	uint8_t filter_meth = IHDR.u8();
	uint8_t interlace_meth = IHDR.u8();
	
	if (width == 0 || height == 0 || width >= 0x80000000 || height >= 0x80000000) goto fail;
	if ((uint64_t)width * height >= 0x80000000 / sizeof(uint32_t)) goto fail; // ensure width*height doesn't overflow
	// huge images will still OOM, but at least they won't corrupt memory
	if (bits_per_sample >= 32 || color_type > 6 || comp_meth != 0 || filter_meth != 0 || interlace_meth > 1) goto fail;
	if (bits_per_sample > 8) goto fail; // bpp=16 is allowed by the png standard, but not by this program
	if (interlace_meth) goto fail; // TODO: implement this
	static const uint32_t bpp_allowed[7] = { 0x68808000, 0x00000000, 0x00808000, 0x68800000, 0x00808000, 0x00000000, 0x00808000 };
	if (!((bpp_allowed[color_type]<<bits_per_sample)&0x80000000)) goto fail; // clear bit - invalid bpp (this also rejects types 1 and 5)
	
	uint32_t palette[256];
	unsigned palettelen = 0;
	
	if (color_type == 3)
	{
		pngchunk PLTE = reader.chunk();
		if (PLTE.type != 0x504C5445) goto fail;
		
		if (PLTE.len == 0 || PLTE.len%3 || PLTE.len/3 > (1u<<bits_per_sample)) goto fail;
		palettelen = PLTE.len/3;
		for (unsigned i=0;i<palettelen;i++)
		{
			// this reads a byte it shouldn't, but it's either previous color or the chunk's type, so not UB
			palette[i] = 0xFF000000 | readu_be32(PLTE.bytes(3).ptr()-1);
		}
	}
	
	bool has_alpha = (color_type >= 4);
	bool has_bool_alpha = false;
	uint32_t transparent = 0; // if you see this value (after filtering), make it transparent
	                          // for rgb, this value is ARGB, A=0xFF
	
	pngchunk tRNS_IDAT = reader.chunk();
	if (tRNS_IDAT.type == 0x504C5445) // PLTE
	{
		if (color_type == 2 || color_type == 6) // it's allowed on those two types
			tRNS_IDAT = reader.chunk();
		//else fall through and let IEND handler whine
	}
	pngchunk IDAT;
	if (!has_alpha && tRNS_IDAT.type == 0x74524E53) // tRNS
	{
		pngchunk tRNS = tRNS_IDAT;
		has_alpha = true;
		
		if (color_type == 0)
		{
			if (tRNS.len != 2) goto fail;
			transparent = tRNS.u16b();
			if (transparent >= 1u<<bits_per_sample) goto fail;
			if (bits_per_sample == 8) transparent = 0xFF000000 + transparent*0x010101;
			has_bool_alpha = true;
		}
		if (color_type == 2)
		{
			if (tRNS.len != 6) goto fail;
			
			uint16_t r = tRNS.u16b();
			uint16_t g = tRNS.u16b();
			uint16_t b = tRNS.u16b();
			
			if ((r|g|b) >= 1<<bits_per_sample) goto fail;
			
			transparent = 0xFF000000 | r<<16 | g<<8 | b;
			has_bool_alpha = true;
		}
		if (color_type == 3)
		{
			if (tRNS.len == 0 || tRNS.len > palettelen) goto fail;
			
			has_bool_alpha = true;
			for (size_t i=0;i<tRNS.len;i++)
			{
				uint8_t newa = tRNS.u8();
				if (newa != 0x00 && newa != 0xFF) has_bool_alpha = false;
				palette[i] = (palette[i]&0x00FFFFFF) | (uint32_t)newa<<24; // extra cast because u8 << 24 is signed
			}
		}
		if (color_type == 4) goto fail;
		if (color_type == 6) goto fail;
		
		IDAT = reader.chunk();
	}
	else IDAT = tRNS_IDAT; // could be neither tRNS or IDAT, in which case the while loop won't enter, and the IEND checker will whine
	
	
	this->stride = sizeof(uint32_t) * width;
	
	int samples_per_px = (0x04021301 >> (color_type*4))&15;
	size_t bytes_per_line_raw = (bits_per_sample*samples_per_px*width + 7)/8;
	
	//+4 and +2 to let filters read outside the image, and to ensure there's enough
	// space to decode and convert the image to the desired output format
	//+7*u32 because the decoder overshoots on low bitdepths
	//unpacking (png -> uint32_t) needs one pixel of buffer, though compiler considerations say minimum one scanline
	//unfiltering needs another scanline of buffer, plus another one must exist in front
	//
	//however, there's another another issue - what scanline size?
	// output must be packed, raw is pngpack+1, unfiltering needs at least pngpack+4
	//the correct offsets are
	//scan_out = width * (3 or 4)
	//scan_packed = whatever+4
	//scan_filtered = whatever+1
	//start_out = 0
	//start_packed = end - height*scan_packed - scan_packed
	//start_filtered = end - height*scan_filtered
	//deinterleaving probably isn't doable in-place at all
	size_t nbytes = max(this->stride, bytes_per_line_raw+4) * (height+2) + sizeof(uint32_t)*7;
	this->storage = xmalloc(nbytes);
	
	this->pixels8 = (uint8_t*)this->storage;
	this->fmt = (has_alpha ? (has_bool_alpha ? ifmt_bargb8888 : ifmt_argb8888) : ifmt_xrgb8888);
	
	uint8_t* inflate_end = (uint8_t*)this->storage + nbytes;
	uint8_t* inflate_start = inflate_end - (bytes_per_line_raw+1)*height;
	
	inflator::zlibhead infl;
	infl.set_output_first(bytesw(inflate_start, inflate_end-inflate_start));
	inflator::ret_t infl_status = inflator::ret_more_input;
	
	while (IDAT.type == 0x49444154 && infl_status == inflator::ret_more_input)
	{
		infl.set_input(IDAT.bytes(IDAT.len), false);
		infl_status = infl.inflate();
		IDAT = reader.chunk_raw(); // all IDAT chunks must be consecutive
	}
	
	if (infl_status == inflator::ret_more_input)
	{
		infl.set_input(NULL, true);
		infl_status = infl.inflate();
	}
	if (infl_status != inflator::ret_done) goto fail;
	if (inflate_start+infl.output_in_last() != inflate_end) goto fail;
	
	pngchunk IEND = IDAT;
	if (IEND.type != 0x49454E44) IEND = reader.chunk(); // ancillary between IDAT and IEND is fine, just discard that
	if (IEND.type != 0x49454E44 || IEND.len != 0) goto fail;
	
	
	if (interlace_meth == 1)
	{
puts("unsupported: Adam7");
goto fail;
	}
	
//for(uint8_t*n=inflate_start;n<inflate_at;n++)printf("%.2X ",*n);
//puts("");
	
	size_t defilter_out_line = 4 + bytes_per_line_raw;
	uint8_t* defilter_start = inflate_end - height*defilter_out_line - defilter_out_line;
	
	if (inflate_start[0] >= 2)
		memset(defilter_start - defilter_out_line, 0, defilter_out_line); // y=-1 is all zeroes
	size_t filter_bpp = (bits_per_sample*samples_per_px + 7)/8;
	if (!image::png_defilter(defilter_start, defilter_out_line, inflate_start, filter_bpp, bytes_per_line_raw, height)) goto fail;
	
	defilter_start += 4; // skip the x=-1 = 0 padding
	
	if(0);
	else if (color_type == 0)
	{
		//treating gray as a palette makes things a fair bit simpler, especially with tRNS handling
		//doing it for bpp=8 means an 1KB table which is boring, but that one doesn't pack multiple pixels in a single byte,
		// so it's easy to put in the non-palette decoder (and there's no other sane way to handle gray+alpha)
		if (bits_per_sample == 1)
		{
			static const uint32_t gray_1bpp[] = { 0xFF000000, 0xFFFFFFFF };
			if (has_alpha) transparent = gray_1bpp[transparent];
			png_unpack_plte<1>(defilter_start, defilter_out_line, gray_1bpp, 2);
		}
		else if (bits_per_sample == 2)
		{
			static const uint32_t gray_2bpp[] = { 0xFF000000, 0xFF555555, 0xFFAAAAAA, 0xFFFFFFFF };
			if (has_alpha) transparent = gray_2bpp[transparent];
			png_unpack_plte<2>(defilter_start, defilter_out_line, gray_2bpp, 4);
		}
		else if (bits_per_sample == 4)
		{
			static const uint32_t gray_4bpp[] = { 0xFF000000, 0xFF111111, 0xFF222222, 0xFF333333,
			                                      0xFF444444, 0xFF555555, 0xFF666666, 0xFF777777,
			                                      0xFF888888, 0xFF999999, 0xFFAAAAAA, 0xFFBBBBBB,
			                                      0xFFCCCCCC, 0xFFDDDDDD, 0xFFEEEEEE, 0xFFFFFFFF };
			if (has_alpha) transparent = gray_4bpp[transparent];
			png_unpack_plte<4>(defilter_start, defilter_out_line, gray_4bpp, 16);
		}
		else /* bits_per_sample == 8 */ png_unpack_rgb<0>(defilter_start, defilter_out_line);
	}
	
	else if (color_type == 2 /* bits_per_sample == 8 */) png_unpack_rgb<2>(defilter_start, defilter_out_line);
	else if (color_type == 3)
	{
		if      (bits_per_sample == 1) { if (!png_unpack_plte<1>(defilter_start, defilter_out_line, palette, palettelen)) goto fail; }
		else if (bits_per_sample == 2) { if (!png_unpack_plte<2>(defilter_start, defilter_out_line, palette, palettelen)) goto fail; }
		else if (bits_per_sample == 4) { if (!png_unpack_plte<4>(defilter_start, defilter_out_line, palette, palettelen)) goto fail; }
		else /* bits_per_sample = 8 */ { if (!png_unpack_plte<8>(defilter_start, defilter_out_line, palette, palettelen)) goto fail; }
	}
	else if (color_type == 4 /* bits_per_sample == 8 */) png_unpack_rgb<4>(defilter_start, defilter_out_line);
	else  /* color_type == 6 && bits_per_sample == 8 */  png_unpack_rgb<6>(defilter_start, defilter_out_line);
	
	if (transparent >= 0xFF000000)
	{
		uint32_t* pixels = (uint32_t*)(uint8_t*)this->storage;
		for (size_t i=0;i<width*height;i++)
		{
			if (pixels[i] == transparent) pixels[i] &= 0x00FFFFFF;
		}
	}
	
	return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x17b8, %rsp           # imm = 0x17B8
movq %rdi, %rbx
movq %rsi, 0x60(%rsp)
leaq (%rsi,%rdx), %rax
movq %rax, 0x70(%rsp)
cmpq $0x8, %rdx
jb 0xae44
movabsq $0xa1a0a0d474e5089, %rax # imm = 0xA1A0A0D474E5089
cmpq %rax, (%rsi)
jne 0xae44
addq $0x8, %rsi
leaq 0x60(%rsp), %rax
movq %rsi, 0x8(%rax)
leaq 0xc0(%rsp), %r14
movq %r14, %rdi
movq %rax, %rsi
callq 0xb6ee
cmpl $0x49484452, 0x18(%r14) # imm = 0x49484452
jne 0xae44
cmpl $0xd, 0xdc(%rsp)
jne 0xae44
movq 0xc8(%rsp), %rax
movl (%rax), %ebp
bswapl %ebp
movl %ebp, (%rbx)
movl 0x4(%rax), %r8d
movl %r8d, %r12d
bswapl %r12d
movl %r12d, 0x4(%rbx)
movzbl 0x8(%rax), %r13d
movb 0x9(%rax), %dil
movb 0xa(%rax), %cl
leaq 0xc(%rax), %rdx
movq %rdx, 0xc8(%rsp)
testl %ebp, %ebp
setle %dl
testl %r12d, %r12d
setle %sil
orb %dl, %sil
jne 0xae44
movl %ebp, %edx
movl %r12d, %esi
imulq %rsi, %rdx
cmpq $0x1fffffff, %rdx       # imm = 0x1FFFFFFF
ja 0xae44
movb 0xc(%rax), %dl
testb %dl, %dl
jne 0xae44
cmpb $0x8, %r13b
ja 0xae44
cmpb $0x1f, %r13b
ja 0xae44
cmpb $0x6, %dil
ja 0xae44
orb 0xb(%rax), %cl
jne 0xae44
cmpb $0x1, %dl
ja 0xae44
movzbl %dil, %edx
leaq 0x24a98(%rip), %rax     # 0x2f8d0
movl (%rax,%rdx,4), %eax
movl %r13d, %ecx
shll %cl, %eax
testl %eax, %eax
js 0xae69
movq 0x18(%rbx), %rdi
callq 0x3430
movq $0x0, 0x18(%rbx)
xorl %eax, %eax
addq $0x17b8, %rsp           # imm = 0x17B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %r8d, 0x38(%rsp)
movq %rdx, 0x58(%rsp)
movq %rsi, 0x48(%rsp)
xorl %r8d, %r8d
movq %rdi, 0x20(%rsp)
cmpb $0x3, %dil
jne 0xaf33
leaq 0xe0(%rsp), %r14
leaq 0x60(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb6ee
movl 0xf8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xaeba
movl %eax, %ecx
andl $0x20000000, %ecx       # imm = 0x20000000
jne 0xae97
cmpl $0x504c5445, %eax       # imm = 0x504C5445
jne 0xae44
movl 0xfc(%rsp), %eax
movl $0x1, %edx
movl %r13d, %ecx
shll %cl, %edx
testq %rax, %rax
je 0xae44
movl $0xaaaaaaab, %r8d       # imm = 0xAAAAAAAB
imulq %rax, %r8
shrq $0x21, %r8
leal (%r8,%r8,2), %ecx
movl %eax, %esi
subl %ecx, %esi
jne 0xae44
cmpl %edx, %r8d
ja 0xae44
cmpl $0x3, %eax
jb 0xaf33
movq 0xe8(%rsp), %rax
movl %r8d, %ecx
decq %rax
xorl %edx, %edx
movl $0xff, %esi
movl (%rax), %edi
orl %esi, %edi
bswapl %edi
movl %edi, 0x13b0(%rsp,%rdx,4)
incq %rdx
addq $0x3, %rax
cmpq %rdx, %rcx
jne 0xaf1a
movq %r8, 0x30(%rsp)
leaq 0x80(%rsp), %r14
leaq 0x60(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb6ee
movl 0x98(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xaf68
movl %eax, %ecx
andl $0x20000000, %ecx       # imm = 0x20000000
jne 0xaf45
movq 0x20(%rsp), %rsi
cmpb $0x4, %sil
setae 0xf(%rsp)
cmpl $0x504c5445, %eax       # imm = 0x504C5445
setne %cl
movl %esi, %edx
andb $0x3, %dl
cmpb $0x2, %dl
setne %dl
orb %cl, %dl
jne 0xafe6
leaq 0xe0(%rsp), %r14
leaq 0x60(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb6ee
movl 0xf8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xafba
andl $0x20000000, %eax       # imm = 0x20000000
jne 0xaf9a
movups 0xe0(%rsp), %xmm0
movups 0xf0(%rsp), %xmm1
movaps %xmm1, 0x90(%rsp)
movaps %xmm0, 0x80(%rsp)
movl 0x98(%rsp), %eax
movq 0x20(%rsp), %rsi
movl %r13d, 0x10(%rsp)
movq 0x88(%rsp), %r13
movq 0x98(%rsp), %r15
cmpb $0x3, %sil
ja 0xb063
cmpl $0x74524e53, %eax       # imm = 0x74524E53
jne 0xb063
cmpb $0x2, %sil
je 0xb3e2
movq 0x58(%rsp), %r8
testl %r8d, %r8d
jne 0xb43d
shrq $0x20, %r15
cmpl $0x2, %r15d
jne 0xae44
movzwl (%r13), %eax
rolw $0x8, %ax
movzwl %ax, %eax
movl %eax, %edx
movl 0x10(%rsp), %ecx
shrl %cl, %edx
testl %edx, %edx
jne 0xae44
imull $0x10101, %eax, %edi    # imm = 0x10101
addl $0xff000000, %edi       # imm = 0xFF000000
cmpl $0x8, 0x10(%rsp)
cmovnel %eax, %edi
jmp 0xb438
movl $0x5, 0x28(%rsp)
movl $0x0, 0x14(%rsp)
leal (,%rbp,4), %eax
leal (,%rsi,4), %ecx
movl $0x4021301, %edx        # imm = 0x4021301
shrl %cl, %edx
movl %eax, 0xc(%rbx)
andl $0x7, %edx
imull 0x10(%rsp), %edx
movl %edx, 0x54(%rsp)
movl %edx, %r14d
imull %ebp, %r14d
addl $0x7, %r14d
shrl $0x3, %r14d
leaq 0x4(%r14), %rcx
cmpl %eax, %ecx
movq %rcx, 0x18(%rsp)
cmoval %ecx, %eax
leal 0x2(%r12), %ecx
imull %eax, %ecx
movq %rcx, 0x40(%rsp)
leaq 0x1c(%rcx), %rdi
callq 0x1597c
movq %rax, 0x78(%rsp)
movq 0x18(%rbx), %rdi
callq 0x3430
movq 0x78(%rsp), %rax
movq %rax, 0x18(%rbx)
movq %rax, 0x10(%rbx)
movq %rax, %rcx
cmpb $0x0, 0xf(%rsp)
movl $0x6, %eax
cmovnel 0x28(%rsp), %eax
movl %eax, 0x8(%rbx)
movq 0x40(%rsp), %rax
addq %rcx, %rax
addq $0x1c, %rax
movq %r14, 0x40(%rsp)
notq %r14
imulq 0x48(%rsp), %r14
addq %rax, %r14
movl $0x1, 0xe0(%rsp)
movb $0x0, 0xea(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0xec(%rsp)
movups %xmm0, 0xf8(%rsp)
movb $-0x2, 0xe8(%rsp)
movq %rax, 0x28(%rsp)
subq %r14, %rax
cmpl $0x0, 0x38(%rsp)
leaq 0x27313(%rip), %rcx     # 0x3246c
movq %r14, 0x38(%rsp)
cmovneq %r14, %rcx
movq $0x0, 0x108(%rsp)
movq %rcx, 0x110(%rsp)
movq %rcx, 0x118(%rsp)
addq %rax, %rcx
movq %rcx, 0x120(%rsp)
cmpl $0x49444154, %r15d      # imm = 0x49444154
jne 0xb22b
movq 0xf8(%rsp), %rax
cmpq 0x100(%rsp), %rax
jne 0xb6e9
cmpb $0x1, 0xea(%rsp)
je 0xb6e9
shrq $0x20, %r15
movq %r13, 0xf8(%rsp)
addq %r13, %r15
movq %r15, 0x100(%rsp)
movb $0x0, 0xea(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x1d2de
movl %eax, %r14d
leaq 0xa0(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0xb6ee
movq 0xb8(%rsp), %r15
cmpl $0x49444154, %r15d      # imm = 0x49444154
jne 0xb21e
movq 0xa8(%rsp), %r13
cmpl $0x2, %r14d
je 0xb196
cmpl $0x2, %r14d
movq 0x28(%rsp), %r13
je 0xb230
jmp 0xb276
movq 0x28(%rsp), %r13
movq 0xf8(%rsp), %rax
cmpq 0x100(%rsp), %rax
jne 0xb6e9
cmpb $0x1, 0xea(%rsp)
je 0xb6e9
leaq 0xf8(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movb $0x1, -0xe(%rax)
leaq 0xe0(%rsp), %rdi
callq 0x1d2de
movl %eax, %r14d
testl %r14d, %r14d
jne 0xae44
movq 0x118(%rsp), %rax
subq 0x110(%rsp), %rax
addq 0x38(%rsp), %rax
cmpq %r13, %rax
jne 0xae44
cmpl $0x49454e44, %r15d      # imm = 0x49454E44
je 0xb2db
leaq 0xa0(%rsp), %r14
leaq 0x60(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb6ee
movl 0xb8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xb2d3
andl $0x20000000, %eax       # imm = 0x20000000
jne 0xb2b3
movq 0xb8(%rsp), %r15
cmpq $0x49454e44, %r15       # imm = 0x49454E44
jne 0xae44
movq 0x18(%rsp), %r15
movq %r15, %rax
movq 0x48(%rsp), %r14
imulq %r14, %rax
subq %rax, %r13
movq $-0x4, %rdi
subq 0x40(%rsp), %rdi
addq %rdi, %r13
movq 0x38(%rsp), %rax
cmpb $0x2, (%rax)
jb 0xb322
addq %r13, %rdi
xorl %esi, %esi
movq %r15, %rdx
callq 0x3170
movl 0x54(%rsp), %ecx
addl $0x7, %ecx
shrl $0x3, %ecx
movq %r13, %rdi
movq %r15, %rsi
movq 0x38(%rsp), %rdx
movq 0x40(%rsp), %r8
movq %r14, %r9
callq 0xb786
testb %al, %al
je 0xae44
addq $0x4, %r13
movq %r13, %rsi
cmpb $0x2, 0x20(%rsp)
je 0xb4f2
cmpl $0x0, 0x58(%rsp)
jne 0xb53e
cmpl $0x1, 0x10(%rsp)
je 0xb58a
cmpl $0x2, 0x10(%rsp)
je 0xb673
cmpl $0x4, 0x10(%rsp)
je 0xb63b
movl 0x4(%rbx), %eax
testl %eax, %eax
je 0xb5cc
movl (%rbx), %ecx
movq 0x10(%rbx), %rdx
leaq (,%rcx,4), %r11
xorl %edi, %edi
movq 0x18(%rsp), %r10
testq %rcx, %rcx
je 0xb3d1
xorl %r8d, %r8d
movzbl (%rsi,%r8), %r9d
imull $0x10101, %r9d, %r9d    # imm = 0x10101
orl $0xff000000, %r9d       # imm = 0xFF000000
movl %r9d, (%rdx,%r8,4)
incq %r8
cmpq %r8, %rcx
jne 0xb3b2
addq %r10, %rsi
incl %edi
addq %r11, %rdx
cmpl %eax, %edi
jne 0xb3aa
jmp 0xb5cc
shrq $0x20, %r15
cmpl $0x6, %r15d
jne 0xae44
movzwl (%r13), %eax
movzwl 0x2(%r13), %ecx
rolw $0x8, %ax
rolw $0x8, %cx
movzwl 0x4(%r13), %edx
rolw $0x8, %dx
movzwl %ax, %eax
movzwl %cx, %edi
movl %edi, %esi
orl %eax, %esi
movzwl %dx, %edx
orl %edx, %esi
movl 0x10(%rsp), %ecx
shrl %cl, %esi
testl %esi, %esi
jne 0xae44
shll $0x10, %eax
shll $0x8, %edi
orl %eax, %edi
orl %edx, %edi
orl $0xff000000, %edi       # imm = 0xFF000000
movb $0x1, %r14b
jmp 0xb494
xorl %edi, %edi
movl $0x0, %r14d
cmpb $0x3, %sil
jne 0xb485
shrq $0x20, %r15
je 0xae44
cmpl %r15d, 0x30(%rsp)
jb 0xae44
movb $0x1, %r14b
xorl %eax, %eax
movb (%r13,%rax), %cl
leal 0x1(%rcx), %edx
cmpb $0x2, %dl
setb %dl
andb %dl, %r14b
movb %cl, 0x13b3(%rsp,%rax,4)
incq %rax
cmpq %rax, %r15
jne 0xb465
movl %r8d, %eax
orl $0x2, %eax
cmpl $0x6, %eax
je 0xae44
movl %edi, 0x14(%rsp)
leaq 0xe0(%rsp), %r13
leaq 0x60(%rsp), %r15
movq %r13, %rdi
movq %r15, %rsi
callq 0xb6ee
movl 0xf8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xb4c5
andl $0x20000000, %eax       # imm = 0x20000000
jne 0xb4a5
movq 0xe8(%rsp), %r13
movq 0xf8(%rsp), %r15
movzbl %r14b, %eax
leal (%rax,%rax,2), %eax
addl $0x5, %eax
movl %eax, 0x28(%rsp)
movb $0x1, 0xf(%rsp)
movq 0x20(%rsp), %rsi
jmp 0xb073
movl 0x4(%rbx), %r13d
testl %r13d, %r13d
je 0xb5cc
movl (%rbx), %eax
movq 0x10(%rbx), %r15
movq %rax, 0x20(%rsp)
leaq (,%rax,4), %rax
movq %rax, 0x48(%rsp)
movq %rsi, %r14
movq %r15, %rdi
movq %r14, %rsi
movq 0x20(%rsp), %rdx
callq 0xd132
addq 0x18(%rsp), %r14
addq 0x48(%rsp), %r15
decl %r13d
jne 0xb51a
jmp 0xb5cc
cmpb $0x3, 0x20(%rsp)
jne 0xb574
cmpl $0x1, 0x10(%rsp)
jne 0xb606
leaq 0x13b0(%rsp), %rcx
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
movq 0x30(%rsp), %r8
callq 0xbb88
testb %al, %al
je 0xae44
jmp 0xb5cc
cmpb $0x4, 0x20(%rsp)
jne 0xb5bf
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
callq 0xbcfa
jmp 0xb5cc
cmpb $0x0, 0xf(%rsp)
je 0xb5a3
leaq 0x24354(%rip), %rax     # 0x2f8ec
movl 0x14(%rsp), %ecx
movl (%rax,%rcx,4), %eax
movl %eax, 0x14(%rsp)
leaq 0x24342(%rip), %rcx     # 0x2f8ec
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
movl $0x2, %r8d
callq 0xbb88
jmp 0xb5cc
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
callq 0xbd50
movl 0x14(%rsp), %esi
cmpl $0xff000000, %esi       # imm = 0xFF000000
jb 0xb5ff
imull %ebp, %r12d
testl %r12d, %r12d
je 0xb5ff
movq 0x18(%rbx), %rax
movl %esi, %ecx
andl $0xffffff, %ecx         # imm = 0xFFFFFF
xorl %edx, %edx
cmpl %esi, (%rax,%rdx,4)
jne 0xb5f7
movl %ecx, (%rax,%rdx,4)
incq %rdx
cmpq %rdx, %r12
jne 0xb5ef
movb $0x1, %al
jmp 0xae57
cmpl $0x2, 0x10(%rsp)
je 0xb6ab
cmpl $0x4, 0x10(%rsp)
jne 0xb6ca
leaq 0x13b0(%rsp), %rcx
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
movq 0x30(%rsp), %r8
callq 0x3cae
jmp 0xb56a
cmpb $0x0, 0xf(%rsp)
je 0xb654
leaq 0x242c7(%rip), %rax     # 0x2f910
movl 0x14(%rsp), %ecx
movl (%rax,%rcx,4), %eax
movl %eax, 0x14(%rsp)
leaq 0x242b5(%rip), %rcx     # 0x2f910
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
movl $0x10, %r8d
callq 0x3cae
jmp 0xb5cc
cmpb $0x0, 0xf(%rsp)
je 0xb68c
leaq 0x2427f(%rip), %rax     # 0x2f900
movl 0x14(%rsp), %ecx
movl (%rax,%rcx,4), %eax
movl %eax, 0x14(%rsp)
leaq 0x2426d(%rip), %rcx     # 0x2f900
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
movl $0x4, %r8d
callq 0x3bc6
jmp 0xb5cc
leaq 0x13b0(%rsp), %rcx
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
movq 0x30(%rsp), %r8
callq 0x3bc6
jmp 0xb56a
leaq 0x13b0(%rsp), %rcx
movq %rbx, %rdi
movq 0x18(%rsp), %rdx
movq 0x30(%rsp), %r8
callq 0x3d60
jmp 0xb56a
callq 0x3180