// File: /workspace/github_cpp_makefile_star2_O2/timothyqiu[P]ssoaag/bitmap.cc
// Function: Bitmap::LoadUncompressedPixelData(BITMAPFILEHEADER const*, BITMAPINFOHEADER const*)
bool Bitmap::LoadUncompressedPixelData(BITMAPFILEHEADER const *bf,
                                       BITMAPINFOHEADER const *bi)
{
    assert(bi->biCompression == BI_RGB);

    /*
     * BI_RGB Pixel Format (R.G.B.A.X)
     *
     *        before V3  after V3
     * 16bpp  5.5.5.0.0  5.5.5.[0-1].[0-1]
     * 24bpp  8.8.8.0.0  8.8.8.0.0
     * 32bpp  8.8.8.0.0  8.8.8.[0-8].[0-8]
     */

    auto w = this->width_;
    auto h = this->height_;

    // width and height of BI_RGB bitmaps can be negative if flipped
    bool flip_x = (w != bi->biWidth );
    bool flip_y = (h != bi->biHeight);

    // for BI_RGB, color table is immediately after the info header
    auto *palette = reinterpret_cast<uint32_t const *>(
            reinterpret_cast<uint8_t const *>(bf) +
            sizeof(BITMAPFILEHEADER) +
            bi->biSize);

    // bitmap pixel data
    auto *raw = reinterpret_cast<uint8_t const *>(bf) + bf->bfOffBits;

    // echo row is rounded up to a multiple of 4 bytes by padding
    auto row_size = (bi->biBitCount * w + 31) / 32 * 4;

    // TODO: find a way to remove the switch..case
    switch (bi->biBitCount) {
    case 1: case 4: case 8: // these are all paletted image
        {
            auto ppb = 8 / bi->biBitCount;  // pixel per byte
            for (int y = 0; y < h; y++) {
                auto *line_r = raw + row_size * y;
                auto *line_w = this->pixels_ + w * (flip_y ? y : (h - 1 - y));
                for (int x = 0; x < w; x++) {
                    auto *pixel_r = line_r + x / ppb;
                    auto *pixel_w = line_w + (flip_x ? w - 1 - x : x);

                    // TODO: make the point clearer?
                    uint8_t mask = ((1 << bi->biBitCount) - 1);
                    auto shift = (ppb - 1 - (x % ppb)) * bi->biBitCount;
                    auto index = ((*pixel_r) >> shift) & mask;
                    auto *color = reinterpret_cast<uint8_t const *>(palette + index);

                    uint8_t b = color[0];
                    uint8_t g = color[1];
                    uint8_t r = color[2];

                    *pixel_w = Bitmap::MakeColor(0xFF, r, g, b);
                }
            }
        }
        break;

    case 16:    // 1555 for uncompressed. ignore any alpha channel(bit)
        for (int y = 0; y < h; y++) {
            auto *line_r = raw + row_size * y;
            auto *line_w = this->pixels_ + w * (flip_y ? y : (h - 1 - y));
            for (int x = 0; x < w; x++) {
                auto *pixel_r = line_r + x * bi->biBitCount / 8;
                auto *pixel_w = line_w + (flip_x ? w - 1 - x : x);

                auto *color = pixel_r;

                // TODO: fix the ugly code :(
                uint8_t b = (((color[0] & 0x1F) << 0)                         ) * 255 / 31;
                uint8_t g = (((color[1] & 0x03) << 3) | (color[0] >> 5 & 0x07)) * 255 / 31;
                uint8_t r = (                           (color[1] >> 2 & 0x1F)) * 255 / 31;

                *pixel_w = Bitmap::MakeColor(0xFF, r, g, b);
            }
        }
        break;

    case 24:
    case 32:    // alpha channel unsupported
        for (int y = 0; y < h; y++) {
            auto *line_r = raw + row_size * y;
            auto *line_w = this->pixels_ + w * (flip_y ? y : (h - 1 - y));
            for (int x = 0; x < w; x++) {
                auto *pixel_r = line_r + x * bi->biBitCount / 8;
                auto *pixel_w = line_w + (flip_x ? w - 1 - x : x);

                auto *color = pixel_r;

                uint8_t b = color[0];
                uint8_t g = color[1];
                uint8_t r = color[2];

                *pixel_w = Bitmap::MakeColor(0xFF, r, g, b);
            }
        }
        break;

    default:
        this->error_type_ = kUnsupportedBitmap;
        this->error_description_ = "Color depth not supported";
        return false;
    }

    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
cmpl $0x0, 0x10(%rdx)
jne 0x347f
movq %rdx, %rcx
movl (%rdi), %r9d
movzwl 0xe(%rdx), %r8d
movl %r9d, %eax
imull %r8d, %eax
addl $0x1f, %eax
pushq $0x20
popq %r10
cltd
idivl %r10d
cmpq $0x20, %r8
ja 0x3464
movl %eax, %edx
movl 0x4(%rdi), %r14d
movl 0x4(%rcx), %r11d
movl 0x8(%rcx), %eax
movl %eax, (%rsp)
movl 0xa(%rsi), %eax
addq %rsi, %rax
movq %rax, 0x30(%rsp)
shll $0x2, %edx
movl $0x112, %eax            # imm = 0x112
btq %r8, %rax
movl %r14d, 0x4(%rsp)
jb 0x3225
movabsq $0x101000000, %rax      # imm = 0x101000000
btq %r8, %rax
jae 0x331b
movq 0x8(%rdi), %rax
movq %rax, 0x10(%rsp)
xorl %ecx, %ecx
testl %r9d, %r9d
movl $0x0, %esi
cmovgl %r9d, %esi
movslq %edx, %rax
movq %rax, 0x8(%rsp)
testl %r14d, %r14d
movl $0x0, %edi
cmovgl %r14d, %edi
leal -0x1(%r9), %eax
cmpq %rdi, %rcx
je 0x3453
movq %rcx, %rbx
imulq 0x8(%rsp), %rbx
addq 0x30(%rsp), %rbx
movl %ecx, %ebp
notl %ebp
addl %r14d, %ebp
cmpl (%rsp), %r14d
cmovnel %ecx, %ebp
imull %r9d, %ebp
movslq %ebp, %r14
movq 0x10(%rsp), %rdx
leaq (%rdx,%r14,4), %r14
xorl %ebp, %ebp
movl %eax, %r10d
xorl %r12d, %r12d
cmpl %r12d, %esi
je 0x3218
movl %ebp, %r13d
shrl $0x3, %r13d
cmpl %r11d, %r9d
movl %r10d, %r15d
cmovel %r12d, %r15d
movslq %r15d, %r15
movzbl (%rbx,%r13), %edx
movzwl 0x1(%rbx,%r13), %r13d
shll $0x8, %r13d
orl %edx, %r13d
orl $0xff000000, %r13d      # imm = 0xFF000000
movl %r13d, (%r14,%r15,4)
incl %r12d
decl %r10d
addl %r8d, %ebp
jmp 0x31d7
incq %rcx
movl 0x4(%rsp), %r14d
jmp 0x319a
movl (%rcx), %ecx
movb $0x8, %al
movzbl %al, %eax
divb %r8b
addq %rcx, %rsi
addq $0xe, %rsi
movzbl %al, %r15d
movq 0x8(%rdi), %rax
movq %rax, 0x28(%rsp)
pushq $-0x1
popq %rax
movl %r8d, %ecx
shll %cl, %eax
notl %eax
movzbl %al, %ebp
xorl %ecx, %ecx
testl %r9d, %r9d
movl $0x0, %ebx
cmovgl %r9d, %ebx
movslq %edx, %rax
movq %rax, 0x20(%rsp)
testl %r14d, %r14d
movl $0x0, %eax
cmovgl %r14d, %eax
movq %rax, 0x8(%rsp)
leal -0x1(%r9), %eax
movl %eax, 0x18(%rsp)
cmpq 0x8(%rsp), %rcx
je 0x3453
movq %rcx, %r10
imulq 0x20(%rsp), %r10
addq 0x30(%rsp), %r10
movl %ecx, %eax
notl %eax
addl %r14d, %eax
cmpl (%rsp), %r14d
movq %rcx, 0x10(%rsp)
cmovnel %ecx, %eax
imull %r9d, %eax
cltq
movq 0x28(%rsp), %rcx
leaq (%rcx,%rax,4), %r14
xorl %edi, %edi
movl 0x18(%rsp), %r12d
cmpl %edi, %ebx
je 0x3309
movl %edi, %eax
xorl %edx, %edx
divl %r15d
cmpl %r11d, %r9d
movl %r12d, %ecx
cmovel %edi, %ecx
movslq %ecx, %r13
notl %edx
leal (%rdx,%r15), %ecx
imull %r8d, %ecx
movzbl (%r10,%rax), %eax
shrl %cl, %eax
andl %ebp, %eax
movzbl (%rsi,%rax,4), %ecx
movzwl 0x1(%rsi,%rax,4), %eax
shll $0x8, %eax
orl %ecx, %eax
orl $0xff000000, %eax       # imm = 0xFF000000
movl %eax, (%r14,%r13,4)
incl %edi
decl %r12d
jmp 0x32c1
movq 0x10(%rsp), %rcx
incq %rcx
movl 0x4(%rsp), %r14d
jmp 0x327f
cmpq $0x10, %r8
jne 0x3464
movq 0x8(%rdi), %rax
movq %rax, 0x18(%rsp)
testl %r9d, %r9d
movl $0x0, %eax
cmovgl %r9d, %eax
movl %eax, 0x10(%rsp)
testl %r14d, %r14d
movl $0x0, %eax
cmovgl %r14d, %eax
movq %rax, 0x20(%rsp)
movslq %edx, %rax
movq %rax, 0x40(%rsp)
leal -0x1(%r9), %eax
movl %eax, 0x3c(%rsp)
movw $0x1f, %di
xorl %ecx, %ecx
cmpq 0x20(%rsp), %rcx
je 0x3453
movq %rcx, %r12
imulq 0x40(%rsp), %r12
addq 0x30(%rsp), %r12
movl %ecx, %eax
notl %eax
addl %r14d, %eax
cmpl (%rsp), %r14d
movq %rcx, 0x28(%rsp)
cmovnel %ecx, %eax
imull %r9d, %eax
cltq
movq 0x18(%rsp), %rcx
leaq (%rcx,%rax,4), %rax
movq %rax, 0x8(%rsp)
xorl %r14d, %r14d
movl 0x3c(%rsp), %r15d
xorl %r10d, %r10d
cmpl %r10d, 0x10(%rsp)
je 0x3441
movl %r14d, %esi
shrl $0x3, %esi
cmpl %r11d, %r9d
movl %r15d, %eax
cmovel %r10d, %eax
movslq %eax, %r13
movzbl (%r12,%rsi), %ebp
movl %ebp, %eax
andl $0x1f, %eax
imull $0xff, %eax, %eax
xorl %edx, %edx
divw %di
movl %eax, %ecx
movzbl 0x1(%r12,%rsi), %ebx
movl %ebx, %eax
andl $0x3, %eax
shrl $0x5, %ebp
leal (%rbp,%rax,8), %eax
imull $0xff, %eax, %eax
xorl %edx, %edx
divw %di
movl %eax, %esi
shrl $0x2, %ebx
andl $0x1f, %ebx
imull $0xff, %ebx, %eax
xorl %edx, %edx
divw %di
shll $0x10, %eax
shll $0x8, %esi
movzwl %si, %edx
orl %eax, %edx
movzwl %cx, %eax
orl %edx, %eax
orl $0xff000000, %eax       # imm = 0xFF000000
movq 0x8(%rsp), %rcx
movl %eax, (%rcx,%r13,4)
incl %r10d
decl %r15d
addl %r8d, %r14d
jmp 0x33b0
movq 0x28(%rsp), %rcx
incq %rcx
movl 0x4(%rsp), %r14d
jmp 0x3365
movb $0x1, %al
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x3, 0x10(%rdi)
addq $0x18, %rdi
leaq 0xff0(%rip), %rsi       # 0x4466
callq 0x2260
xorl %eax, %eax
jmp 0x3455
leaq 0xf5f(%rip), %rdi       # 0x43e5
leaq 0xf74(%rip), %rsi       # 0x4401
leaq 0xf77(%rip), %rcx       # 0x440b
movl $0xf1, %edx
callq 0x2100