// File: Lut99[P]RayTracer/src/lib/LodePNG.cpp
// Function: filter(unsigned char*, unsigned char const*, unsigned int, unsigned int, LodePNGColorMode const*, LodePNGEncoderSettings const*)
static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,
                       const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) {
  /*
  For PNG filter method 0
  out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are
  the scanlines with 1 extra byte per scanline
  */

  unsigned bpp = lodepng_get_bpp(info);
  /*the width of a scanline in bytes, not including the filter type*/
  size_t linebytes = (w * bpp + 7u) / 8u;
  /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
  size_t bytewidth = (bpp + 7u) / 8u;
  const unsigned char* prevline = 0;
  unsigned x, y;
  unsigned error = 0;
  LodePNGFilterStrategy strategy = settings->filter_strategy;

  /*
  There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard:
   *  If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e.
      use fixed filtering, with the filter None).
   * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is
     not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply
     all five filters and select the filter that produces the smallest sum of absolute values per row.
  This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true.

  If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed,
  but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum
  heuristic is used.
  */
  if(settings->filter_palette_zero &&
     (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO;

  if(bpp == 0) return 31; /*error: invalid color type*/

  if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) {
    unsigned char type = (unsigned char)strategy;
    for(y = 0; y != h; ++y) {
      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
      size_t inindex = linebytes * y;
      out[outindex] = type; /*filter type byte*/
      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
      prevline = &in[inindex];
    }
  } else if(strategy == LFS_MINSUM) {
    /*adaptive filtering*/
    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
    size_t smallest = 0;
    unsigned char type, bestType = 0;

    for(type = 0; type != 5; ++type) {
      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
      if(!attempt[type]) return 83; /*alloc fail*/
    }

    if(!error) {
      for(y = 0; y != h; ++y) {
        /*try the 5 filter types*/
        for(type = 0; type != 5; ++type) {
          size_t sum = 0;
          filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);

          /*calculate the sum of the result*/
          if(type == 0) {
            for(x = 0; x != linebytes; ++x) sum += (unsigned char)(attempt[type][x]);
          } else {
            for(x = 0; x != linebytes; ++x) {
              /*For differences, each byte should be treated as signed, values above 127 are negative
              (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there.
              This means filtertype 0 is almost never chosen, but that is justified.*/
              unsigned char s = attempt[type][x];
              sum += s < 128 ? s : (255U - s);
            }
          }

          /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
          if(type == 0 || sum < smallest) {
            bestType = type;
            smallest = sum;
          }
        }

        prevline = &in[y * linebytes];

        /*now fill the out values*/
        out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
        for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
      }
    }

    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
  } else if(strategy == LFS_ENTROPY) {
    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
    size_t bestSum = 0;
    unsigned type, bestType = 0;
    unsigned count[256];

    for(type = 0; type != 5; ++type) {
      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
      if(!attempt[type]) return 83; /*alloc fail*/
    }

    for(y = 0; y != h; ++y) {
      /*try the 5 filter types*/
      for(type = 0; type != 5; ++type) {
        size_t sum = 0;
        filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
        for(x = 0; x != 256; ++x) count[x] = 0;
        for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]];
        ++count[type]; /*the filter type itself is part of the scanline*/
        for(x = 0; x != 256; ++x) {
          sum += ilog2i(count[x]);
        }
        /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
        if(type == 0 || sum > bestSum) {
          bestType = type;
          bestSum = sum;
        }
      }

      prevline = &in[y * linebytes];

      /*now fill the out values*/
      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
      for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
    }

    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
  } else if(strategy == LFS_PREDEFINED) {
    for(y = 0; y != h; ++y) {
      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
      size_t inindex = linebytes * y;
      unsigned char type = settings->predefined_filters[y];
      out[outindex] = type; /*filter type byte*/
      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
      prevline = &in[inindex];
    }
  } else if(strategy == LFS_BRUTE_FORCE) {
    /*brute force filter chooser.
    deflate the scanline after every filter attempt to see which one deflates best.
    This is very slow and gives only slightly smaller, sometimes even larger, result*/
    size_t size[5];
    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
    size_t smallest = 0;
    unsigned type = 0, bestType = 0;
    unsigned char* dummy;
    LodePNGCompressSettings zlibsettings = settings->zlibsettings;
    /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose,
    to simulate the true case where the tree is the same for the whole image. Sometimes it gives
    better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare
    cases better compression. It does make this a bit less slow, so it's worth doing this.*/
    zlibsettings.btype = 1;
    /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG
    images only, so disable it*/
    zlibsettings.custom_zlib = 0;
    zlibsettings.custom_deflate = 0;
    for(type = 0; type != 5; ++type) {
      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
      if(!attempt[type]) return 83; /*alloc fail*/
    }
    for(y = 0; y != h; ++y) /*try the 5 filter types*/ {
      for(type = 0; type != 5; ++type) {
        unsigned testsize = (unsigned)linebytes;
        /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/

        filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
        size[type] = 0;
        dummy = 0;
        zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings);
        lodepng_free(dummy);
        /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/
        if(type == 0 || size[type] < smallest) {
          bestType = type;
          smallest = size[type];
        }
      }
      prevline = &in[y * linebytes];
      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
      for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
    }
    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
  }
  else return 88; /* unknown filter strategy */

  return error;
}

// Assembly:
subq $0x5d8, %rsp            # imm = 0x5D8
movq %rdi, 0x5c8(%rsp)
movq %rsi, 0x5c0(%rsp)
movl %edx, 0x5bc(%rsp)
movl %ecx, 0x5b8(%rsp)
movq %r8, 0x5b0(%rsp)
movq %r9, 0x5a8(%rsp)
movq 0x5b0(%rsp), %rdi
callq 0x13fb50
movl %eax, 0x5a4(%rsp)
movl 0x5bc(%rsp), %eax
imull 0x5a4(%rsp), %eax
addl $0x7, %eax
shrl $0x3, %eax
movl %eax, %eax
movq %rax, 0x598(%rsp)
movl 0x5a4(%rsp), %eax
addl $0x7, %eax
shrl $0x3, %eax
movl %eax, %eax
movq %rax, 0x590(%rsp)
movq $0x0, 0x588(%rsp)
movl $0x0, 0x57c(%rsp)
movq 0x5a8(%rsp), %rax
movl 0x38(%rax), %eax
movl %eax, 0x578(%rsp)
movq 0x5a8(%rsp), %rax
cmpl $0x0, 0x34(%rax)
je 0x151c7c
movq 0x5b0(%rsp), %rax
cmpl $0x3, (%rax)
je 0x151c71
movq 0x5b0(%rsp), %rax
cmpl $0x8, 0x4(%rax)
jae 0x151c7c
movl $0x0, 0x578(%rsp)
cmpl $0x0, 0x5a4(%rsp)
jne 0x151c96
movl $0x1f, 0x5d4(%rsp)
jmp 0x1528ff
cmpl $0x0, 0x578(%rsp)
jl 0x151db3
cmpl $0x4, 0x578(%rsp)
jg 0x151db3
movl 0x578(%rsp), %eax
movb %al, 0x577(%rsp)
movl $0x0, 0x580(%rsp)
movl 0x580(%rsp), %eax
cmpl 0x5b8(%rsp), %eax
je 0x151dae
movq 0x598(%rsp), %rax
addq $0x1, %rax
movl 0x580(%rsp), %ecx
imulq %rcx, %rax
movq %rax, 0x568(%rsp)
movq 0x598(%rsp), %rax
movl 0x580(%rsp), %ecx
imulq %rcx, %rax
movq %rax, 0x560(%rsp)
movb 0x577(%rsp), %dl
movq 0x5c8(%rsp), %rax
movq 0x568(%rsp), %rcx
movb %dl, (%rax,%rcx)
movq 0x5c8(%rsp), %rdi
movq 0x568(%rsp), %rax
addq $0x1, %rax
addq %rax, %rdi
movq 0x5c0(%rsp), %rsi
addq 0x560(%rsp), %rsi
movq 0x588(%rsp), %rdx
movq 0x598(%rsp), %rcx
movq 0x590(%rsp), %r8
movzbl 0x577(%rsp), %r9d
callq 0x152cb0
movq 0x5c0(%rsp), %rax
addq 0x560(%rsp), %rax
movq %rax, 0x588(%rsp)
movl 0x580(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x580(%rsp)
jmp 0x151ccb
jmp 0x1528f1
cmpl $0x5, 0x578(%rsp)
jne 0x15215c
movq $0x0, 0x528(%rsp)
movb $0x0, 0x526(%rsp)
movb $0x0, 0x527(%rsp)
movzbl 0x527(%rsp), %eax
cmpl $0x5, %eax
je 0x151e41
movq 0x598(%rsp), %rdi
callq 0x13ce80
movq %rax, %rcx
movzbl 0x527(%rsp), %eax
movq %rcx, 0x530(%rsp,%rax,8)
movzbl 0x527(%rsp), %eax
cmpq $0x0, 0x530(%rsp,%rax,8)
jne 0x151e2d
movl $0x53, 0x5d4(%rsp)
jmp 0x1528ff
jmp 0x151e2f
movb 0x527(%rsp), %al
addb $0x1, %al
movb %al, 0x527(%rsp)
jmp 0x151ddd
cmpl $0x0, 0x57c(%rsp)
jne 0x15211b
movl $0x0, 0x580(%rsp)
movl 0x580(%rsp), %eax
cmpl 0x5b8(%rsp), %eax
je 0x152119
movb $0x0, 0x527(%rsp)
movzbl 0x527(%rsp), %eax
cmpl $0x5, %eax
je 0x15203c
movq $0x0, 0x518(%rsp)
movzbl 0x527(%rsp), %eax
movq 0x530(%rsp,%rax,8), %rdi
movq 0x5c0(%rsp), %rsi
movl 0x580(%rsp), %eax
imulq 0x598(%rsp), %rax
addq %rax, %rsi
movq 0x588(%rsp), %rdx
movq 0x598(%rsp), %rcx
movq 0x590(%rsp), %r8
movzbl 0x527(%rsp), %r9d
callq 0x152cb0
movzbl 0x527(%rsp), %eax
cmpl $0x0, %eax
jne 0x151f50
movl $0x0, 0x584(%rsp)
movl 0x584(%rsp), %eax
cmpq 0x598(%rsp), %rax
je 0x151f4b
movzbl 0x527(%rsp), %eax
movq 0x530(%rsp,%rax,8), %rax
movl 0x584(%rsp), %ecx
movzbl (%rax,%rcx), %eax
addq 0x518(%rsp), %rax
movq %rax, 0x518(%rsp)
movl 0x584(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x584(%rsp)
jmp 0x151efc
jmp 0x151fe8
movl $0x0, 0x584(%rsp)
movl 0x584(%rsp), %eax
cmpq 0x598(%rsp), %rax
je 0x151fe6
movzbl 0x527(%rsp), %eax
movq 0x530(%rsp,%rax,8), %rax
movl 0x584(%rsp), %ecx
movb (%rax,%rcx), %al
movb %al, 0x517(%rsp)
movzbl 0x517(%rsp), %eax
cmpl $0x80, %eax
jge 0x151fa9
movzbl 0x517(%rsp), %eax
movl %eax, (%rsp)
jmp 0x151fbb
movzbl 0x517(%rsp), %ecx
movl $0xff, %eax
subl %ecx, %eax
movl %eax, (%rsp)
movl (%rsp), %eax
movl %eax, %eax
addq 0x518(%rsp), %rax
movq %rax, 0x518(%rsp)
movl 0x584(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x584(%rsp)
jmp 0x151f5b
jmp 0x151fe8
movzbl 0x527(%rsp), %eax
cmpl $0x0, %eax
je 0x152007
movq 0x518(%rsp), %rax
cmpq 0x528(%rsp), %rax
jae 0x152025
movb 0x527(%rsp), %al
movb %al, 0x526(%rsp)
movq 0x518(%rsp), %rax
movq %rax, 0x528(%rsp)
jmp 0x152027
movb 0x527(%rsp), %al
addb $0x1, %al
movb %al, 0x527(%rsp)
jmp 0x151e76
movq 0x5c0(%rsp), %rax
movl 0x580(%rsp), %ecx
imulq 0x598(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x588(%rsp)
movb 0x526(%rsp), %dl
movq 0x5c8(%rsp), %rax
movl 0x580(%rsp), %ecx
movq 0x598(%rsp), %rsi
addq $0x1, %rsi
imulq %rsi, %rcx
movb %dl, (%rax,%rcx)
movl $0x0, 0x584(%rsp)
movl 0x584(%rsp), %eax
cmpq 0x598(%rsp), %rax
je 0x152101
movzbl 0x526(%rsp), %eax
movq 0x530(%rsp,%rax,8), %rax
movl 0x584(%rsp), %ecx
movb (%rax,%rcx), %dl
movq 0x5c8(%rsp), %rax
movl 0x580(%rsp), %ecx
movq 0x598(%rsp), %rsi
addq $0x1, %rsi
imulq %rsi, %rcx
addq $0x1, %rcx
movl 0x584(%rsp), %esi
addq %rsi, %rcx
movb %dl, (%rax,%rcx)
movl 0x584(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x584(%rsp)
jmp 0x152093
jmp 0x152103
movl 0x580(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x580(%rsp)
jmp 0x151e5a
jmp 0x15211b
movb $0x0, 0x527(%rsp)
movzbl 0x527(%rsp), %eax
cmpl $0x5, %eax
je 0x152157
movzbl 0x527(%rsp), %eax
movq 0x530(%rsp,%rax,8), %rdi
callq 0x13e2d0
movb 0x527(%rsp), %al
addb $0x1, %al
movb %al, 0x527(%rsp)
jmp 0x152123
jmp 0x1528ef
cmpl $0x6, 0x578(%rsp)
jne 0x1524f2
movq $0x0, 0x4d8(%rsp)
movl $0x0, 0x4d0(%rsp)
movl $0x0, 0x4d4(%rsp)
cmpl $0x5, 0x4d4(%rsp)
je 0x1521ec
movq 0x598(%rsp), %rdi
callq 0x13ce80
movq %rax, %rcx
movl 0x4d4(%rsp), %eax
movq %rcx, 0x4e0(%rsp,%rax,8)
movl 0x4d4(%rsp), %eax
cmpq $0x0, 0x4e0(%rsp,%rax,8)
jne 0x1521d7
movl $0x53, 0x5d4(%rsp)
jmp 0x1528ff
jmp 0x1521d9
movl 0x4d4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4d4(%rsp)
jmp 0x15218c
movl $0x0, 0x580(%rsp)
movl 0x580(%rsp), %eax
cmpl 0x5b8(%rsp), %eax
je 0x1524b1
movl $0x0, 0x4d4(%rsp)
cmpl $0x5, 0x4d4(%rsp)
je 0x1523d3
movq $0x0, 0xc8(%rsp)
movl 0x4d4(%rsp), %eax
movq 0x4e0(%rsp,%rax,8), %rdi
movq 0x5c0(%rsp), %rsi
movl 0x580(%rsp), %eax
imulq 0x598(%rsp), %rax
addq %rax, %rsi
movq 0x588(%rsp), %rdx
movq 0x598(%rsp), %rcx
movq 0x590(%rsp), %r8
movl 0x4d4(%rsp), %eax
movzbl %al, %r9d
callq 0x152cb0
movl $0x0, 0x584(%rsp)
cmpl $0x100, 0x584(%rsp) # imm = 0x100
je 0x1522bf
movl 0x584(%rsp), %eax
movl $0x0, 0xd0(%rsp,%rax,4)
movl 0x584(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x584(%rsp)
jmp 0x15228d
movl $0x0, 0x584(%rsp)
movl 0x584(%rsp), %eax
cmpq 0x598(%rsp), %rax
je 0x152319
movl 0x4d4(%rsp), %eax
movq 0x4e0(%rsp,%rax,8), %rax
movl 0x584(%rsp), %ecx
movzbl (%rax,%rcx), %eax
movl 0xd0(%rsp,%rax,4), %ecx
addl $0x1, %ecx
movl %ecx, 0xd0(%rsp,%rax,4)
movl 0x584(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x584(%rsp)
jmp 0x1522ca
movl 0x4d4(%rsp), %eax
movl 0xd0(%rsp,%rax,4), %ecx
addl $0x1, %ecx
movl %ecx, 0xd0(%rsp,%rax,4)
movl $0x0, 0x584(%rsp)
cmpl $0x100, 0x584(%rsp) # imm = 0x100
je 0x152381
movl 0x584(%rsp), %eax
movl 0xd0(%rsp,%rax,4), %eax
movl %eax, %edi
callq 0x1531a0
addq 0xc8(%rsp), %rax
movq %rax, 0xc8(%rsp)
movl 0x584(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x584(%rsp)
jmp 0x15233c
cmpl $0x0, 0x4d4(%rsp)
je 0x15239d
movq 0xc8(%rsp), %rax
cmpq 0x4d8(%rsp), %rax
jbe 0x1523bb
movl 0x4d4(%rsp), %eax
movl %eax, 0x4d0(%rsp)
movq 0xc8(%rsp), %rax
movq %rax, 0x4d8(%rsp)
jmp 0x1523bd
movl 0x4d4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4d4(%rsp)
jmp 0x152216
movq 0x5c0(%rsp), %rax
movl 0x580(%rsp), %ecx
imulq 0x598(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x588(%rsp)
movl 0x4d0(%rsp), %eax
movb %al, %dl
movq 0x5c8(%rsp), %rax
movl 0x580(%rsp), %ecx
movq 0x598(%rsp), %rsi
addq $0x1, %rsi
imulq %rsi, %rcx
movb %dl, (%rax,%rcx)
movl $0x0, 0x584(%rsp)
movl 0x584(%rsp), %eax
cmpq 0x598(%rsp), %rax
je 0x152499
movl 0x4d0(%rsp), %eax
movq 0x4e0(%rsp,%rax,8), %rax
movl 0x584(%rsp), %ecx
movb (%rax,%rcx), %dl
movq 0x5c8(%rsp), %rax
movl 0x580(%rsp), %ecx
movq 0x598(%rsp), %rsi
addq $0x1, %rsi
imulq %rsi, %rcx
addq $0x1, %rcx
movl 0x584(%rsp), %esi
addq %rsi, %rcx
movb %dl, (%rax,%rcx)
movl 0x584(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x584(%rsp)
jmp 0x15242c
jmp 0x15249b
movl 0x580(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x580(%rsp)
jmp 0x1521f7
movl $0x0, 0x4d4(%rsp)
cmpl $0x5, 0x4d4(%rsp)
je 0x1524ed
movl 0x4d4(%rsp), %eax
movq 0x4e0(%rsp,%rax,8), %rdi
callq 0x13e2d0
movl 0x4d4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4d4(%rsp)
jmp 0x1524bc
jmp 0x1528ed
cmpl $0x8, 0x578(%rsp)
jne 0x152610
movl $0x0, 0x580(%rsp)
movl 0x580(%rsp), %eax
cmpl 0x5b8(%rsp), %eax
je 0x15260b
movq 0x598(%rsp), %rax
addq $0x1, %rax
movl 0x580(%rsp), %ecx
imulq %rcx, %rax
movq %rax, 0xc0(%rsp)
movq 0x598(%rsp), %rax
movl 0x580(%rsp), %ecx
imulq %rcx, %rax
movq %rax, 0xb8(%rsp)
movq 0x5a8(%rsp), %rax
movq 0x40(%rax), %rax
movl 0x580(%rsp), %ecx
movb (%rax,%rcx), %al
movb %al, 0xb7(%rsp)
movb 0xb7(%rsp), %dl
movq 0x5c8(%rsp), %rax
movq 0xc0(%rsp), %rcx
movb %dl, (%rax,%rcx)
movq 0x5c8(%rsp), %rdi
movq 0xc0(%rsp), %rax
addq $0x1, %rax
addq %rax, %rdi
movq 0x5c0(%rsp), %rsi
addq 0xb8(%rsp), %rsi
movq 0x588(%rsp), %rdx
movq 0x598(%rsp), %rcx
movq 0x590(%rsp), %r8
movzbl 0xb7(%rsp), %r9d
callq 0x152cb0
movq 0x5c0(%rsp), %rax
addq 0xb8(%rsp), %rax
movq %rax, 0x588(%rsp)
movl 0x580(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x580(%rsp)
jmp 0x15250b
jmp 0x1528eb
cmpl $0x7, 0x578(%rsp)
jne 0x1528dc
movq $0x0, 0x48(%rsp)
movl $0x0, 0x44(%rsp)
movl $0x0, 0x40(%rsp)
movq 0x5a8(%rsp), %rsi
leaq 0x8(%rsp), %rdi
movl $0x30, %edx
callq 0xd04d0
movl $0x1, 0x8(%rsp)
movq $0x0, 0x20(%rsp)
movq $0x0, 0x28(%rsp)
movl $0x0, 0x44(%rsp)
cmpl $0x5, 0x44(%rsp)
je 0x1526bb
movq 0x598(%rsp), %rdi
callq 0x13ce80
movq %rax, %rcx
movl 0x44(%rsp), %eax
movq %rcx, 0x50(%rsp,%rax,8)
movl 0x44(%rsp), %eax
cmpq $0x0, 0x50(%rsp,%rax,8)
jne 0x1526ac
movl $0x53, 0x5d4(%rsp)
jmp 0x1528ff
jmp 0x1526ae
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x152670
movl $0x0, 0x580(%rsp)
movl 0x580(%rsp), %eax
cmpl 0x5b8(%rsp), %eax
je 0x1528b0
movl $0x0, 0x44(%rsp)
cmpl $0x5, 0x44(%rsp)
je 0x1527db
movq 0x598(%rsp), %rax
movl %eax, 0x4(%rsp)
movl 0x44(%rsp), %eax
movq 0x50(%rsp,%rax,8), %rdi
movq 0x5c0(%rsp), %rsi
movl 0x580(%rsp), %eax
imulq 0x598(%rsp), %rax
addq %rax, %rsi
movq 0x588(%rsp), %rdx
movq 0x598(%rsp), %rcx
movq 0x590(%rsp), %r8
movl 0x44(%rsp), %eax
movzbl %al, %r9d
callq 0x152cb0
movl 0x44(%rsp), %eax
movq $0x0, 0x80(%rsp,%rax,8)
movq $0x0, 0x38(%rsp)
movl 0x44(%rsp), %eax
leaq 0x80(%rsp), %rsi
shlq $0x3, %rax
addq %rax, %rsi
movl 0x44(%rsp), %eax
movq 0x50(%rsp,%rax,8), %rdx
movl 0x4(%rsp), %eax
movl %eax, %ecx
leaq 0x38(%rsp), %rdi
leaq 0x8(%rsp), %r8
callq 0x14ac70
movq 0x38(%rsp), %rdi
callq 0x13e2d0
cmpl $0x0, 0x44(%rsp)
je 0x1527b0
movl 0x44(%rsp), %eax
movq 0x80(%rsp,%rax,8), %rax
cmpq 0x48(%rsp), %rax
jae 0x1527c9
movl 0x44(%rsp), %eax
movl %eax, 0x40(%rsp)
movl 0x44(%rsp), %eax
movq 0x80(%rsp,%rax,8), %rax
movq %rax, 0x48(%rsp)
jmp 0x1527cb
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x1526e2
movq 0x5c0(%rsp), %rax
movl 0x580(%rsp), %ecx
imulq 0x598(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x588(%rsp)
movl 0x40(%rsp), %eax
movb %al, %dl
movq 0x5c8(%rsp), %rax
movl 0x580(%rsp), %ecx
movq 0x598(%rsp), %rsi
addq $0x1, %rsi
imulq %rsi, %rcx
movb %dl, (%rax,%rcx)
movl $0x0, 0x584(%rsp)
movl 0x584(%rsp), %eax
cmpq 0x598(%rsp), %rax
je 0x152898
movl 0x40(%rsp), %eax
movq 0x50(%rsp,%rax,8), %rax
movl 0x584(%rsp), %ecx
movb (%rax,%rcx), %dl
movq 0x5c8(%rsp), %rax
movl 0x580(%rsp), %ecx
movq 0x598(%rsp), %rsi
addq $0x1, %rsi
imulq %rsi, %rcx
addq $0x1, %rcx
movl 0x584(%rsp), %esi
addq %rsi, %rcx
movb %dl, (%rax,%rcx)
movl 0x584(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x584(%rsp)
jmp 0x152831
jmp 0x15289a
movl 0x580(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x580(%rsp)
jmp 0x1526c6
movl $0x0, 0x44(%rsp)
cmpl $0x5, 0x44(%rsp)
je 0x1528da
movl 0x44(%rsp), %eax
movq 0x50(%rsp,%rax,8), %rdi
callq 0x13e2d0
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x1528b8
jmp 0x1528e9
movl $0x58, 0x5d4(%rsp)
jmp 0x1528ff
jmp 0x1528eb
jmp 0x1528ed
jmp 0x1528ef
jmp 0x1528f1
movl 0x57c(%rsp), %eax
movl %eax, 0x5d4(%rsp)
movl 0x5d4(%rsp), %eax
addq $0x5d8, %rsp            # imm = 0x5D8
retq
nop