// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq (%rdi), %rax
movq %rax, -0x50(%rbp)
movq 0x8(%rax), %rax
movb 0xff40(%rax), %al
andb $0x4, %al
shrb $0x2, %al
movzbl 0x10(%rdi), %ecx
movb 0x279ef(%rip), %dl      # 0x5fde8
movb %dl, -0x29(%rbp)
movzbl %al, %eax
leal 0x8(,%rax,8), %eax
movl %eax, -0x30(%rbp)
movq %rdi, -0x68(%rbp)
leaq 0x1d(%rdi), %rax
xorl %edi, %edi
movq %rcx, -0x40(%rbp)
imulq $0x1e0, %rcx, %r12      # imm = 0x1E0
addq %rax, %r12
movq -0x50(%rbp), %rax
movq 0x8(%rax), %rcx
movb 0xfe00(%rcx,%rdi,4), %sil
movb 0xfe01(%rcx,%rdi,4), %al
movzbl 0xfe02(%rcx,%rdi,4), %edx
movzbl 0xfe03(%rcx,%rdi,4), %r8d
movl %r8d, -0x34(%rbp)
movq %rdi, -0x58(%rbp)
testq %rdi, %rdi
jne 0x3846a
leal -0x8(%rax), %edi
cmpb -0x29(%rbp), %dil
je 0x3846a
movb %dil, 0x27982(%rip)     # 0x5fde8
movb %dil, -0x29(%rbp)
addb $-0x10, %sil
cmpb %sil, -0x40(%rbp)
jb 0x38560
movzbl %sil, %edi
addl -0x30(%rbp), %edi
cmpl -0x40(%rbp), %edi
jbe 0x38560
movq -0x40(%rbp), %rdi
subb %sil, %dil
movl -0x30(%rbp), %esi
subb %dil, %sil
movl -0x34(%rbp), %r8d
testb $0x40, %r8b
movzbl %dil, %edi
movzbl %sil, %esi
cmovel %edi, %esi
addb %sil, %sil
shll $0x4, %edx
movzbl %sil, %esi
addq %rdx, %rsi
movzbl 0x8000(%rcx,%rsi), %edx
movl %edx, -0x44(%rbp)
movzbl 0x8001(%rcx,%rsi), %ebx
movl %r8d, %ecx
andl $0x10, %ecx
cmpl $0x1, %ecx
movw $0xff49, %cx            # imm = 0xFF49
sbbw $0x0, %cx
addb $-0x8, %al
movzbl %al, %eax
movq %rax, -0x60(%rbp)
movl $0x7, %r15d
xorl %r13d, %r13d
movzwl %cx, %r14d
testb $0x20, -0x34(%rbp)
movl %r13d, %eax
cmovel %r15d, %eax
btl %eax, %ebx
setb %cl
addb %cl, %cl
movl -0x44(%rbp), %edx
btl %eax, %edx
setb %al
orb %cl, %al
movzbl %al, %esi
movq -0x68(%rbp), %rdi
movl %r14d, %edx
callq 0x38580
movl %eax, %eax
leaq 0xfd4f(%rip), %rcx      # 0x48274
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movb $-0x34, %al
jmp 0x38538
movb $0x77, %al
jmp 0x38538
xorl %eax, %eax
movq -0x60(%rbp), %rcx
addl %r13d, %ecx
movzbl %cl, %ecx
leaq (%rcx,%rcx,2), %rcx
movb %al, (%r12,%rcx)
movb %al, 0x1(%r12,%rcx)
movb %al, 0x2(%r12,%rcx)
decl %r15d
incl %r13d
cmpl $0x8, %r13d
jne 0x384ef
movq -0x58(%rbp), %rdi
incq %rdi
cmpq $0x28, %rdi
jne 0x38421
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq