// File: drummyfish[P]flowchart/src/lodepng.cpp
// Function: inflateHuffmanBlock(ucvector*, unsigned char const*, unsigned long*, unsigned long*, unsigned long, unsigned int)
static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp,
                                    size_t* pos, size_t inlength, unsigned btype)
{
  unsigned error = 0;
  HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
  HuffmanTree tree_d; /*the huffman tree for distance codes*/
  size_t inbitlength = inlength * 8;

  HuffmanTree_init(&tree_ll);
  HuffmanTree_init(&tree_d);

  if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d);
  else if(btype == 2)
  {
    error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength);
  }

  while(!error) /*decode all symbols until end reached, breaks at end code*/
  {
    /*code_ll is literal, length or end code*/
    unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength);
    if(code_ll <= 255) /*literal symbol*/
    {
      if((*pos) >= out->size)
      {
        /*reserve more room at once*/
        if(!ucvector_resize(out, ((*pos) + 1) * 2)) ERROR_BREAK(83 /*alloc fail*/);
      }
      out->data[(*pos)] = (unsigned char)(code_ll);
      (*pos)++;
    }
    else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/
    {
      unsigned code_d, distance;
      unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/
      size_t start, forward, backward, length;

      /*part 1: get length base*/
      length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX];

      /*part 2: get extra bits and add the value of that to length*/
      numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
      if(*bp >= inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
      length += readBitsFromStream(bp, in, numextrabits_l);

      /*part 3: get distance code*/
      code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength);
      if(code_d > 29)
      {
        if(code_ll == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/
        {
          /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
          (10=no endcode, 11=wrong jump outside of tree)*/
          error = (*bp) > inlength * 8 ? 10 : 11;
        }
        else error = 18; /*error: invalid distance code (30-31 are never used)*/
        break;
      }
      distance = DISTANCEBASE[code_d];

      /*part 4: get extra bits from distance*/
      numextrabits_d = DISTANCEEXTRA[code_d];
      if(*bp >= inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/

      distance += readBitsFromStream(bp, in, numextrabits_d);

      /*part 5: fill in all the out[n] values based on the length and dist*/
      start = (*pos);
      if(distance > start) ERROR_BREAK(52); /*too long backward distance*/
      backward = start - distance;
      if((*pos) + length >= out->size)
      {
        /*reserve more room at once*/
        if(!ucvector_resize(out, ((*pos) + length) * 2)) ERROR_BREAK(83 /*alloc fail*/);
      }

      for(forward = 0; forward < length; forward++)
      {
        out->data[(*pos)] = out->data[backward];
        (*pos)++;
        backward++;
        if(backward >= start) backward = start - distance;
      }
    }
    else if(code_ll == 256)
    {
      break; /*end code, break the loop*/
    }
    else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/
    {
      /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
      (10=no endcode, 11=wrong jump outside of tree)*/
      error = (*bp) > inlength * 8 ? 10 : 11;
      break;
    }
  }

  HuffmanTree_cleanup(&tree_ll);
  HuffmanTree_cleanup(&tree_d);

  return error;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movl %r9d, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
movq -0x28(%rbp), %rax
shlq $0x3, %rax
movq %rax, -0x78(%rbp)
leaq -0x50(%rbp), %rdi
callq 0xd7d0
leaq -0x70(%rbp), %rdi
callq 0xd7d0
cmpl $0x1, -0x2c(%rbp)
jne 0xd3ad
leaq -0x50(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0xd800
jmp 0xd3d1
cmpl $0x2, -0x2c(%rbp)
jne 0xd3cf
movq -0x10(%rbp), %rdx
movq -0x18(%rbp), %rcx
movq -0x28(%rbp), %r8
leaq -0x50(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0xd830
movl %eax, -0x30(%rbp)
jmp 0xd3d1
jmp 0xd3d3
cmpl $0x0, -0x30(%rbp)
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0xd3e5
jmp 0xd711
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x78(%rbp), %rcx
leaq -0x50(%rbp), %rdx
callq 0xde10
movl %eax, -0x7c(%rbp)
cmpl $0xff, -0x7c(%rbp)
ja 0xd46a
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq -0x8(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jb 0xd441
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rax
movq (%rax), %rsi
addq $0x1, %rsi
shlq %rsi
callq 0xd730
cmpl $0x0, %eax
jne 0xd43f
movl $0x53, -0x30(%rbp)
jmp 0xd711
jmp 0xd441
movl -0x7c(%rbp), %eax
movb %al, %dl
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq -0x20(%rbp), %rcx
movq (%rcx), %rcx
movb %dl, (%rax,%rcx)
movq -0x20(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
jmp 0xd70c
cmpl $0x101, -0x7c(%rbp)     # imm = 0x101
jb 0xd6db
cmpl $0x11d, -0x7c(%rbp)     # imm = 0x11D
ja 0xd6db
movl -0x7c(%rbp), %eax
subl $0x101, %eax            # imm = 0x101
movl %eax, %eax
movl %eax, %ecx
leaq 0x10d99(%rip), %rax     # 0x1e230
movl (%rax,%rcx,4), %eax
movq %rax, -0xb0(%rbp)
movl -0x7c(%rbp), %eax
subl $0x101, %eax            # imm = 0x101
movl %eax, %eax
movl %eax, %ecx
leaq 0x10dfc(%rip), %rax     # 0x1e2b0
movl (%rax,%rcx,4), %eax
movl %eax, -0x88(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpq -0x78(%rbp), %rax
jb 0xd4d6
movl $0x33, -0x30(%rbp)
jmp 0xd711
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl -0x88(%rbp), %eax
movl %eax, %edx
callq 0xdee0
movl %eax, %eax
addq -0xb0(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x78(%rbp), %rcx
leaq -0x70(%rbp), %rdx
callq 0xde10
movl %eax, -0x80(%rbp)
cmpl $0x1d, -0x80(%rbp)
jbe 0xd54f
cmpl $-0x1, -0x7c(%rbp)
jne 0xd543
movq -0x18(%rbp), %rax
movq (%rax), %rdx
movq -0x28(%rbp), %rsi
shlq $0x3, %rsi
movl $0xb, %eax
movl $0xa, %ecx
cmpq %rsi, %rdx
cmoval %ecx, %eax
movl %eax, -0x30(%rbp)
jmp 0xd54a
movl $0x12, -0x30(%rbp)
jmp 0xd711
movl -0x80(%rbp), %eax
movl %eax, %ecx
leaq 0x10dd5(%rip), %rax     # 0x1e330
movl (%rax,%rcx,4), %eax
movl %eax, -0x84(%rbp)
movl -0x80(%rbp), %eax
movl %eax, %ecx
leaq 0x10e40(%rip), %rax     # 0x1e3b0
movl (%rax,%rcx,4), %eax
movl %eax, -0x8c(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
cmpq -0x78(%rbp), %rax
jb 0xd592
movl $0x33, -0x30(%rbp)
jmp 0xd711
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl -0x8c(%rbp), %eax
movl %eax, %edx
callq 0xdee0
addl -0x84(%rbp), %eax
movl %eax, -0x84(%rbp)
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x98(%rbp)
movl -0x84(%rbp), %eax
cmpq -0x98(%rbp), %rax
jbe 0xd5dc
movl $0x34, -0x30(%rbp)
jmp 0xd711
movq -0x98(%rbp), %rax
movl -0x84(%rbp), %ecx
subq %rcx, %rax
movq %rax, -0xa8(%rbp)
movq -0x20(%rbp), %rax
movq (%rax), %rax
addq -0xb0(%rbp), %rax
movq -0x8(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jb 0xd638
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rax
movq (%rax), %rsi
addq -0xb0(%rbp), %rsi
shlq %rsi
callq 0xd730
cmpl $0x0, %eax
jne 0xd636
movl $0x53, -0x30(%rbp)
jmp 0xd711
jmp 0xd638
movq $0x0, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
cmpq -0xb0(%rbp), %rax
jae 0xd6d9
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq -0xa8(%rbp), %rcx
movb (%rax,%rcx), %dl
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq -0x20(%rbp), %rcx
movq (%rcx), %rcx
movb %dl, (%rax,%rcx)
movq -0x20(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movq -0xa8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
cmpq -0x98(%rbp), %rax
jb 0xd6c0
movq -0x98(%rbp), %rax
movl -0x84(%rbp), %ecx
subq %rcx, %rax
movq %rax, -0xa8(%rbp)
jmp 0xd6c2
movq -0xa0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
jmp 0xd643
jmp 0xd70a
cmpl $0x100, -0x7c(%rbp)     # imm = 0x100
jne 0xd6e6
jmp 0xd711
movq -0x18(%rbp), %rax
movq (%rax), %rdx
movq -0x28(%rbp), %rsi
shlq $0x3, %rsi
movl $0xb, %eax
movl $0xa, %ecx
cmpq %rsi, %rdx
cmoval %ecx, %eax
movl %eax, -0x30(%rbp)
jmp 0xd711
jmp 0xd70c
jmp 0xd3d3
leaq -0x50(%rbp), %rdi
callq 0xdf60
leaq -0x70(%rbp), %rdi
callq 0xdf60
movl -0x30(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
nop