// File: RegulusImpact[P]sadboy/src/Graphics/XGPU.cpp
// Function: XGPU::Step(unsigned int)
void XGPU::Step(uint32_t clockStep) {
    Sync();
    clocks += clockStep;

    switch (mode) {
        case GPU_MODE::OAM: // 2
        {
            if (clocks >= 80) {
                clocks = 0;
                mode = GPU_MODE::VRAM;
            }
        }
            break;
        case GPU_MODE::VRAM: // 3
        {
            if (clocks >= 172) {
                clocks = 0;
                mode = GPU_MODE::HBLANK;
                TriggerLCDStat(Utils::BIT_3); // trigger hblank lcdc status interrupt

                RenderScanline();
            }
        }
            break;
        case GPU_MODE::HBLANK: // 0
        {
            if (clocks >= 204) {
                clocks = 0;
                IncrementScanline();

                if (scanline == 143) {
                    mode = GPU_MODE::VBLANK;
                    TriggerVBlank();
                    TriggerLCDStat(Utils::BIT_4); // trigger vblank lcdc status interrupt
                    RenderFrame();
                } else {
                    mode = GPU_MODE::OAM;
                }
            }
        }
            break;
        case GPU_MODE::VBLANK: // 1
        {
            if (clocks >= 456) {
                clocks = 0;

                IncrementScanline();

                if (scanline > 153) {
                    mode = GPU_MODE::OAM;
                    TriggerLCDStat(Utils::BIT_5); // trigger oam-rams lcdc status interrupt

                    ResetScanline();
                    //XFlush(display);
                }
            }
        }
            break;
    }

    SyncMemory();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x20(%rbp)
callq 0x352c0
movq -0x20(%rbp), %rax
movl -0xc(%rbp), %edx
movl 0x8(%rax), %ecx
addl %edx, %ecx
movl %ecx, 0x8(%rax)
movl 0x5a18(%rax), %eax
movq %rax, -0x18(%rbp)
subq $0x3, %rax
ja 0x357e7
movq -0x18(%rbp), %rax
leaq 0x452e(%rip), %rcx      # 0x39be8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x20(%rbp), %rax
cmpl $0x50, 0x8(%rax)
jb 0x356e2
movq -0x20(%rbp), %rax
movl $0x0, 0x8(%rax)
movl $0x3, 0x5a18(%rax)
jmp 0x357e7
movq -0x20(%rbp), %rax
cmpl $0xac, 0x8(%rax)
jb 0x35720
movq -0x20(%rbp), %rdi
movl $0x0, 0x8(%rdi)
movl $0x0, 0x5a18(%rdi)
movl $0x8, %esi
callq 0x35510
movq -0x20(%rbp), %rdi
movq (%rdi), %rax
callq *0xa0(%rax)
jmp 0x357e7
movq -0x20(%rbp), %rax
cmpl $0xcc, 0x8(%rax)
jb 0x35791
movq -0x20(%rbp), %rdi
movl $0x0, 0x8(%rdi)
callq 0x355d0
movq -0x20(%rbp), %rax
movzbl 0x5a1e(%rax), %eax
cmpl $0x8f, %eax
jne 0x35781
movq -0x20(%rbp), %rdi
movl $0x1, 0x5a18(%rdi)
callq 0x35610
movq -0x20(%rbp), %rdi
movl $0x10, %esi
callq 0x35510
movq -0x20(%rbp), %rdi
movq (%rdi), %rax
callq *0x70(%rax)
jmp 0x3578f
movq -0x20(%rbp), %rax
movl $0x2, 0x5a18(%rax)
jmp 0x35791
jmp 0x357e7
movq -0x20(%rbp), %rax
cmpl $0x1c8, 0x8(%rax)       # imm = 0x1C8
jb 0x357e5
movq -0x20(%rbp), %rdi
movl $0x0, 0x8(%rdi)
callq 0x355d0
movq -0x20(%rbp), %rax
movzbl 0x5a1e(%rax), %eax
cmpl $0x99, %eax
jle 0x357e3
movq -0x20(%rbp), %rdi
movl $0x2, 0x5a18(%rdi)
movl $0x20, %esi
callq 0x35510
movq -0x20(%rbp), %rdi
callq 0x355f0
jmp 0x357e5
jmp 0x357e7
movq -0x20(%rbp), %rdi
callq 0x35440
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)