// File: Lut99[P]RayTracer/src/lib/LodePNG.cpp
// Function: lodepng_convert_rgb(unsigned int*, unsigned int*, unsigned int*, unsigned int, unsigned int, unsigned int, LodePNGColorMode const*, LodePNGColorMode const*)
unsigned lodepng_convert_rgb(
    unsigned* r_out, unsigned* g_out, unsigned* b_out,
    unsigned r_in, unsigned g_in, unsigned b_in,
    const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) {
  unsigned r = 0, g = 0, b = 0;
  unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/
  unsigned shift = 16 - mode_out->bitdepth;

  if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) {
    r = g = b = r_in * mul;
  } else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) {
    r = r_in * mul;
    g = g_in * mul;
    b = b_in * mul;
  } else if(mode_in->colortype == LCT_PALETTE) {
    if(r_in >= mode_in->palettesize) return 82;
    r = mode_in->palette[r_in * 4 + 0] * 257u;
    g = mode_in->palette[r_in * 4 + 1] * 257u;
    b = mode_in->palette[r_in * 4 + 2] * 257u;
  } else {
    return 31;
  }

  /* now convert to output format */
  if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) {
    *r_out = r >> shift ;
  } else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) {
    *r_out = r >> shift ;
    *g_out = g >> shift ;
    *b_out = b >> shift ;
  } else if(mode_out->colortype == LCT_PALETTE) {
    unsigned i;
    /* a 16-bit color cannot be in the palette */
    if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82;
    for(i = 0; i < mode_out->palettesize; i++) {
      unsigned j = i * 4;
      if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] &&
          (b >> 8) == mode_out->palette[j + 2]) {
        *r_out = i;
        return 0;
      }
    }
    return 82;
  } else {
    return 31;
  }

  return 0;
}

// Assembly:
movq 0x10(%rsp), %rax
movq 0x8(%rsp), %rax
movq %rdi, -0x10(%rsp)
movq %rsi, -0x18(%rsp)
movq %rdx, -0x20(%rsp)
movl %ecx, -0x24(%rsp)
movl %r8d, -0x28(%rsp)
movl %r9d, -0x2c(%rsp)
movl $0x0, -0x30(%rsp)
movl $0x0, -0x34(%rsp)
movl $0x0, -0x38(%rsp)
movq 0x10(%rsp), %rax
movl 0x4(%rax), %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, %ecx
subl $0x1, %ecx
movl $0xffff, %eax           # imm = 0xFFFF
xorl %edx, %edx
divl %ecx
movl %eax, -0x3c(%rsp)
movq 0x8(%rsp), %rcx
movl $0x10, %eax
subl 0x4(%rcx), %eax
movl %eax, -0x40(%rsp)
movq 0x10(%rsp), %rax
cmpl $0x0, (%rax)
je 0x143395
movq 0x10(%rsp), %rax
cmpl $0x4, (%rax)
jne 0x1433af
movl -0x24(%rsp), %eax
imull -0x3c(%rsp), %eax
movl %eax, -0x38(%rsp)
movl %eax, -0x34(%rsp)
movl %eax, -0x30(%rsp)
jmp 0x143495
movq 0x10(%rsp), %rax
cmpl $0x2, (%rax)
je 0x1433c3
movq 0x10(%rsp), %rax
cmpl $0x6, (%rax)
jne 0x1433ef
movl -0x24(%rsp), %eax
imull -0x3c(%rsp), %eax
movl %eax, -0x30(%rsp)
movl -0x28(%rsp), %eax
imull -0x3c(%rsp), %eax
movl %eax, -0x34(%rsp)
movl -0x2c(%rsp), %eax
imull -0x3c(%rsp), %eax
movl %eax, -0x38(%rsp)
jmp 0x143493
movq 0x10(%rsp), %rax
cmpl $0x3, (%rax)
jne 0x143484
movl -0x24(%rsp), %eax
movq 0x10(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jb 0x143419
movl $0x52, -0x4(%rsp)
jmp 0x14363b
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rax
movl -0x24(%rsp), %ecx
shll $0x2, %ecx
addl $0x0, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
imull $0x101, %eax, %eax      # imm = 0x101
movl %eax, -0x30(%rsp)
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rax
movl -0x24(%rsp), %ecx
shll $0x2, %ecx
addl $0x1, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
imull $0x101, %eax, %eax      # imm = 0x101
movl %eax, -0x34(%rsp)
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rax
movl -0x24(%rsp), %ecx
shll $0x2, %ecx
addl $0x2, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
imull $0x101, %eax, %eax      # imm = 0x101
movl %eax, -0x38(%rsp)
jmp 0x143491
movl $0x1f, -0x4(%rsp)
jmp 0x14363b
jmp 0x143493
jmp 0x143495
movq 0x8(%rsp), %rax
cmpl $0x0, (%rax)
je 0x1434a9
movq 0x8(%rsp), %rax
cmpl $0x4, (%rax)
jne 0x1434c1
movl -0x30(%rsp), %eax
movl -0x40(%rsp), %ecx
shrl %cl, %eax
movl %eax, %ecx
movq -0x10(%rsp), %rax
movl %ecx, (%rax)
jmp 0x143633
movq 0x8(%rsp), %rax
cmpl $0x2, (%rax)
je 0x1434d5
movq 0x8(%rsp), %rax
cmpl $0x6, (%rax)
jne 0x143513
movl -0x30(%rsp), %eax
movl -0x40(%rsp), %ecx
shrl %cl, %eax
movl %eax, %ecx
movq -0x10(%rsp), %rax
movl %ecx, (%rax)
movl -0x34(%rsp), %eax
movl -0x40(%rsp), %ecx
shrl %cl, %eax
movl %eax, %ecx
movq -0x18(%rsp), %rax
movl %ecx, (%rax)
movl -0x38(%rsp), %eax
movl -0x40(%rsp), %ecx
shrl %cl, %eax
movl %eax, %ecx
movq -0x20(%rsp), %rax
movl %ecx, (%rax)
jmp 0x143631
movq 0x8(%rsp), %rax
cmpl $0x3, (%rax)
jne 0x143627
movl -0x30(%rsp), %eax
shrl $0x8, %eax
movl -0x30(%rsp), %ecx
andl $0xff, %ecx
cmpl %ecx, %eax
jne 0x143560
movl -0x34(%rsp), %eax
shrl $0x8, %eax
movl -0x34(%rsp), %ecx
andl $0xff, %ecx
cmpl %ecx, %eax
jne 0x143560
movl -0x38(%rsp), %eax
shrl $0x8, %eax
movl -0x38(%rsp), %ecx
andl $0xff, %ecx
cmpl %ecx, %eax
je 0x14356d
movl $0x52, -0x4(%rsp)
jmp 0x14363b
movl $0x0, -0x44(%rsp)
movl -0x44(%rsp), %eax
movq 0x8(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jae 0x14361d
movl -0x44(%rsp), %eax
shll $0x2, %eax
movl %eax, -0x48(%rsp)
movl -0x30(%rsp), %eax
shrl $0x8, %eax
movq 0x8(%rsp), %rcx
movq 0x8(%rcx), %rcx
movl -0x48(%rsp), %edx
addl $0x0, %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x14360b
movl -0x34(%rsp), %eax
shrl $0x8, %eax
movq 0x8(%rsp), %rcx
movq 0x8(%rcx), %rcx
movl -0x48(%rsp), %edx
addl $0x1, %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x14360b
movl -0x38(%rsp), %eax
shrl $0x8, %eax
movq 0x8(%rsp), %rcx
movq 0x8(%rcx), %rcx
movl -0x48(%rsp), %edx
addl $0x2, %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jne 0x14360b
movl -0x44(%rsp), %ecx
movq -0x10(%rsp), %rax
movl %ecx, (%rax)
movl $0x0, -0x4(%rsp)
jmp 0x14363b
jmp 0x14360d
movl -0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rsp)
jmp 0x143575
movl $0x52, -0x4(%rsp)
jmp 0x14363b
movl $0x1f, -0x4(%rsp)
jmp 0x14363b
jmp 0x143633
movl $0x0, -0x4(%rsp)
movl -0x4(%rsp), %eax
retq