// File: Ciaxur[P]yagb-emu/src/PPU.cc
// Function: PPU::execute()
void PPU::execute() {
  // Set current LY Value for CPU
  if (memory->read(0xFF40) & 0x80) {
    memory->write(0xFF44, this->LY);
  } else {
    memory->write(0xFF44, 0);
  }

  // Determine LCDMode based on LY State
  if (this->LY < 144) {
    if (cpu->cyclesLeft > 94) {
      this->LCDMode = 2;
    } else if (cpu->cyclesLeft > 22) {
      this->LCDMode = 3;
    } else if (cpu->cyclesLeft < 22) {
      this->LCDMode = 0;
    }
  } else {
    this->LCDMode = 1;
  }

  // Update PPU and CPU state based on both
  //  CPU's current States
  if (cpu->cyclesLeft <= 0) { // End of current scanline
    if (this->LY == 143) {
      // VBlank Area
      uint8_t IF = memory->read(0xFF0F);
      IF |= 0x01;
      memory->write(0xFF0F, IF);

      this->LY = 144;
      this->currentFrame++;
      cpu->cyclesLeft += 114;   // Account for Extra Cycles Taken
    } else {
      this->LY = (this->LY + 1) % 154;
      cpu->cyclesLeft += 114;
    }
  }

  // Execute CPU
  cpu->execute();

  // TODO: Perform PPU functions based on current LCD Mode
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x18(%rbp)
movq 0x10(%rax), %rdi
movl $0xff40, %esi           # imm = 0xFF40
callq 0xbc0c0
movzbl %al, %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0xbd0a7
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdi
movl $0xff44, %esi           # imm = 0xFF44
movzbl 0x20(%rax), %edx
callq 0xbc150
jmp 0xbd0bb
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdi
movl $0xff44, %esi           # imm = 0xFF44
xorl %edx, %edx
callq 0xbc150
movq -0x18(%rbp), %rax
movzbl 0x20(%rax), %eax
cmpl $0x90, %eax
jge 0xbd113
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
cmpl $0x5e, 0x8(%rax)
jle 0xbd0e1
movq -0x18(%rbp), %rax
movb $0x2, (%rax)
jmp 0xbd111
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
cmpl $0x16, 0x8(%rax)
jle 0xbd0f8
movq -0x18(%rbp), %rax
movb $0x3, (%rax)
jmp 0xbd10f
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
cmpl $0x16, 0x8(%rax)
jge 0xbd10d
movq -0x18(%rbp), %rax
movb $0x0, (%rax)
jmp 0xbd10f
jmp 0xbd111
jmp 0xbd11a
movq -0x18(%rbp), %rax
movb $0x1, (%rax)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
cmpl $0x0, 0x8(%rax)
jg 0xbd1c0
movq -0x18(%rbp), %rax
movzbl 0x20(%rax), %eax
cmpl $0x8f, %eax
jne 0xbd195
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdi
movl $0xff0f, %esi           # imm = 0xFF0F
callq 0xbc0c0
movb %al, %cl
movq -0x18(%rbp), %rax
movb %cl, -0x9(%rbp)
movzbl -0x9(%rbp), %ecx
orl $0x1, %ecx
movb %cl, -0x9(%rbp)
movq 0x10(%rax), %rdi
movl $0xff0f, %esi           # imm = 0xFF0F
movzbl -0x9(%rbp), %edx
callq 0xbc150
movq -0x18(%rbp), %rax
movb $-0x70, 0x20(%rax)
movq 0x8(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x8(%rax)
movq 0x18(%rax), %rax
movl 0x8(%rax), %ecx
addl $0x72, %ecx
movl %ecx, 0x8(%rax)
jmp 0xbd1be
movq -0x18(%rbp), %rax
movzbl 0x20(%rax), %eax
addl $0x1, %eax
movl $0x9a, %ecx
cltd
idivl %ecx
movq -0x18(%rbp), %rax
movb %dl, %cl
movb %cl, 0x20(%rax)
movq 0x18(%rax), %rax
movl 0x8(%rax), %ecx
addl $0x72, %ecx
movl %ecx, 0x8(%rax)
jmp 0xbd1c0
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x4c0a0
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)