// File: donfreiday[P]gb/gpu.cpp
// Function: GPU::renderBackground()
void GPU::renderBackground() {
  u16 tileData = mmu->memory[LCDC] & (1 << 4) ? 0x8000 : 0x8800;
  u16 bgTileMap = mmu->memory[LCDC] & (1 << 3) ? 0x9C00 : 0x9800;

  // yPos calculates which of 32 vertical tiles the current scanline is drawing
  u8 yPos = mmu->memory[SCY] + mmu->memory[LY];

  // Determine which of the 8 vertical pixels of the current tile the scanline
  // is on
  u16 tileRow = (((u8)(yPos / 8)) * 32);

  for (int pixel = 0; pixel < 160; pixel++) {
    u8 xPos = pixel + mmu->memory[SCX];

    // Determine which of the 32 horizontal tiles this xPos falls within
    u16 tileCol = (xPos / 8);

    u16 tileAddress = bgTileMap + tileRow + tileCol;

    // Tile ID can be signed or unsigned depending on tile data memory region
    s16 tileID = (tileData == 0x8800) ? (s8)(mmu->memory[tileAddress])
                                      : mmu->memory[tileAddress];

    // Find this tile ID in memory
    /* If the tile data memory area we are using is 0x8000-0x8FFF then the tile
    identifier read from the background layout regions is an UNSIGNED BYTE
    meaning the tile identifier will range from 0 - 255. However if we are using
    tile data area 0x8800-0x97FF then the tile identifier read from the
    background layout is a SIGNED BYTE meaning the tile identifier will range
    from -127 to 127. */
    u16 tileLocation = tileData;
    // printf("\ntileLocation: %04X",tileLocation);
    if (tileData == 0x8000) {
      tileLocation += (tileID * 16);
    } else {
      tileLocation += ((tileID + 128) * 16);
    }

    u8 line = yPos % 8;  // Current vertical line of tile
    line *= 2;           // Each vertical line is two bytes
    u8 data1 = mmu->memory[tileLocation + line];
    u8 data2 = mmu->memory[tileLocation + line + 1];

    /* A tile is 8x8 pixels; each horizontal line in a tile is two bytes.
      pixel# = 0 1 2 3 4 5 6 7
      data 2 = 1 0 1 0 1 1 1 0
      data 1 = 0 0 1 1 0 1 0 1

      Pixel 0 color id: 10
      Pixel 1 color id: 00
      Pixel 2 color id: 11
      Pixel 3 color id: 01
      Pixel 4 color id: 10
      Pixel 5 color id: 11
      Pixel 6 color id: 10
      Pixel 7 color id: 01

      Pixel 0 is bit 7 of data1 and data2: */
    int colorBit = xPos % 8;
    colorBit -= 7;
    colorBit *= -1;

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

    COLOR color = paletteLookup(colorID, BGP);
    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
    }

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

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x40(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movl $0xff40, %esi           # imm = 0xFF40
callq 0x4f3d0
movq %rax, %rcx
movq -0x40(%rbp), %rax
movzbl (%rcx), %esi
andl $0x10, %esi
movl $0x8800, %ecx           # imm = 0x8800
movl $0x8000, %edx           # imm = 0x8000
cmpl $0x0, %esi
cmovnel %edx, %ecx
movw %cx, -0xa(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movl $0xff40, %esi           # imm = 0xFF40
callq 0x4f3d0
movq %rax, %rcx
movq -0x40(%rbp), %rax
movzbl (%rcx), %esi
andl $0x8, %esi
movl $0x9800, %ecx           # imm = 0x9800
movl $0x9c00, %edx           # imm = 0x9C00
cmpl $0x0, %esi
cmovnel %edx, %ecx
movw %cx, -0xc(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movl $0xff42, %esi           # imm = 0xFF42
callq 0x4f3d0
movq %rax, %rcx
movq -0x40(%rbp), %rax
movzbl (%rcx), %ecx
movl %ecx, -0x38(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movl $0xff44, %esi           # imm = 0xFF44
callq 0x4f3d0
movq %rax, %rcx
movl -0x38(%rbp), %eax
movzbl (%rcx), %ecx
addl %ecx, %eax
movb %al, -0xd(%rbp)
movzbl -0xd(%rbp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movzbl %al, %eax
shll $0x5, %eax
movw %ax, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
cmpl $0xa0, -0x14(%rbp)
jge 0x51a70
movq -0x40(%rbp), %rax
movl -0x14(%rbp), %ecx
movl %ecx, -0x44(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movl $0xff43, %esi           # imm = 0xFF43
callq 0x4f3d0
movq %rax, %rcx
movl -0x44(%rbp), %eax
movzbl (%rcx), %ecx
addl %ecx, %eax
movb %al, -0x15(%rbp)
movzbl -0x15(%rbp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movw %ax, -0x18(%rbp)
movzwl -0xc(%rbp), %eax
movzwl -0x10(%rbp), %ecx
addl %ecx, %eax
movzwl -0x18(%rbp), %ecx
addl %ecx, %eax
movw %ax, -0x1a(%rbp)
movzwl -0xa(%rbp), %eax
cmpl $0x8800, %eax           # imm = 0x8800
jne 0x51855
movq -0x40(%rbp), %rax
movq (%rax), %rdi
addq $0x8, %rdi
movzwl -0x1a(%rbp), %eax
movl %eax, %esi
callq 0x4f3d0
movsbl (%rax), %eax
movl %eax, -0x48(%rbp)
jmp 0x51871
movq -0x40(%rbp), %rax
movq (%rax), %rdi
addq $0x8, %rdi
movzwl -0x1a(%rbp), %eax
movl %eax, %esi
callq 0x4f3d0
movzbl (%rax), %eax
movl %eax, -0x48(%rbp)
movl -0x48(%rbp), %eax
movw %ax, -0x1c(%rbp)
movw -0xa(%rbp), %ax
movw %ax, -0x1e(%rbp)
movzwl -0xa(%rbp), %eax
cmpl $0x8000, %eax           # imm = 0x8000
jne 0x5189e
movswl -0x1c(%rbp), %ecx
shll $0x4, %ecx
movzwl -0x1e(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x1e(%rbp)
jmp 0x518b5
movswl -0x1c(%rbp), %ecx
addl $0x80, %ecx
shll $0x4, %ecx
movzwl -0x1e(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x1e(%rbp)
movzbl -0xd(%rbp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movq -0x40(%rbp), %rax
movb %dl, %cl
movb %cl, -0x1f(%rbp)
movzbl -0x1f(%rbp), %ecx
shll %ecx
movb %cl, -0x1f(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movzwl -0x1e(%rbp), %eax
movzbl -0x1f(%rbp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
callq 0x4f3d0
movq %rax, %rcx
movq -0x40(%rbp), %rax
movb (%rcx), %cl
movb %cl, -0x20(%rbp)
movq (%rax), %rdi
addq $0x8, %rdi
movzwl -0x1e(%rbp), %eax
movzbl -0x1f(%rbp), %ecx
addl %ecx, %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x4f3d0
movb (%rax), %al
movb %al, -0x21(%rbp)
movzbl -0x15(%rbp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %edx, -0x28(%rbp)
movl -0x28(%rbp), %eax
subl $0x7, %eax
movl %eax, -0x28(%rbp)
imull $-0x1, -0x28(%rbp), %eax
movl %eax, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movzbl -0x21(%rbp), %eax
movl -0x28(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x5195f
movl -0x2c(%rbp), %eax
orl $0x2, %eax
movl %eax, -0x2c(%rbp)
movzbl -0x20(%rbp), %eax
movl -0x28(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x5197f
movl -0x2c(%rbp), %eax
orl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x40(%rbp), %rdi
movzbl -0x2c(%rbp), %esi
movl $0xff47, %edx           # imm = 0xFF47
callq 0x51e50
movl %eax, -0x30(%rbp)
movb $0x0, -0x31(%rbp)
movb $0x0, -0x32(%rbp)
movb $0x0, -0x33(%rbp)
movl -0x30(%rbp), %eax
movq %rax, -0x50(%rbp)
subq $0x3, %rax
ja 0x519ed
movq -0x50(%rbp), %rax
leaq 0x146bc(%rip), %rcx     # 0x66074
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movb $-0x1, -0x31(%rbp)
movb $-0x1, -0x32(%rbp)
movb $-0x1, -0x33(%rbp)
jmp 0x519ed
movb $-0x34, -0x31(%rbp)
movb $-0x34, -0x32(%rbp)
movb $-0x34, -0x33(%rbp)
jmp 0x519ed
movb $0x77, -0x31(%rbp)
movb $0x77, -0x32(%rbp)
movb $0x77, -0x33(%rbp)
jmp 0x519ed
jmp 0x519ed
movq -0x40(%rbp), %rdx
movb -0x31(%rbp), %cl
movq %rdx, %rax
addq $0x1d, %rax
movzbl 0x10(%rdx), %esi
imulq $0x1e0, %rsi, %rsi      # imm = 0x1E0
addq %rsi, %rax
movslq -0x14(%rbp), %rsi
imulq $0x3, %rsi, %rsi
addq %rsi, %rax
movb %cl, (%rax)
movb -0x32(%rbp), %cl
movq %rdx, %rax
addq $0x1d, %rax
movzbl 0x10(%rdx), %esi
imulq $0x1e0, %rsi, %rsi      # imm = 0x1E0
addq %rsi, %rax
movslq -0x14(%rbp), %rsi
imulq $0x3, %rsi, %rsi
addq %rsi, %rax
movb %cl, 0x1(%rax)
movb -0x33(%rbp), %cl
movq %rdx, %rax
addq $0x1d, %rax
movzbl 0x10(%rdx), %edx
imulq $0x1e0, %rdx, %rdx      # imm = 0x1E0
addq %rdx, %rax
movslq -0x14(%rbp), %rdx
imulq $0x3, %rdx, %rdx
addq %rdx, %rax
movb %cl, 0x2(%rax)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x517d2
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)