// File: /workspace/github_cpp_makefile_star2_O1/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 $0x17a8, %rsp           # imm = 0x17A8
movq %rdi, %rbx
movq %rsi, 0x50(%rsp)
movq %rsi, 0x58(%rsp)
leaq (%rsi,%rdx), %rax
movq %rax, 0x60(%rsp)
cmpq $0x8, %rdx
jb 0xb272
movabsq $0xa1a0a0d474e5089, %rax # imm = 0xA1A0A0D474E5089
cmpq %rax, (%rsi)
jne 0xb272
addq $0x8, %rsi
leaq 0x50(%rsp), %rax
movq %rsi, 0x8(%rax)
leaq 0x70(%rsp), %r14
movq %r14, %rdi
movq %rax, %rsi
callq 0xb380
cmpl $0x49484452, 0x18(%r14) # imm = 0x49484452
jne 0xb272
cmpl $0xd, 0x8c(%rsp)
jne 0xb272
movq 0x78(%rsp), %r8
leaq 0x4(%r8), %rax
movq %rax, 0x78(%rsp)
movl (%r8), %r13d
bswapl %r13d
movl %r13d, (%rbx)
leaq 0x8(%r8), %rax
movq %rax, 0x78(%rsp)
movl 0x4(%r8), %r12d
movl %r12d, %ebp
bswapl %ebp
movl %ebp, 0x4(%rbx)
leaq 0x9(%r8), %rax
movq %rax, 0x78(%rsp)
movzbl 0x8(%r8), %ecx
leaq 0xa(%r8), %rax
movq %rax, 0x78(%rsp)
movzbl 0x9(%r8), %r9d
leaq 0xb(%r8), %rax
movq %rax, 0x78(%rsp)
movb 0xa(%r8), %al
leaq 0xc(%r8), %rdx
movq %rdx, 0x78(%rsp)
movb 0xb(%r8), %dl
leaq 0xd(%r8), %rsi
movq %rsi, 0x78(%rsp)
testl %r13d, %r13d
setle %sil
testl %ebp, %ebp
setle %dil
orb %sil, %dil
jne 0xb272
movl %r13d, %esi
movl %ebp, %r10d
imulq %r10, %rsi
cmpq $0x1fffffff, %rsi       # imm = 0x1FFFFFFF
ja 0xb272
movb 0xc(%r8), %sil
testb %sil, %sil
jne 0xb272
cmpb $0x8, %cl
ja 0xb272
cmpb $0x1f, %cl
ja 0xb272
cmpb $0x6, %r9b
ja 0xb272
orb %al, %dl
jne 0xb272
cmpb $0x1, %sil
ja 0xb272
leaq 0x24f2d(%rip), %rax     # 0x2f8e0
movl (%rax,%r9,4), %eax
shll %cl, %eax
testl %eax, %eax
jns 0xb272
xorl %r8d, %r8d
cmpl $0x3, %r9d
movl %ecx, 0x18(%rsp)
movq %r9, 0x28(%rsp)
movq %r10, 0x68(%rsp)
jne 0xaab3
leaq 0xd0(%rsp), %r14
leaq 0x50(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb380
movl 0xe8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xaa0c
movl %eax, %ecx
andl $0x20000000, %ecx       # imm = 0x20000000
jne 0xa9e9
movl $0x2, %edi
xorl %r8d, %r8d
cmpl $0x504c5445, %eax       # imm = 0x504C5445
jne 0xaaa9
movl $0x1, %esi
movl 0x18(%rsp), %ecx
shll %cl, %esi
movl 0xec(%rsp), %edx
xorl %r8d, %r8d
testq %rdx, %rdx
je 0xaaa9
movl $0xaaaaaaab, %ecx       # imm = 0xAAAAAAAB
imulq %rdx, %rcx
shrq $0x21, %rcx
leal (%rcx,%rcx,2), %eax
movl %edx, %edi
subl %eax, %edi
jne 0xac9f
movl $0x0, %eax
cmpl %esi, %ecx
movl $0x2, %edi
ja 0xaaab
xorl %edi, %edi
movb $0x1, %al
cmpl $0x3, %edx
jb 0xaaa4
movq 0xd8(%rsp), %rdx
movl %ecx, %esi
xorl %edi, %edi
movl $0xff, %r8d
movl -0x1(%rdx), %r9d
orl %r8d, %r9d
addq $0x3, %rdx
bswapl %r9d
movl %r9d, 0x13a0(%rsp,%rdi,4)
incq %rdi
cmpq %rdi, %rsi
jne 0xaa7c
movq %rdx, 0xd8(%rsp)
xorl %edi, %edi
movl %ecx, %r8d
jmp 0xaaab
xorl %eax, %eax
testb %al, %al
je 0xb26b
movl %r8d, 0x24(%rsp)
leaq 0x90(%rsp), %r14
leaq 0x50(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb380
movl 0xa8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xaae8
movl %eax, %ecx
andl $0x20000000, %ecx       # imm = 0x20000000
jne 0xaac5
movq 0x28(%rsp), %r11
cmpb $0x4, %r11b
setae 0x3(%rsp)
cmpl $0x504c5445, %eax       # imm = 0x504C5445
setne %al
movl %r11d, %ecx
andb $0x3, %cl
cmpb $0x2, %cl
setne %cl
orb %al, %cl
jne 0xab60
leaq 0xd0(%rsp), %r14
leaq 0x50(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb380
movl 0xe8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xab3b
andl $0x20000000, %eax       # imm = 0x20000000
jne 0xab1b
movups 0xd0(%rsp), %xmm0
movups 0xe0(%rsp), %xmm1
movaps %xmm1, 0xa0(%rsp)
movaps %xmm0, 0x90(%rsp)
movq 0x28(%rsp), %r11
movq 0x98(%rsp), %rax
movq 0xa8(%rsp), %r15
cmpb $0x3, %r11b
ja 0xac42
cmpl $0x74524e53, 0xa8(%rsp) # imm = 0x74524E53
movl 0x18(%rsp), %r9d
jne 0xac25
xorl %r10d, %r10d
testl %r11d, %r11d
je 0xac64
xorl %r8d, %r8d
cmpl $0x2, %r11d
jne 0xacd5
movq %r15, %rcx
shrq $0x20, %rcx
cmpl $0x6, %ecx
jne 0xad25
movl %r8d, 0x8(%rsp)
movzwl (%rax), %ecx
rolw $0x8, %cx
movzwl 0x2(%rax), %edx
rolw $0x8, %dx
movzwl 0x4(%rax), %r8d
rolw $0x8, %r8w
movzwl %cx, %edi
movzwl %dx, %esi
movl %esi, %edx
orl %edi, %edx
movzwl %r8w, %r8d
orl %r8d, %edx
movl %r9d, %ecx
shrl %cl, %edx
movl $0x2, %ecx
testl %edx, %edx
jne 0xac13
shll $0x10, %edi
shll $0x8, %esi
orl %edi, %esi
orl %r8d, %esi
orl $0xff000000, %esi       # imm = 0xFF000000
xorl %ecx, %ecx
movb $0x1, %dil
movl %edi, 0x8(%rsp)
movl %esi, %r10d
testl %edx, %edx
je 0xaccc
xorl %r14d, %r14d
movl %ecx, %edi
jmp 0xad87
movl %r12d, 0x34(%rsp)
movl $0x0, 0x4(%rsp)
movq %rax, %r14
movl $0x0, 0x8(%rsp)
jmp 0xada8
movl %r12d, 0x34(%rsp)
movl $0x0, 0x4(%rsp)
movq %rax, %r14
movl $0x0, 0x8(%rsp)
movl 0x18(%rsp), %r9d
jmp 0xada8
movq %r15, %rcx
shrq $0x20, %rcx
movl $0x2, %edi
cmpl $0x2, %ecx
jne 0xac91
movzwl (%rax), %ecx
rolw $0x8, %cx
movzwl %cx, %r10d
movl %r10d, %edx
movl %r9d, %ecx
shrl %cl, %edx
testl %edx, %edx
je 0xacab
xorl %r14d, %r14d
jmp 0xac97
xorl %r14d, %r14d
xorl %r10d, %r10d
xorl %r8d, %r8d
jmp 0xad8c
xorl %eax, %eax
movl $0x2, %edi
jmp 0xaaab
addq $0x2, %rax
imull $0x10101, %r10d, %ecx   # imm = 0x10101
addl $0xff000000, %ecx       # imm = 0xFF000000
cmpl $0x8, %r9d
cmovel %ecx, %r10d
movb $0x1, %r8b
jmp 0xab9f
addq $0x6, %rax
movl 0x8(%rsp), %r8d
cmpl $0x3, %r11d
jne 0xad1a
xorl %r14d, %r14d
shrq $0x20, %r15
movl $0x2, %edi
je 0xad2d
cmpl %r15d, 0x24(%rsp)
jb 0xad2d
movb $0x1, %r8b
xorl %ecx, %ecx
xorl %edx, %edx
movb (%rax,%rdx), %sil
leal -0x1(%rsi), %edi
cmpb $-0x2, %dil
movzbl %r8b, %r8d
cmovbl %ecx, %r8d
movb %sil, 0x13a3(%rsp,%rdx,4)
incq %rdx
cmpq %rdx, %r15
jne 0xacf7
movl %r11d, %eax
orl $0x2, %eax
cmpl $0x6, %eax
jne 0xad2f
movl $0x2, %edi
xorl %r14d, %r14d
jmp 0xad8c
movl %r8d, 0x8(%rsp)
movl %r10d, 0x4(%rsp)
leaq 0xd0(%rsp), %r14
leaq 0x50(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb380
movl 0xe8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xad66
andl $0x20000000, %eax       # imm = 0x20000000
jne 0xad46
movq 0xd8(%rsp), %r14
movq 0xe8(%rsp), %r15
xorl %edi, %edi
movl 0x18(%rsp), %r9d
movl 0x4(%rsp), %r10d
movq 0x28(%rsp), %r11
movl 0x8(%rsp), %r8d
testl %edi, %edi
jne 0xb26b
movl %r12d, 0x34(%rsp)
movl %r10d, 0x4(%rsp)
movb $0x1, 0x3(%rsp)
movl %r8d, 0x8(%rsp)
leal (,%r13,4), %eax
leal (,%r11,4), %ecx
movl $0x4021301, %edx        # imm = 0x4021301
shrl %cl, %edx
movl %eax, 0xc(%rbx)
andl $0x7, %edx
imull %r9d, %edx
movl %edx, 0x4c(%rsp)
movl %edx, %r12d
imull %r13d, %r12d
addl $0x7, %r12d
shrl $0x3, %r12d
leaq 0x4(%r12), %rcx
cmpl %eax, %ecx
movq %rcx, 0x10(%rsp)
cmoval %ecx, %eax
leal 0x2(%rbp), %ecx
imull %eax, %ecx
movq %rcx, 0x40(%rsp)
leaq 0x1c(%rcx), %rdi
callq 0x1573c
movq %rax, 0x38(%rsp)
movq 0x18(%rbx), %rdi
callq 0x3430
movq 0x38(%rsp), %rax
movq %rax, 0x18(%rbx)
movq %rax, 0x10(%rbx)
movq %rax, %rdx
movzbl 0x8(%rsp), %eax
andl $0x1, %eax
leal (%rax,%rax,2), %eax
addl $0x5, %eax
cmpb $0x0, 0x3(%rsp)
movl $0x6, %ecx
cmovnel %eax, %ecx
movl %ecx, 0x8(%rbx)
movq 0x40(%rsp), %rax
addq %rdx, %rax
addq $0x1c, %rax
movq %r12, 0x38(%rsp)
notq %r12
imulq 0x68(%rsp), %r12
addq %rax, %r12
movb $0x0, 0xda(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0xdc(%rsp)
movups %xmm0, 0xe8(%rsp)
movl $0x1, 0xd0(%rsp)
movups %xmm0, 0xdc(%rsp)
movups %xmm0, 0xe8(%rsp)
movb $-0x2, 0xd8(%rsp)
movq %rax, 0x40(%rsp)
subq %r12, %rax
cmpl $0x0, 0x34(%rsp)
leaq 0x27522(%rip), %rcx     # 0x323cc
movq %r12, 0x8(%rsp)
cmovneq %r12, %rcx
movq $0x0, 0xf8(%rsp)
movq %rcx, 0x100(%rsp)
movq %rcx, 0x108(%rsp)
addq %rax, %rcx
movq %rcx, 0x110(%rsp)
cmpl $0x49444154, %r15d      # imm = 0x49444154
jne 0xaf78
movq 0xe8(%rsp), %rax
cmpq 0xf0(%rsp), %rax
jne 0xb37a
cmpb $0x1, 0xda(%rsp)
je 0xb37a
shrq $0x20, %r15
movq %r14, 0xe8(%rsp)
addq %r14, %r15
movq %r15, 0xf0(%rsp)
movb $0x0, 0xda(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x1d9ee
movl %eax, %r12d
leaq 0xb0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0xb380
movq 0xc8(%rsp), %r15
cmpl $0x2, %r12d
sete %al
cmpl $0x49444154, %r15d      # imm = 0x49444154
jne 0xaf80
movq 0xb8(%rsp), %r14
cmpl $0x2, %r12d
je 0xaee7
jmp 0xaf80
movb $0x1, %al
movl $0x2, %r12d
testb %al, %al
je 0xafca
movq 0xe8(%rsp), %rax
cmpq 0xf0(%rsp), %rax
jne 0xb37a
cmpb $0x1, 0xda(%rsp)
je 0xb37a
leaq 0xe8(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movb $0x1, -0xe(%rax)
leaq 0xd0(%rsp), %rdi
callq 0x1d9ee
movl %eax, %r12d
movl $0x2, %edi
testl %r12d, %r12d
jne 0xb26b
movq 0x108(%rsp), %rax
subq 0x100(%rsp), %rax
addq 0x8(%rsp), %rax
movq 0x40(%rsp), %r12
cmpq %r12, %rax
jne 0xb26b
cmpl $0x49454e44, %r15d      # imm = 0x49454E44
je 0xb03e
leaq 0xb0(%rsp), %r14
leaq 0x50(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb380
movl 0xc8(%rsp), %eax
cmpl $0x74524e53, %eax       # imm = 0x74524E53
je 0xb031
andl $0x20000000, %eax       # imm = 0x20000000
jne 0xb011
movq 0xc8(%rsp), %r15
movl $0x2, %edi
cmpq $0x49454e44, %r15       # imm = 0x49454E44
jne 0xb26b
movq 0x10(%rsp), %r15
movq %r15, %rax
movq 0x68(%rsp), %r14
imulq %r14, %rax
subq %rax, %r12
movq $-0x4, %rdi
subq 0x38(%rsp), %rdi
addq %rdi, %r12
movq 0x8(%rsp), %rdx
cmpb $0x2, (%rdx)
jb 0xb08a
addq %r12, %rdi
xorl %esi, %esi
movq %r15, %rdx
callq 0x3170
movq 0x8(%rsp), %rdx
movl 0x4c(%rsp), %ecx
addl $0x7, %ecx
shrl $0x3, %ecx
movq %r12, %rdi
movq %r15, %rsi
movq 0x38(%rsp), %r8
movq %r14, %r9
callq 0xb41e
testb %al, %al
je 0xb145
addq $0x4, %r12
movq %r12, %rsi
movq 0x28(%rsp), %rax
cmpl $0x2, %eax
je 0xb14f
testl %eax, %eax
jne 0xb19b
cmpl $0x1, 0x18(%rsp)
je 0xb1eb
cmpl $0x2, 0x18(%rsp)
je 0xb304
cmpl $0x4, 0x18(%rsp)
je 0xb2cc
movl 0x4(%rbx), %eax
testl %eax, %eax
je 0xb22d
movl (%rbx), %ecx
movq 0x10(%rbx), %rdx
leaq (,%rcx,4), %r11
xorl %edi, %edi
movq 0x10(%rsp), %r10
testq %rcx, %rcx
je 0xb134
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 0xb115
addq %r10, %rsi
incl %edi
addq %r11, %rdx
cmpl %eax, %edi
jne 0xb10d
jmp 0xb22d
movl $0x2, %edi
jmp 0xb26b
movl 0x4(%rbx), %r12d
testl %r12d, %r12d
je 0xb22d
movl (%rbx), %eax
movq 0x10(%rbx), %r15
movq %rax, 0x28(%rsp)
leaq (,%rax,4), %rax
movq %rax, 0x18(%rsp)
movq %rsi, %r14
movq %r15, %rdi
movq %r14, %rsi
movq 0x28(%rsp), %rdx
callq 0xcc8a
addq 0x10(%rsp), %r14
addq 0x18(%rsp), %r15
decl %r12d
jne 0xb177
jmp 0xb22d
cmpl $0x3, 0x28(%rsp)
jne 0xb1d5
cmpl $0x1, 0x18(%rsp)
jne 0xb297
leaq 0x13a0(%rsp), %rcx
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
movl 0x24(%rsp), %r8d
callq 0xb80e
testb %al, %al
movl $0x2, %edi
jne 0xb22d
jmp 0xb26b
cmpl $0x4, 0x28(%rsp)
jne 0xb220
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
callq 0xb988
jmp 0xb22d
cmpb $0x0, 0x3(%rsp)
je 0xb204
leaq 0x24703(%rip), %rax     # 0x2f8fc
movl 0x4(%rsp), %ecx
movl (%rax,%rcx,4), %eax
movl %eax, 0x4(%rsp)
leaq 0x246f1(%rip), %rcx     # 0x2f8fc
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
movl $0x2, %r8d
callq 0xb80e
jmp 0xb22d
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
callq 0xb9de
movl $0x1, %edi
cmpl $0xff000000, 0x4(%rsp)  # imm = 0xFF000000
jb 0xb26b
imull %r13d, %ebp
testl %ebp, %ebp
je 0xb26b
movq 0x18(%rbx), %rax
xorl %ecx, %ecx
movl 0x4(%rsp), %esi
movl (%rax,%rcx,4), %edx
cmpl %esi, %edx
jne 0xb25e
andl $0xffffff, %edx         # imm = 0xFFFFFF
movl %edx, (%rax,%rcx,4)
incq %rcx
cmpq %rcx, %rbp
jne 0xb24e
movl $0x1, %edi
movb $0x1, %al
cmpl $0x2, %edi
jne 0xb285
movq 0x18(%rbx), %rdi
callq 0x3430
movq $0x0, 0x18(%rbx)
xorl %eax, %eax
addq $0x17a8, %rsp           # imm = 0x17A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl $0x2, 0x18(%rsp)
je 0xb33c
cmpl $0x4, 0x18(%rsp)
jne 0xb35b
leaq 0x13a0(%rsp), %rcx
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
movl 0x24(%rsp), %r8d
callq 0x39d8
jmp 0xb1c7
cmpb $0x0, 0x3(%rsp)
je 0xb2e5
leaq 0x24646(%rip), %rax     # 0x2f920
movl 0x4(%rsp), %ecx
movl (%rax,%rcx,4), %eax
movl %eax, 0x4(%rsp)
leaq 0x24634(%rip), %rcx     # 0x2f920
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
movl $0x10, %r8d
callq 0x39d8
jmp 0xb22d
cmpb $0x0, 0x3(%rsp)
je 0xb31d
leaq 0x245fe(%rip), %rax     # 0x2f910
movl 0x4(%rsp), %ecx
movl (%rax,%rcx,4), %eax
movl %eax, 0x4(%rsp)
leaq 0x245ec(%rip), %rcx     # 0x2f910
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
movl $0x4, %r8d
callq 0x3902
jmp 0xb22d
leaq 0x13a0(%rsp), %rcx
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
movl 0x24(%rsp), %r8d
callq 0x3902
jmp 0xb1c7
leaq 0x13a0(%rsp), %rcx
movq %rbx, %rdi
movq 0x10(%rsp), %rdx
movl 0x24(%rsp), %r8d
callq 0x3a7e
jmp 0xb1c7
callq 0x3180
nop