// File: donfreiday[P]gb/mmu.cpp
// Function: MMU::write8(unsigned short, unsigned char)
void MMU::write8(u16 addr, u8 value) {
  // External RAM switch
  if (addr <= 0x1FFF) {
  }

  // ROM
  else if (addr >= 0x2000 && addr <= 0x3FFF) {
    switch (mbc.type) {
      case 1:
      case 2:
      case 3:
        value &= 0x0F;
        if (!value) {
          value = 1;
        }
        mbc.romBank = (mbc.romBank & 0x60) + value;
        mbc.romOffset = mbc.romBank * 0x4000;
        break;
      default:
        break;
    }
  }

  // RAM
  else if (addr >= 0x4000 && addr <= 0x5FFF) {
    switch (mbc.type) {
      case 1:
      case 2:
      case 3:
        // RAM bank
        if (mbc.mode) {
          mbc.ramOffset = (value & 3) * 0x2000;
        } else {
          // ROM bank
          mbc.romBank = (mbc.romBank & 0x1F) + ((value & 3) << 5);
          mbc.romOffset = mbc.romBank * 0x4000;
        }
        break;
      default:
        break;
    }
  }

  else if (addr >= 0x6000 && addr <= 0x7FFF) {
    switch (mbc.type) {
      case 2:
      case 3:
        mbc.mode = value & 1;
        break;
      default:
        break;
    }
  }

  // RAM, external
  else if (addr >= 0xA000 && addr <= 0xBFFF) {
    ram[mbc.ramOffset + (addr & 0x1FFF)] = value;
  }

  // WRAM shadow
  else if (addr >= 0xE000 && addr <= 0xFDFF) {
    memory[addr - 0x1000] = value;
  }

  // Writes to DIV reset it to zero
  else if (addr == DIV) {
    memory[DIV] = 0;
  }

  // Joypad class handles its register
  else if (addr == JOYP) {
    memory[addr] = joypad->read(value);
  }

  // CPU IF always polls high on bits 5-7
  else if (addr == IF) {
    value |= 0xE0;
    memory[addr] = value;
  }

  // Writes to current scanline register reset it
  else if (addr == LY) {
    memory[addr] = 0;
  }

  // DMA
  else if (addr == DMA) {
    memory[0xFF46] = value;
    dma(value);
  }

  // Unmap bootrom
  else if (addr == 0xFF50) {
    return;
  }

  // Default
  else {
    memory[addr] = value;
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movb %dl, %al
movw %si, %cx
movq %rdi, -0x8(%rbp)
movw %cx, -0xa(%rbp)
movb %al, -0xb(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x18(%rbp)
movzwl -0xa(%rbp), %eax
cmpl $0x1fff, %eax           # imm = 0x1FFF
jg 0x4eea0
jmp 0x4f173
movzwl -0xa(%rbp), %eax
cmpl $0x2000, %eax           # imm = 0x2000
jl 0x4ef02
movzwl -0xa(%rbp), %eax
cmpl $0x3fff, %eax           # imm = 0x3FFF
jg 0x4ef02
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
decl %eax
subl $0x2, %eax
ja 0x4eefb
jmp 0x4eec6
movzbl -0xb(%rbp), %eax
andl $0xf, %eax
movb %al, -0xb(%rbp)
cmpb $0x0, -0xb(%rbp)
jne 0x4eeda
movb $0x1, -0xb(%rbp)
movq -0x18(%rbp), %rax
movzbl 0x1(%rax), %ecx
andl $0x60, %ecx
movzbl -0xb(%rbp), %edx
addl %edx, %ecx
movb %cl, 0x1(%rax)
movzbl 0x1(%rax), %ecx
shll $0xe, %ecx
movw %cx, 0x2(%rax)
jmp 0x4eefd
jmp 0x4eefd
jmp 0x4f171
movzwl -0xa(%rbp), %eax
cmpl $0x4000, %eax           # imm = 0x4000
jl 0x4ef74
movzwl -0xa(%rbp), %eax
cmpl $0x5fff, %eax           # imm = 0x5FFF
jg 0x4ef74
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
decl %eax
subl $0x2, %eax
ja 0x4ef6d
jmp 0x4ef28
movq -0x18(%rbp), %rax
cmpb $0x0, 0x6(%rax)
je 0x4ef46
movq -0x18(%rbp), %rax
movzbl -0xb(%rbp), %ecx
andl $0x3, %ecx
shll $0xd, %ecx
movw %cx, 0x4(%rax)
jmp 0x4ef6b
movq -0x18(%rbp), %rax
movzbl 0x1(%rax), %ecx
andl $0x1f, %ecx
movzbl -0xb(%rbp), %edx
andl $0x3, %edx
shll $0x5, %edx
addl %edx, %ecx
movb %cl, 0x1(%rax)
movzbl 0x1(%rax), %ecx
shll $0xe, %ecx
movw %cx, 0x2(%rax)
jmp 0x4ef6f
jmp 0x4ef6f
jmp 0x4f16f
movzwl -0xa(%rbp), %eax
cmpl $0x6000, %eax           # imm = 0x6000
jl 0x4efb2
movzwl -0xa(%rbp), %eax
cmpl $0x7fff, %eax           # imm = 0x7FFF
jg 0x4efb2
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
addl $-0x2, %eax
subl $0x1, %eax
ja 0x4efab
jmp 0x4ef9b
movq -0x18(%rbp), %rax
movzbl -0xb(%rbp), %ecx
andl $0x1, %ecx
movb %cl, 0x6(%rax)
jmp 0x4efad
jmp 0x4efad
jmp 0x4f16d
movzwl -0xa(%rbp), %eax
cmpl $0xa000, %eax           # imm = 0xA000
jl 0x4effb
movzwl -0xa(%rbp), %eax
cmpl $0xbfff, %eax           # imm = 0xBFFF
jg 0x4effb
movq -0x18(%rbp), %rax
movb -0xb(%rbp), %cl
movb %cl, -0x19(%rbp)
movq %rax, %rdi
addq $0x50, %rdi
movzwl 0x4(%rax), %eax
movzwl -0xa(%rbp), %ecx
andl $0x1fff, %ecx           # imm = 0x1FFF
addl %ecx, %eax
movslq %eax, %rsi
callq 0x4f3d0
movb -0x19(%rbp), %cl
movb %cl, (%rax)
jmp 0x4f16b
movzwl -0xa(%rbp), %eax
cmpl $0xe000, %eax           # imm = 0xE000
jl 0x4f03a
movzwl -0xa(%rbp), %eax
cmpl $0xfdff, %eax           # imm = 0xFDFF
jg 0x4f03a
movq -0x18(%rbp), %rdi
movb -0xb(%rbp), %al
movb %al, -0x1a(%rbp)
addq $0x8, %rdi
movzwl -0xa(%rbp), %eax
subl $0x1000, %eax           # imm = 0x1000
movslq %eax, %rsi
callq 0x4f3d0
movb -0x1a(%rbp), %cl
movb %cl, (%rax)
jmp 0x4f169
movzwl -0xa(%rbp), %eax
cmpl $0xff04, %eax           # imm = 0xFF04
jne 0x4f05f
movq -0x18(%rbp), %rdi
addq $0x8, %rdi
movl $0xff04, %esi           # imm = 0xFF04
callq 0x4f3d0
movb $0x0, (%rax)
jmp 0x4f167
movzwl -0xa(%rbp), %eax
cmpl $0xff00, %eax           # imm = 0xFF00
jne 0x4f09b
movq -0x18(%rbp), %rax
movq 0x70(%rax), %rdi
movzbl -0xb(%rbp), %esi
callq 0x4e840
movq -0x18(%rbp), %rdi
movb %al, -0x1b(%rbp)
addq $0x8, %rdi
movzwl -0xa(%rbp), %eax
movl %eax, %esi
callq 0x4f3d0
movb -0x1b(%rbp), %cl
movb %cl, (%rax)
jmp 0x4f165
movzwl -0xa(%rbp), %eax
cmpl $0xff0f, %eax           # imm = 0xFF0F
jne 0x4f0d5
movq -0x18(%rbp), %rdi
movzbl -0xb(%rbp), %eax
orl $0xe0, %eax
movb %al, -0xb(%rbp)
movb -0xb(%rbp), %al
movb %al, -0x1c(%rbp)
addq $0x8, %rdi
movzwl -0xa(%rbp), %eax
movl %eax, %esi
callq 0x4f3d0
movb -0x1c(%rbp), %cl
movb %cl, (%rax)
jmp 0x4f163
movzwl -0xa(%rbp), %eax
cmpl $0xff44, %eax           # imm = 0xFF44
jne 0x4f0f8
movq -0x18(%rbp), %rdi
addq $0x8, %rdi
movzwl -0xa(%rbp), %eax
movl %eax, %esi
callq 0x4f3d0
movb $0x0, (%rax)
jmp 0x4f161
movzwl -0xa(%rbp), %eax
cmpl $0xff46, %eax           # imm = 0xFF46
jne 0x4f132
movq -0x18(%rbp), %rdi
movb -0xb(%rbp), %al
movb %al, -0x1d(%rbp)
addq $0x8, %rdi
movl $0xff46, %esi           # imm = 0xFF46
callq 0x4f3d0
movb -0x1d(%rbp), %cl
movq -0x18(%rbp), %rdi
movb %cl, (%rax)
movzbl -0xb(%rbp), %eax
movzwl %ax, %esi
callq 0x4f180
jmp 0x4f15f
movzwl -0xa(%rbp), %eax
cmpl $0xff50, %eax           # imm = 0xFF50
jne 0x4f13f
jmp 0x4f173
movq -0x18(%rbp), %rdi
movb -0xb(%rbp), %al
movb %al, -0x1e(%rbp)
addq $0x8, %rdi
movzwl -0xa(%rbp), %eax
movl %eax, %esi
callq 0x4f3d0
movb -0x1e(%rbp), %cl
movb %cl, (%rax)
jmp 0x4f15f
jmp 0x4f161
jmp 0x4f163
jmp 0x4f165
jmp 0x4f167
jmp 0x4f169
jmp 0x4f16b
jmp 0x4f16d
jmp 0x4f16f
jmp 0x4f171
jmp 0x4f173
addq $0x20, %rsp
popq %rbp
retq
nopl (%rax)