// File: /workspace/github_cpp_makefile_star2_O2/nicoeps[P]NicoGB/src/ppu.cpp
// Function: PPU::update()
void PPU::update() {
    if ((lcdc & 0x80) == 0) {
        totalCycles = 0;
        ly = 0;
        windowCounter = 0;
        stat = (stat & 0xFC) | 0x00;
        stat = (lyc == ly) ? (stat | 0x4) : (stat & ~0x4);
        if (clear) {
            clear = false;
            std::fill_n(writebuffer.begin(), 160*144, getPalette(0)[0]);
            std::fill_n(framebuffer.begin(), 160*144, getPalette(0)[0]);
        }
        return;
    }
    clear = true;

    totalCycles++;

    switch (mode) {
        case 2: // OAM Search
            if (totalCycles >= 20) {
                totalCycles -= 20;
                mode = 3;
                stat = (stat & 0xFC) | 0x03;
            }
            break;

        case 3: // Pixel Transfer
            if (totalCycles >= 43) {
                totalCycles -= 43;
                mode = 0;
                stat = (stat & 0xFC) | 0x00;
                std::fill_n(line.begin(), 160, 0);
                drawBackground();
                drawWindow();
                drawSprites();
            }
            break;

        case 0: // H-Blank
            if (totalCycles >= 51) {
                totalCycles -= 51;
                ++ly;
                if (ly < 144) {
                    mode = 2;
                    stat = (stat & 0xFC) | 0x02;
                } else {
                    mode = 1;
                    stat = (stat & 0xFC) | 0x01;
                    framebuffer.swap(writebuffer);
                    memory.interrupt(0x1);
                }
            }
            break;

        case 1: // V-Blank
            if (totalCycles >= 114) {
                totalCycles -= 114;
                ++ly;
                if (ly > 153) {
                    ly = 0;
                    windowCounter = 0;
                    mode = 2;
                    stat = (stat & 0xFC) | 0x02;
                }
            }
            break;

        default: // Glitched OAM Search
            if (totalCycles >= 19) {
                totalCycles -= 19;
                mode = 3;
                stat = (stat & 0xFC) | 0x03;
            }
            break;
    }

    stat = (lyc == ly) ? (stat | 0x4) : (stat & ~0x4);
    if (((stat & 0x4) && (stat & 0x40))
    || (((stat >> (mode + 3)) & 1) && mode != 0x3)) {
        if (interrupt == false) {
            memory.interrupt(0x2);
            interrupt = true;
        }
    } else {
        interrupt = false;
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
movq 0x28(%rdi), %rax
cmpb $0x0, (%rax)
js 0x6e38
andl $0x0, 0x20(%rbx)
movq 0x48(%rbx), %rax
movb $0x0, (%rax)
andl $0x0, 0x84(%rbx)
movq 0x30(%rbx), %rax
andb $-0x4, (%rax)
movq 0x50(%rbx), %rax
movb (%rax), %al
movq 0x30(%rbx), %rcx
movq 0x48(%rbx), %rdx
cmpb (%rdx), %al
sete %al
movb (%rcx), %dl
andb $-0x5, %dl
shlb $0x2, %al
orb %dl, %al
movb %al, (%rcx)
cmpb $0x1, 0xb8(%rbx)
jne 0x7012
movb $0x0, 0xb8(%rbx)
movq 0x88(%rbx), %r15
movq %rsp, %r14
xorl %r12d, %r12d
movq %r14, %rdi
xorl %edx, %edx
callq 0x701e
movq (%r14), %rax
movl (%rax), %eax
cmpq $0x16800, %r12          # imm = 0x16800
je 0x6ebf
movl %eax, (%r15,%r12)
addq $0x4, %r12
jmp 0x6e21
movb $0x1, 0xb8(%rbx)
movl 0x20(%rbx), %eax
leal 0x1(%rax), %ecx
movl %ecx, 0x20(%rbx)
movzbl 0x80(%rbx), %ecx
cmpq $0x3, %rcx
ja 0x6f81
leaq 0x2d44(%rip), %rdx      # 0x9ba4
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
cmpl $0x32, %eax
jl 0x6fb4
addl $-0x32, %eax
movl %eax, 0x20(%rbx)
movq 0x48(%rbx), %rax
incb (%rax)
movq 0x48(%rbx), %rax
cmpb $-0x71, (%rax)
jbe 0x6f6a
movb $0x1, 0x80(%rbx)
movq 0x30(%rbx), %rax
movb (%rax), %cl
andb $-0x4, %cl
incb %cl
movb %cl, (%rax)
leaq 0x8(%rbx), %rdi
leaq 0x88(%rbx), %rsi
callq 0x7e52
movq (%rbx), %rdi
pushq $0x1
popq %rsi
callq 0x64c0
jmp 0x6fb4
movq %rsp, %rdi
callq 0x5b6e
movq 0x8(%rbx), %r14
movq %rsp, %rbx
xorl %r15d, %r15d
movq %rbx, %rdi
xorl %edx, %edx
callq 0x701e
movq (%rbx), %rax
movl (%rax), %eax
cmpq $0x16800, %r15          # imm = 0x16800
je 0x6ef3
movl %eax, (%r14,%r15)
addq $0x4, %r15
jmp 0x6ee0
movq %rsp, %rdi
callq 0x5b6e
jmp 0x7012
cmpl $0x13, %eax
jl 0x6fb4
addl $-0x13, %eax
jmp 0x6f89
cmpl $0x2a, %eax
jl 0x6fb4
addl $-0x2a, %eax
movl %eax, 0x20(%rbx)
movb $0x0, 0x80(%rbx)
movq 0x30(%rbx), %rax
andb $-0x4, (%rax)
movq 0xa0(%rbx), %rax
xorl %ecx, %ecx
cmpq $0xa0, %rcx
je 0x6f9c
movb $0x0, (%rax,%rcx)
incq %rcx
jmp 0x6f34
cmpl $0x71, %eax
jl 0x6fb4
addl $-0x71, %eax
movl %eax, 0x20(%rbx)
movq 0x48(%rbx), %rax
incb (%rax)
movq 0x48(%rbx), %rax
cmpb $-0x66, (%rax)
jb 0x6fb4
movb $0x0, (%rax)
andl $0x0, 0x84(%rbx)
movb $0x2, 0x80(%rbx)
movq 0x30(%rbx), %rax
movb (%rax), %cl
andb $-0x4, %cl
orb $0x2, %cl
movb %cl, (%rax)
jmp 0x6fb4
cmpl $0x12, %eax
jl 0x6fb4
addl $-0x12, %eax
movl %eax, 0x20(%rbx)
movb $0x3, 0x80(%rbx)
movq 0x30(%rbx), %rax
orb $0x3, (%rax)
jmp 0x6fb4
movq %rbx, %rdi
callq 0x70f8
movq %rbx, %rdi
callq 0x732e
movq %rbx, %rdi
callq 0x752c
movq 0x50(%rbx), %rax
movb (%rax), %al
movq 0x48(%rbx), %rcx
cmpb (%rcx), %al
movq 0x30(%rbx), %rax
sete %cl
movb (%rax), %dl
andb $-0x5, %dl
shlb $0x2, %cl
orb %dl, %cl
movb %cl, (%rax)
movq 0x30(%rbx), %rax
movzbl (%rax), %eax
movl %eax, %ecx
notl %ecx
testb $0x44, %cl
je 0x6ff7
movb 0x80(%rbx), %cl
pushq $0x8
popq %rdx
shll %cl, %edx
cmpb $0x3, %cl
je 0x700e
andl %eax, %edx
je 0x700e
cmpb $0x0, 0x24(%rbx)
jne 0x7012
movq (%rbx), %rdi
pushq $0x2
popq %rsi
callq 0x64c0
movb $0x1, 0x24(%rbx)
jmp 0x7012
movb $0x0, 0x24(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq