// File: 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:
subq $0xb8, %rsp
movq %rdi, 0xb0(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x28(%rax), %rax
movzbl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x11256
movq 0x28(%rsp), %rax
movq 0x48(%rax), %rax
movzbl (%rax), %eax
cmpl $0x90, %eax
jge 0x11251
movq 0x28(%rsp), %rdi
addq $0x88, %rdi
callq 0x13440
movq %rax, %rcx
movq 0x28(%rsp), %rax
movq %rcx, 0xa0(%rsp)
movq 0x48(%rax), %rax
movzbl (%rax), %ecx
shll $0x5, %ecx
movl %ecx, %eax
leal (%rax,%rax,4), %eax
movl %eax, %esi
leaq 0xa0(%rsp), %rdi
callq 0x13600
movq 0x28(%rsp), %rsi
movq %rax, 0xa8(%rsp)
movq 0x58(%rsi), %rax
movzbl (%rax), %edx
leaq 0x88(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x10e60
movq 0x18(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x134d0
movq %rax, %rdx
movq 0xa8(%rsp), %rdi
movl $0xa0, %esi
callq 0x13470
movq %rax, 0x20(%rsp)
jmp 0x11215
movq 0x20(%rsp), %rax
movq %rax, 0x70(%rsp)
leaq 0x88(%rsp), %rdi
callq 0xd450
jmp 0x11251
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
leaq 0x88(%rsp), %rdi
callq 0xd450
jmp 0x115ed
jmp 0x115e5
movq 0x28(%rsp), %rsi
movq 0x28(%rsi), %rax
movzbl (%rax), %edx
andl $0x8, %edx
sarl $0x3, %edx
movl $0x9800, %eax           # imm = 0x9800
movl $0x9c00, %ecx           # imm = 0x9C00
cmpl $0x0, %edx
cmovnel %ecx, %eax
movw %ax, 0x6e(%rsp)
movq 0x28(%rsi), %rax
movzbl (%rax), %edx
andl $0x10, %edx
sarl $0x4, %edx
movl $0x9000, %eax           # imm = 0x9000
movl $0x8000, %ecx           # imm = 0x8000
cmpl $0x0, %edx
cmovnel %ecx, %eax
movw %ax, 0x6c(%rsp)
movq 0x58(%rsi), %rax
leaq 0x50(%rsp), %rdi
movzbl (%rax), %edx
callq 0x10e60
movq 0x28(%rsp), %rcx
movq 0x48(%rcx), %rax
movzbl (%rax), %eax
movq 0x38(%rcx), %rcx
movzbl (%rcx), %ecx
addl %ecx, %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl $0x20, %ecx
cltd
idivl %ecx
movb %dl, %al
movb %al, 0x4f(%rsp)
movl $0x0, 0x48(%rsp)
cmpl $0x15, 0x48(%rsp)
jge 0x115db
movq 0x28(%rsp), %rax
movq 0x40(%rax), %rcx
movzbl (%rcx), %edi
shrl $0x3, %edi
movl 0x48(%rsp), %edx
movl %edi, %ecx
addl %edx, %ecx
movl %edx, %esi
movl %edi, %edx
leal 0x1f(%rdx,%rsi), %esi
testl %ecx, %ecx
movl %ecx, %edx
cmovsl %esi, %edx
andl $0xe0, %edx
subl %edx, %ecx
movb %cl, 0x47(%rsp)
movq (%rax), %rdi
movzwl 0x6e(%rsp), %eax
movzbl 0x4f(%rsp), %ecx
shll $0x5, %ecx
addl %ecx, %eax
movzbl 0x47(%rsp), %ecx
addl %ecx, %eax
movzwl %ax, %esi
callq 0xef80
movb %al, 0x17(%rsp)
jmp 0x11347
movq 0x28(%rsp), %rcx
movb 0x17(%rsp), %al
movb %al, 0x46(%rsp)
movq 0x48(%rcx), %rax
movzbl (%rax), %eax
movq 0x38(%rcx), %rcx
movzbl (%rcx), %ecx
addl %ecx, %eax
movl $0x8, %ecx
cltd
idivl %ecx
movb %dl, %al
movb %al, 0x45(%rsp)
movb $0x0, 0x44(%rsp)
movb $0x0, 0x43(%rsp)
movzwl 0x6c(%rsp), %eax
cmpl $0x8000, %eax           # imm = 0x8000
jne 0x11424
movq 0x28(%rsp), %rax
movq (%rax), %rdi
movzwl 0x6c(%rsp), %edx
movzbl 0x46(%rsp), %eax
shll $0x4, %eax
addl %eax, %edx
movzbl 0x45(%rsp), %eax
movl %eax, %ecx
movl %edx, %eax
leal (%rax,%rcx,2), %eax
movzwl %ax, %esi
callq 0xef80
movb %al, 0x16(%rsp)
jmp 0x113bd
movq 0x28(%rsp), %rax
movb 0x16(%rsp), %cl
movb %cl, 0x44(%rsp)
movq (%rax), %rdi
movzwl 0x6c(%rsp), %edx
movzbl 0x46(%rsp), %eax
shll $0x4, %eax
addl %eax, %edx
movzbl 0x45(%rsp), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x1(%rax,%rcx,2), %eax
movzwl %ax, %esi
callq 0xef80
movb %al, 0x15(%rsp)
jmp 0x113f7
movb 0x15(%rsp), %al
movb %al, 0x43(%rsp)
jmp 0x11497
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
leaq 0x50(%rsp), %rdi
callq 0xd450
jmp 0x115ed
movq 0x28(%rsp), %rax
movq (%rax), %rdi
movzwl 0x6c(%rsp), %edx
movsbl 0x46(%rsp), %eax
shll $0x4, %eax
addl %eax, %edx
movzbl 0x45(%rsp), %eax
movl %eax, %ecx
movl %edx, %eax
leal (%rax,%rcx,2), %eax
movzwl %ax, %esi
callq 0xef80
movb %al, 0x14(%rsp)
jmp 0x11455
movq 0x28(%rsp), %rax
movb 0x14(%rsp), %cl
movb %cl, 0x44(%rsp)
movq (%rax), %rdi
movzwl 0x6c(%rsp), %edx
movsbl 0x46(%rsp), %eax
shll $0x4, %eax
addl %eax, %edx
movzbl 0x45(%rsp), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x1(%rax,%rcx,2), %eax
movzwl %ax, %esi
callq 0xef80
movb %al, 0x13(%rsp)
jmp 0x1148f
movb 0x13(%rsp), %al
movb %al, 0x43(%rsp)
movb $0x0, 0x42(%rsp)
movzbl 0x42(%rsp), %eax
cmpl $0x8, %eax
jge 0x115c9
movzbl 0x44(%rsp), %eax
movzbl 0x42(%rsp), %edx
movl $0x7, %ecx
subl %edx, %ecx
sarl %cl, %eax
andl $0x1, %eax
movb %al, 0x41(%rsp)
movzbl 0x43(%rsp), %eax
movzbl 0x42(%rsp), %edx
movl $0x7, %ecx
subl %edx, %ecx
sarl %cl, %eax
andl $0x1, %eax
movb %al, 0x40(%rsp)
movzbl 0x40(%rsp), %eax
shll %eax
movzbl 0x41(%rsp), %ecx
orl %ecx, %eax
movb %al, 0x3f(%rsp)
movzbl 0x3f(%rsp), %eax
movl %eax, %esi
leaq 0x50(%rsp), %rdi
callq 0x134d0
movq %rax, %rcx
movq 0x28(%rsp), %rax
movl (%rcx), %ecx
movl %ecx, 0x38(%rsp)
movl 0x48(%rsp), %ecx
shll $0x3, %ecx
movzbl 0x42(%rsp), %edx
addl %edx, %ecx
movl %ecx, 0xc(%rsp)
movq 0x40(%rax), %rax
movzbl (%rax), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl 0xc(%rsp), %eax
subl %edx, %eax
movl %eax, 0x34(%rsp)
cmpl $0x0, 0x34(%rsp)
jl 0x115b8
movq 0x28(%rsp), %rax
movq 0x48(%rax), %rax
movzbl (%rax), %eax
cmpl $0x90, %eax
jge 0x115b8
cmpl $0xa0, 0x34(%rsp)
jge 0x115b8
movq 0x28(%rsp), %rax
movl 0x38(%rsp), %ecx
movl %ecx, 0x4(%rsp)
movq %rax, %rdi
addq $0x88, %rdi
movq 0x48(%rax), %rax
movzbl (%rax), %eax
imull $0xa0, %eax, %eax
addl 0x34(%rsp), %eax
movslq %eax, %rsi
callq 0x134d0
movl 0x4(%rsp), %ecx
movq 0x28(%rsp), %rdi
movl %ecx, (%rax)
movb 0x3f(%rsp), %al
movb %al, 0xb(%rsp)
addq $0xa0, %rdi
movslq 0x34(%rsp), %rsi
callq 0x40f0
movb 0xb(%rsp), %cl
movb %cl, (%rax)
jmp 0x115ba
movb 0x42(%rsp), %al
addb $0x1, %al
movb %al, 0x42(%rsp)
jmp 0x1149c
jmp 0x115cb
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
jmp 0x112e3
leaq 0x50(%rsp), %rdi
callq 0xd450
addq $0xb8, %rsp
retq
movq 0x80(%rsp), %rdi
callq 0x33d0
nopw (%rax,%rax)