// File: donfreiday[P]gb/gpu.cpp
// Function: GPU::renderSprites()
void GPU::renderSprites() {
  u8 ySize = bitTest(mmu->memory[LCDC], LCDC_OBJ_SIZE) ? 16 : 8;
  for (u8 sprite = 0; sprite < 40; sprite++) {
    u8 index = sprite * 4;  // each oam attribute entry is 4 bytes
    u8 yPos = mmu->memory[OAM_ATTRIB + index] - 16;
    u8 xPos = mmu->memory[OAM_ATTRIB + index + 1] - 8;
    u8 tileLocation = mmu->memory[OAM_ATTRIB + index + 2];
    u8 attributes = mmu->memory[OAM_ATTRIB + index + 3];
    bool yFlip = bitTest(attributes, 6);
    bool xFlip = bitTest(attributes, 5);

    if (OAM_ATTRIB + index == 0xFe00) {
      if (xPos != prevXpos) {
        prevXpos = xPos;
      }
    }

    // Is sprite located on the current scanline?
    if (scanline >= yPos && scanline < (yPos + ySize)) {
      u8 line = scanline - yPos;
      if (yFlip) {
        line -= ySize;
        line *= -1;
      }
      line *= 2;

      u16 tileData = (OAM_DATA + (tileLocation * 16)) + line;
      u8 data1 = mmu->memory[tileData];
      u8 data2 = mmu->memory[tileData + 1];

      for (int tilePixel = 7; tilePixel >= 0; tilePixel--) {
        int colorBit = tilePixel;
        if (xFlip) {
          colorBit -= 7;
          colorBit *= -1;
        }

        u8 colorID = 0;
        if (data2 & (1 << colorBit)) {
          colorID |= 2;
        }
        if (data1 & (1 << colorBit)) {
          colorID |= 1;
        }

        u16 paletteAddress = bitTest(attributes, 4) ? 0xFF49 : 0xFF48;
        COLOR color = paletteLookup(colorID, paletteAddress);

        // white is transparent
        if (color == WHITE) {
          continue;
        }

        u8 red = 0, green = 0, blue = 0;
        switch (color) {
          case WHITE:
            red = 255;
            green = 255;
            blue = 255;
            break;
          case LIGHT_GRAY:
            red = 0xCC;
            green = 0xCC;
            blue = 0xCC;
            break;
          case DARK_GRAY:
            red = 0x77;
            green = 0x77;
            blue = 0x77;
            break;
          case BLACK:
            break;  // -Wswitch warning prevention
        }

        u8 pixel = xPos - tilePixel;
        pixel += 7;

        screenData[scanline][pixel][0] = red;
        screenData[scanline][pixel][1] = green;
        screenData[scanline][pixel][2] = blue;
      }
    }
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x38(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movl $0xff40, %esi           # imm = 0xFF40
callq 0x4f3d0
movl $0x2, %esi
movzbl (%rax), %edi
callq 0x4e910
movb %al, %dl
movl $0x8, %eax
movl $0x10, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
movb %al, -0x9(%rbp)
movb $0x0, -0xa(%rbp)
movzbl -0xa(%rbp), %eax
cmpl $0x28, %eax
jge 0x51e42
movq -0x38(%rbp), %rax
movzbl -0xa(%rbp), %ecx
shll $0x2, %ecx
movb %cl, -0xb(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movzbl -0xb(%rbp), %eax
addl $0xfe00, %eax           # imm = 0xFE00
movslq %eax, %rsi
callq 0x4f3d0
movq %rax, %rcx
movq -0x38(%rbp), %rax
movzbl (%rcx), %ecx
subl $0x10, %ecx
movb %cl, -0xc(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movzbl -0xb(%rbp), %eax
addl $0xfe00, %eax           # imm = 0xFE00
addl $0x1, %eax
movslq %eax, %rsi
callq 0x4f3d0
movq %rax, %rcx
movq -0x38(%rbp), %rax
movzbl (%rcx), %ecx
subl $0x8, %ecx
movb %cl, -0xd(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movzbl -0xb(%rbp), %eax
addl $0xfe00, %eax           # imm = 0xFE00
addl $0x2, %eax
movslq %eax, %rsi
callq 0x4f3d0
movq %rax, %rcx
movq -0x38(%rbp), %rax
movb (%rcx), %cl
movb %cl, -0xe(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movzbl -0xb(%rbp), %eax
addl $0xfe00, %eax           # imm = 0xFE00
addl $0x3, %eax
movslq %eax, %rsi
callq 0x4f3d0
movb (%rax), %al
movb %al, -0xf(%rbp)
movl $0x6, %esi
movzbl -0xf(%rbp), %edi
callq 0x4e910
andb $0x1, %al
movb %al, -0x10(%rbp)
movl $0x5, %esi
movzbl -0xf(%rbp), %edi
callq 0x4e910
andb $0x1, %al
movb %al, -0x11(%rbp)
movzbl -0xb(%rbp), %eax
addl $0xfe00, %eax           # imm = 0xFE00
cmpl $0xfe00, %eax           # imm = 0xFE00
jne 0x51bd0
movzbl -0xd(%rbp), %eax
movzbl 0x32267(%rip), %ecx     # 0x83e28
cmpl %ecx, %eax
je 0x51bce
movb -0xd(%rbp), %al
movb %al, 0x3225a(%rip)      # 0x83e28
jmp 0x51bd0
movq -0x38(%rbp), %rax
movzbl 0x10(%rax), %eax
movzbl -0xc(%rbp), %ecx
cmpl %ecx, %eax
jl 0x51e33
movq -0x38(%rbp), %rax
movzbl 0x10(%rax), %eax
movzbl -0xc(%rbp), %ecx
movzbl -0x9(%rbp), %edx
addl %edx, %ecx
cmpl %ecx, %eax
jge 0x51e33
movq -0x38(%rbp), %rax
movzbl 0x10(%rax), %eax
movzbl -0xc(%rbp), %ecx
subl %ecx, %eax
movb %al, -0x12(%rbp)
testb $0x1, -0x10(%rbp)
je 0x51c2c
movzbl -0x9(%rbp), %ecx
movzbl -0x12(%rbp), %eax
subl %ecx, %eax
movb %al, -0x12(%rbp)
movzbl -0x12(%rbp), %eax
imull $-0x1, %eax, %eax
movb %al, -0x12(%rbp)
movq -0x38(%rbp), %rax
movzbl -0x12(%rbp), %ecx
shll %ecx
movb %cl, -0x12(%rbp)
movzbl -0xe(%rbp), %ecx
shll $0x4, %ecx
addl $0x8000, %ecx           # imm = 0x8000
movzbl -0x12(%rbp), %edx
addl %edx, %ecx
movw %cx, -0x14(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movzwl -0x14(%rbp), %eax
movl %eax, %esi
callq 0x4f3d0
movq %rax, %rcx
movq -0x38(%rbp), %rax
movb (%rcx), %cl
movb %cl, -0x15(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movzwl -0x14(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x4f3d0
movb (%rax), %al
movb %al, -0x16(%rbp)
movl $0x7, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
jl 0x51e31
movl -0x1c(%rbp), %eax
movl %eax, -0x20(%rbp)
testb $0x1, -0x11(%rbp)
je 0x51cb6
movl -0x20(%rbp), %eax
subl $0x7, %eax
movl %eax, -0x20(%rbp)
imull $-0x1, -0x20(%rbp), %eax
movl %eax, -0x20(%rbp)
movb $0x0, -0x21(%rbp)
movzbl -0x16(%rbp), %eax
movl -0x20(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x51cdb
movzbl -0x21(%rbp), %eax
orl $0x2, %eax
movb %al, -0x21(%rbp)
movzbl -0x15(%rbp), %eax
movl -0x20(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x51cfc
movzbl -0x21(%rbp), %eax
orl $0x1, %eax
movb %al, -0x21(%rbp)
movl $0x4, %esi
movzbl -0xf(%rbp), %edi
callq 0x4e910
movq -0x38(%rbp), %rdi
movb %al, %dl
movl $0xff48, %eax           # imm = 0xFF48
movl $0xff49, %ecx           # imm = 0xFF49
testb $0x1, %dl
cmovnel %ecx, %eax
movw %ax, -0x24(%rbp)
movb -0x21(%rbp), %al
movzbl %al, %esi
movzwl -0x24(%rbp), %edx
callq 0x51e50
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
jne 0x51d41
jmp 0x51e23
movb $0x0, -0x29(%rbp)
movb $0x0, -0x2a(%rbp)
movb $0x0, -0x2b(%rbp)
movl -0x28(%rbp), %eax
movq %rax, -0x40(%rbp)
subq $0x3, %rax
ja 0x51d9a
movq -0x40(%rbp), %rax
leaq 0x1431f(%rip), %rcx     # 0x66084
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movb $-0x1, -0x29(%rbp)
movb $-0x1, -0x2a(%rbp)
movb $-0x1, -0x2b(%rbp)
jmp 0x51d9a
movb $-0x34, -0x29(%rbp)
movb $-0x34, -0x2a(%rbp)
movb $-0x34, -0x2b(%rbp)
jmp 0x51d9a
movb $0x77, -0x29(%rbp)
movb $0x77, -0x2a(%rbp)
movb $0x77, -0x2b(%rbp)
jmp 0x51d9a
jmp 0x51d9a
movq -0x38(%rbp), %rdx
movzbl -0xd(%rbp), %eax
subl -0x1c(%rbp), %eax
movb %al, -0x2c(%rbp)
movzbl -0x2c(%rbp), %eax
addl $0x7, %eax
movb %al, -0x2c(%rbp)
movb -0x29(%rbp), %cl
movq %rdx, %rax
addq $0x1d, %rax
movzbl 0x10(%rdx), %esi
imulq $0x1e0, %rsi, %rsi      # imm = 0x1E0
addq %rsi, %rax
movzbl -0x2c(%rbp), %esi
imulq $0x3, %rsi, %rsi
addq %rsi, %rax
movb %cl, (%rax)
movb -0x2a(%rbp), %cl
movq %rdx, %rax
addq $0x1d, %rax
movzbl 0x10(%rdx), %esi
imulq $0x1e0, %rsi, %rsi      # imm = 0x1E0
addq %rsi, %rax
movzbl -0x2c(%rbp), %esi
imulq $0x3, %rsi, %rsi
addq %rsi, %rax
movb %cl, 0x1(%rax)
movb -0x2b(%rbp), %cl
movq %rdx, %rax
addq $0x1d, %rax
movzbl 0x10(%rdx), %edx
imulq $0x1e0, %rdx, %rdx      # imm = 0x1E0
addq %rdx, %rax
movzbl -0x2c(%rbp), %edx
imulq $0x3, %rdx, %rdx
addq %rdx, %rax
movb %cl, 0x2(%rax)
movl -0x1c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x51c90
jmp 0x51e33
jmp 0x51e35
movb -0xa(%rbp), %al
addb $0x1, %al
movb %al, -0xa(%rbp)
jmp 0x51acb
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)