// File: RegulusImpact[P]sadboy/src/MMU.cpp
// Function: MMU::Write(unsigned short, unsigned char)
void MMU::Write(uint16_t addr, uint8_t val) {
    // RAM[addr] = val;


    // cartridge / bios
    // we don't write to cart
    // if (addr <= 0x7FFF)
    //     cart[addr] = val;
    // sram
    if (addr >= 0xA000 && addr <= 0xBFFF)
        sram[addr - 0xA000] = val;
    // video ram
    else if (addr >= 0x8000 && addr <= 0x9FFF) {
        vram[addr - 0x8000] = val;
        if (addr <= 0x97FF) {
            UpdateTile(addr);
        }
    }

    // writable ram
    else if (addr >= 0xC000 && addr <= 0xDFFF)
        wram[addr - 0xC000] = val;

    // more writable ram
    else if (addr >= 0xE000 && addr <= 0xFDFF)
        wram[addr - 0xE000] = val;

    // oam
    else if (addr >= 0xFE00 && addr <= 0xFEFF)
        oam[addr - 0xFE00] = val;

    // io
    // this includes FFOO - user input joypad
    // timers
    // gpu

    else if (addr >= 0xFF80 && addr <= 0xFFFE)
        hram[addr - 0xFF80] = val;
    else if (addr >= 0xFF00 && addr <= 0xFF7F) {
        // io[addr - 0xFF00] = val;


        // stupid timers div and tima
        if (addr == 0xFF04) {
            io[0xFF04 - 0xFF00] = 0;
            io[0xFF05 - 0xFF00] = 0;
        } else if (addr == 0xFF0F) {
            if (Read(0xFFFF) > 0) {
                io[addr - 0xFF00] = val;
            }
        } else if (addr == 0xFF40)
            io[addr - 0xFF00] = val;

        else if (addr == 0xFF42)
            io[addr - 0xFF00] = val;

        else if (addr == 0xFF43)
            io[addr - 0xFF00] = val;

        else if (addr == 0xFF46) {
            Copy(0xFE00, ((uint16_t)val) << 8, 160); // oam dma

            // io[addr - 0xFF00] = val;
        }

        else if (addr == 0xFF47) { // setup bgp
            for (int ii = 0; ii < 4; ii++) {
                bgp[ii] = palette[(val >> ( ii * 2)) & 3];
            }

            io[addr - 0xFF00] = val;
        }

        else if (addr == 0xFF48) { // setup OBP0 ; sprites
            for (int ii = 0; ii < 4; ii++) {
                obp[0][ii] = palette[(val >> ( ii * 2)) & 3];
            }

            io[addr - 0xFF00] = val;
        }

        else if (addr == 0xFF49) { // setup OBP1 ; sprites
            for (int ii = 0; ii < 4; ii++) {
                obp[1][ii] = palette[(val >> ( ii * 2)) & 3];
            }

            io[addr - 0xFF00] = val;
        } else {
            io[addr - 0xFF00] = val;
        }
    }
    else if (addr == 0xFFFF)
        interrupt = val;

    if (0xFF50 == addr && 1 == val) {
        readBios = false;
    }

    // oh christ what are we doing....
    if (addr == 0xFF02) {// || addr == 0x0081) {
        char c = Read(0xFF01);

        if (c == '\n' || c == '\r') {
            std::cout << std::endl;

            // probably the title when the first newline occurs
            enableDebugger = true;
        } else if (c >= 0x20) {
            //c[0] = Read(0xFF01);
            std::cout << c;
            // if (c == 'd') exit(1);
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %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, -0x28(%rbp)
movzwl -0xa(%rbp), %eax
cmpl $0xa000, %eax           # imm = 0xA000
jl 0x33026
movzwl -0xa(%rbp), %eax
cmpl $0xbfff, %eax           # imm = 0xBFFF
jg 0x33026
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xa000, %ecx           # imm = 0xA000
movslq %ecx, %rcx
movb %dl, 0x8000(%rax,%rcx)
jmp 0x33412
movzwl -0xa(%rbp), %eax
cmpl $0x8000, %eax           # imm = 0x8000
jl 0x33074
movzwl -0xa(%rbp), %eax
cmpl $0x9fff, %eax           # imm = 0x9FFF
jg 0x33074
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0x8000, %ecx           # imm = 0x8000
movslq %ecx, %rcx
movb %dl, 0xa100(%rax,%rcx)
movzwl -0xa(%rbp), %eax
cmpl $0x97ff, %eax           # imm = 0x97FF
jg 0x3306f
movq -0x28(%rbp), %rdi
movzwl -0xa(%rbp), %esi
callq 0x33750
jmp 0x33410
movzwl -0xa(%rbp), %eax
cmpl $0xc000, %eax           # imm = 0xC000
jl 0x330aa
movzwl -0xa(%rbp), %eax
cmpl $0xdfff, %eax           # imm = 0xDFFF
jg 0x330aa
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xc000, %ecx           # imm = 0xC000
movslq %ecx, %rcx
movb %dl, 0xc200(%rax,%rcx)
jmp 0x3340e
movzwl -0xa(%rbp), %eax
cmpl $0xe000, %eax           # imm = 0xE000
jl 0x330e0
movzwl -0xa(%rbp), %eax
cmpl $0xfdff, %eax           # imm = 0xFDFF
jg 0x330e0
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xe000, %ecx           # imm = 0xE000
movslq %ecx, %rcx
movb %dl, 0xc200(%rax,%rcx)
jmp 0x3340c
movzwl -0xa(%rbp), %eax
cmpl $0xfe00, %eax           # imm = 0xFE00
jl 0x33116
movzwl -0xa(%rbp), %eax
cmpl $0xfeff, %eax           # imm = 0xFEFF
jg 0x33116
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xfe00, %ecx           # imm = 0xFE00
movslq %ecx, %rcx
movb %dl, 0xc100(%rax,%rcx)
jmp 0x3340a
movzwl -0xa(%rbp), %eax
cmpl $0xff80, %eax           # imm = 0xFF80
jl 0x3314c
movzwl -0xa(%rbp), %eax
cmpl $0xfffe, %eax           # imm = 0xFFFE
jg 0x3314c
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff80, %ecx           # imm = 0xFF80
movslq %ecx, %rcx
movb %dl, 0xe200(%rax,%rcx)
jmp 0x33408
movzwl -0xa(%rbp), %eax
cmpl $0xff00, %eax           # imm = 0xFF00
jl 0x333ec
movzwl -0xa(%rbp), %eax
cmpl $0xff7f, %eax           # imm = 0xFF7F
jg 0x333ec
movzwl -0xa(%rbp), %eax
cmpl $0xff04, %eax           # imm = 0xFF04
jne 0x3318c
movq -0x28(%rbp), %rax
movb $0x0, 0xa004(%rax)
movb $0x0, 0xa005(%rax)
jmp 0x333ea
movzwl -0xa(%rbp), %eax
cmpl $0xff0f, %eax           # imm = 0xFF0F
jne 0x331cd
movq -0x28(%rbp), %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq 0x334c0
movzbl %al, %eax
cmpl $0x0, %eax
jle 0x331c8
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff00, %ecx           # imm = 0xFF00
movslq %ecx, %rcx
movb %dl, 0xa000(%rax,%rcx)
jmp 0x333e8
movzwl -0xa(%rbp), %eax
cmpl $0xff40, %eax           # imm = 0xFF40
jne 0x331f8
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff00, %ecx           # imm = 0xFF00
movslq %ecx, %rcx
movb %dl, 0xa000(%rax,%rcx)
jmp 0x333e6
movzwl -0xa(%rbp), %eax
cmpl $0xff42, %eax           # imm = 0xFF42
jne 0x33223
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff00, %ecx           # imm = 0xFF00
movslq %ecx, %rcx
movb %dl, 0xa000(%rax,%rcx)
jmp 0x333e4
movzwl -0xa(%rbp), %eax
cmpl $0xff43, %eax           # imm = 0xFF43
jne 0x3324e
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff00, %ecx           # imm = 0xFF00
movslq %ecx, %rcx
movb %dl, 0xa000(%rax,%rcx)
jmp 0x333e2
movzwl -0xa(%rbp), %eax
cmpl $0xff46, %eax           # imm = 0xFF46
jne 0x3327e
movq -0x28(%rbp), %rdi
movzbl -0xb(%rbp), %eax
movzwl %ax, %eax
shll $0x8, %eax
movl $0xfe00, %esi           # imm = 0xFE00
movl $0xa0, %ecx
movzwl %ax, %edx
callq 0x33840
jmp 0x333e0
movzwl -0xa(%rbp), %eax
cmpl $0xff47, %eax           # imm = 0xFF47
jne 0x332ea
movl $0x0, -0x10(%rbp)
cmpl $0x4, -0x10(%rbp)
jge 0x332ca
movq -0x28(%rbp), %rax
movzbl -0xb(%rbp), %edx
movl -0x10(%rbp), %ecx
shll %ecx
sarl %cl, %edx
movl %edx, %ecx
andl $0x3, %ecx
movslq %ecx, %rcx
movb 0xe39a(%rax,%rcx), %dl
movslq -0x10(%rbp), %rcx
movb %dl, 0xe39e(%rax,%rcx)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x33290
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff00, %ecx           # imm = 0xFF00
movslq %ecx, %rcx
movb %dl, 0xa000(%rax,%rcx)
jmp 0x333de
movzwl -0xa(%rbp), %eax
cmpl $0xff48, %eax           # imm = 0xFF48
jne 0x33356
movl $0x0, -0x14(%rbp)
cmpl $0x4, -0x14(%rbp)
jge 0x33336
movq -0x28(%rbp), %rax
movzbl -0xb(%rbp), %edx
movl -0x14(%rbp), %ecx
shll %ecx
sarl %cl, %edx
movl %edx, %ecx
andl $0x3, %ecx
movslq %ecx, %rcx
movb 0xe39a(%rax,%rcx), %dl
movslq -0x14(%rbp), %rcx
movb %dl, 0xe3a2(%rax,%rcx)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x332fc
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff00, %ecx           # imm = 0xFF00
movslq %ecx, %rcx
movb %dl, 0xa000(%rax,%rcx)
jmp 0x333dc
movzwl -0xa(%rbp), %eax
cmpl $0xff49, %eax           # imm = 0xFF49
jne 0x333bf
movl $0x0, -0x18(%rbp)
cmpl $0x4, -0x18(%rbp)
jge 0x333a2
movq -0x28(%rbp), %rax
movzbl -0xb(%rbp), %edx
movl -0x18(%rbp), %ecx
shll %ecx
sarl %cl, %edx
movl %edx, %ecx
andl $0x3, %ecx
movslq %ecx, %rcx
movb 0xe39a(%rax,%rcx), %dl
movslq -0x18(%rbp), %rcx
movb %dl, 0xe3a6(%rax,%rcx)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x33368
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff00, %ecx           # imm = 0xFF00
movslq %ecx, %rcx
movb %dl, 0xa000(%rax,%rcx)
jmp 0x333da
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
subl $0xff00, %ecx           # imm = 0xFF00
movslq %ecx, %rcx
movb %dl, 0xa000(%rax,%rcx)
jmp 0x333dc
jmp 0x333de
jmp 0x333e0
jmp 0x333e2
jmp 0x333e4
jmp 0x333e6
jmp 0x333e8
jmp 0x333ea
jmp 0x33406
movzwl -0xa(%rbp), %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
jne 0x33404
movq -0x28(%rbp), %rax
movb -0xb(%rbp), %cl
movb %cl, 0xe280(%rax)
jmp 0x33406
jmp 0x33408
jmp 0x3340a
jmp 0x3340c
jmp 0x3340e
jmp 0x33410
jmp 0x33412
movzwl -0xa(%rbp), %ecx
movl $0xff50, %eax           # imm = 0xFF50
cmpl %ecx, %eax
jne 0x33437
movzbl -0xb(%rbp), %ecx
movl $0x1, %eax
cmpl %ecx, %eax
jne 0x33437
movq -0x28(%rbp), %rax
movb $0x0, 0xe398(%rax)
movzwl -0xa(%rbp), %eax
cmpl $0xff02, %eax           # imm = 0xFF02
jne 0x334a2
movq -0x28(%rbp), %rdi
movl $0xff01, %esi           # imm = 0xFF01
callq 0x334c0
movb %al, -0x19(%rbp)
movsbl -0x19(%rbp), %eax
cmpl $0xa, %eax
je 0x33465
movsbl -0x19(%rbp), %eax
cmpl $0xd, %eax
jne 0x33485
movq 0x18b54(%rip), %rdi     # 0x4bfc0
movq 0x18b35(%rip), %rsi     # 0x4bfa8
callq 0x54d0
movq -0x28(%rbp), %rax
movb $0x1, 0xe399(%rax)
jmp 0x334a0
movsbl -0x19(%rbp), %eax
cmpl $0x20, %eax
jl 0x3349e
movq 0x18b2b(%rip), %rdi     # 0x4bfc0
movsbl -0x19(%rbp), %esi
callq 0x5560
jmp 0x334a0
jmp 0x334a2
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax,%rax)