// File: Alcaro[P]bridges/arlib/zlibhead.cpp
// Function: inflator::zlibhead::inflate()
inflator::ret_t inflator::zlibhead::inflate()
{
	if (inf.m_state >= 254)
	{
	process_tail:
		inf.bits_refill_fast();
		if (inf.m_in_nbits < 32) return ret_more_input; // state 254 only needs 16 bits, but the other 16 will be used soon anyways
		if (inf.m_state == 254) // zlib header
		{
			uint32_t head = inf.bits_extract(16);
			if ((head&0x000F) != 0x0008 || // CMF.CF == DEFLATE (ZIP supports 8=DEFLATE and 0=uncompressed, but zlib only supports 8)
			// ignore 00F0 CMF.CINFO, inflator ignores window size (and it's almost always 7, the maximum)
			// ignore C000 FLG.FLEVEL, it's just informational, and there are too many compressors for it to make sense anymore
			    (head&0x2000) != 0x0000 || // FLG.FDICT, not supported
			    (__builtin_bswap16(head)%31) != 0) return ret_error; // FLG.FCHECK (1F00 bits), must be a multiple of 31
			// (are both 0 and 31 allowed in FCHECK if 0 is the correct checksum? I think they are)
			
			inf.m_state = 0;
		}
		else // zlib footer
		{
			inf.m_in_bits_buf >>= inf.m_in_nbits&7;
			inf.m_in_nbits &= ~7;
			uint32_t adler_head = __builtin_bswap32(inf.bits_extract(32)); // zlib header is big endian, even though DEFLATE is little...
			if (adler_head != adler) return ret_error;
			return ret_done;
		}
	}
	
	const uint8_t * out_prev = inf.m_out_at;
	ret_t ret = inf.inflate();
	adler = adler32(bytesr(out_prev, inf.m_out_at - out_prev), adler);
	if (ret != ret_done) return ret;
	
	inf.m_state = 255;
	goto process_tail;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x40(%rbp)
movzbl 0x8(%rax), %eax
cmpl $0xfe, %eax
jl 0x46673
jmp 0x46595
movq -0x40(%rbp), %rdi
addq $0x8, %rdi
callq 0xe180
movq -0x40(%rbp), %rax
cmpl $0x20, 0xc(%rax)
jae 0x465b8
movl $0x2, -0x4(%rbp)
jmp 0x466df
movq -0x40(%rbp), %rax
movzbl 0x8(%rax), %eax
cmpl $0xfe, %eax
jne 0x46621
movq -0x40(%rbp), %rdi
addq $0x8, %rdi
movl $0x10, %esi
callq 0xe290
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0xf, %eax
cmpl $0x8, %eax
jne 0x4660b
movl -0x14(%rbp), %eax
andl $0x2000, %eax           # imm = 0x2000
cmpl $0x0, %eax
jne 0x4660b
movl -0x14(%rbp), %eax
rolw $0x8, %ax
movzwl %ax, %eax
movl $0x1f, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x46617
movl $0x1, -0x4(%rbp)
jmp 0x466df
movq -0x40(%rbp), %rax
movb $0x0, 0x8(%rax)
jmp 0x46671
movq -0x40(%rbp), %rdi
movl 0xc(%rdi), %ecx
andl $0x7, %ecx
movq 0x10(%rdi), %rax
movl %ecx, %ecx
shrq %cl, %rax
movq %rax, 0x10(%rdi)
movl 0xc(%rdi), %eax
andl $-0x8, %eax
movl %eax, 0xc(%rdi)
addq $0x8, %rdi
movl $0x20, %esi
callq 0xe290
movq -0x40(%rbp), %rcx
bswapl %eax
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl (%rcx), %eax
je 0x46668
movl $0x1, -0x4(%rbp)
jmp 0x466df
movl $0x0, -0x4(%rbp)
jmp 0x466df
jmp 0x46673
movq -0x40(%rbp), %rdi
movq 0x38(%rdi), %rax
movq %rax, -0x20(%rbp)
addq $0x8, %rdi
callq 0xe3b0
movl %eax, %ecx
movq -0x40(%rbp), %rax
movl %ecx, -0x24(%rbp)
movq -0x20(%rbp), %rsi
movq 0x38(%rax), %rdx
movq -0x20(%rbp), %rax
subq %rax, %rdx
leaq -0x38(%rbp), %rdi
callq 0x5d70
movq -0x40(%rbp), %rax
movl (%rax), %edx
movq -0x38(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x462e0
movl %eax, %ecx
movq -0x40(%rbp), %rax
movl %ecx, (%rax)
cmpl $0x0, -0x24(%rbp)
je 0x466d2
movl -0x24(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x466df
movq -0x40(%rbp), %rax
movb $-0x1, 0x8(%rax)
jmp 0x46595
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)