// File: /workspace/github_cpp_makefile_star2_O3/nicoeps[P]NicoGB/src/ppu.cpp
// Function: PPU::drawBackground()
void PPU::drawBackground() {
    if (!(lcdc & 0x1)) {
        if (ly < 144) {
            std::fill_n(writebuffer.begin() + ly * 160, 160, getPalette(bgp)[0]);
        }
        return;
    }
    uint16_t tileSelect = ((lcdc & 0x8) >> 3) ? 0x9C00 : 0x9800;
    uint16_t tileData = ((lcdc & 0x10) >> 4) ? 0x8000 : 0x9000;
    std::vector<uint32_t> col = getPalette(bgp);

    uint8_t tileY = ((ly + scy) / 8) % 32;
    for (int i = 0; i < 21; ++i) {
        uint8_t tileX = (scx / 8 + i) % 32;

        uint8_t tileNumber = memory.read(tileSelect + (tileY * 32) + tileX);
        uint8_t pixelY = (ly + scy) % 8;

        uint8_t byte1 = 0;
        uint8_t byte2 = 0;
        if (tileData == 0x8000) {
            byte1 = memory.read(tileData + tileNumber * 16 + (pixelY * 2));
            byte2 = memory.read(tileData + tileNumber * 16 + (pixelY * 2) + 1);
        } else {
            byte1 = memory.read(tileData + ((int8_t) (tileNumber) * 16) + (pixelY * 2));
            byte2 = memory.read(tileData + ((int8_t) (tileNumber) * 16) + (pixelY * 2) + 1);
        }

        for (uint8_t pixelX = 0; pixelX < 8; ++pixelX) {
            uint8_t bit1 = (byte1 >> (7 - pixelX)) & 0x1;
            uint8_t bit2 = (byte2 >> (7 - pixelX)) & 0x1;
            uint8_t color = (bit2 << 1) | bit1;
            uint32_t pixel = col[color];

            int X = i * 8 + pixelX - (scx % 8);
            if (X >= 0 && ly < 144 && X < 160) {
                writebuffer[ly * 160 + X] = pixel;
                line[X] = color;
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rdi, %rbx
movq 0x28(%rdi), %rax
movzbl (%rax), %eax
testb $0x1, %al
jne 0x8005
movq 0x48(%rbx), %rax
movzbl (%rax), %eax
cmpq $0x8f, %rax
ja 0x81a5
leaq (%rax,%rax,4), %r14
shll $0x7, %r14d
addq 0x88(%rbx), %r14
movq 0x58(%rbx), %rax
movzbl (%rax), %edx
leaq 0x10(%rsp), %rbx
movq %rbx, %rdi
callq 0x7e84
movq (%rbx), %rdi
movd (%rdi), %xmm0
pshufd $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
xorl %eax, %eax
movdqu %xmm0, (%r14,%rax,4)
addq $0x4, %rax
cmpq $0xa0, %rax
jne 0x7fee
jmp 0x8198
movl %eax, 0x8(%rsp)
movl %eax, %r14d
andl $0x8, %r14d
movq 0x58(%rbx), %rax
movzbl (%rax), %edx
leaq 0x10(%rsp), %rdi
callq 0x7e84
movq 0x38(%rbx), %rax
movq 0x48(%rbx), %rcx
movb (%rax), %al
addb (%rcx), %al
shrb $0x3, %al
shll $0x7, %r14d
movzbl %al, %eax
shll $0x5, %eax
addl %r14d, %eax
addl $0x9800, %eax           # imm = 0x9800
movl %eax, 0xc(%rsp)
xorl %r12d, %r12d
xorl %r13d, %r13d
movq (%rbx), %rdi
movq 0x40(%rbx), %rax
movzbl (%rax), %eax
shrl $0x3, %eax
addl %r13d, %eax
andl $0x1f, %eax
orl 0xc(%rsp), %eax
movzwl %ax, %esi
callq 0x7022
movq 0x48(%rbx), %rcx
movq 0x38(%rbx), %rdx
movb (%rdx), %dl
addb (%rcx), %dl
movq (%rbx), %rdi
andb $0x7, %dl
movzbl %dl, %r14d
testb $0x10, 0x8(%rsp)
jne 0x80b6
movsbl %al, %eax
shll $0x4, %eax
leal (%rax,%r14,2), %r14d
addl $0xffff9000, %r14d      # imm = 0xFFFF9000
movzwl %r14w, %esi
callq 0x7022
movl %eax, %ebp
movq (%rbx), %rdi
orl $0x1, %r14d
movzwl %r14w, %esi
callq 0x7022
jmp 0x80e4
movzbl %al, %r15d
shll $0x4, %r15d
leal (%r15,%r14,2), %esi
addl $0x8000, %esi           # imm = 0x8000
callq 0x7022
movl %eax, %ebp
leal (%r15,%r14,2), %eax
movq (%rbx), %rdi
movzwl %ax, %esi
orl $0x8001, %esi           # imm = 0x8001
callq 0x7022
movzbl %bpl, %edx
movzbl %al, %eax
movl $0x7, %ecx
movl %r12d, %esi
xorl %r9d, %r9d
btl %ecx, %edx
setb %r11b
movl %eax, %r10d
shrl %cl, %r10d
movq 0x40(%rbx), %rdi
movzbl (%rdi), %r8d
andl $0x7, %r8d
movl %esi, %edi
subl %r8d, %edi
js 0x8172
movq 0x48(%rbx), %r14
movzbl (%r14), %r14d
cmpl $0x90, %r14d
setae %bpl
cmpl $0xa0, %edi
setae %r15b
orb %bpl, %r15b
jne 0x8172
movb %r11b, %r9b
andl $0x1, %r10d
leal (%r9,%r10,2), %r9d
movq 0x10(%rsp), %r10
movl (%r10,%r9,4), %r10d
leal (%r14,%r14,4), %r11d
shll $0x5, %r11d
addl %esi, %r11d
subl %r8d, %r11d
movq 0x88(%rbx), %r8
movl %r10d, (%r8,%r11,4)
movl %edi, %edi
movq 0xa0(%rbx), %r8
movb %r9b, (%r8,%rdi)
incl %esi
addl $-0x1, %ecx
jb 0x80f3
incl %r13d
addl $0x8, %r12d
cmpl $0x15, %r13d
jne 0x804c
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x81a5
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x21c0
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x81b6
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x81d0
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x21c0
movq %rbx, %rdi
callq 0x2270