// File: /workspace/github_cpp_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movl %edx, %r15d
movq %rdi, %rbx
movl %esi, %eax
andl $0xe000, %eax           # imm = 0xE000
movzwl %si, %r14d
cmpl $0xa000, %eax           # imm = 0xA000
jne 0x1b462
addl $0xffff6000, %esi       # imm = 0xFFFF6000
movb %r15b, 0x8000(%rbx,%rsi)
jmp 0x1b4c5
movswl %si, %ecx
cmpl $0xffff9fff, %ecx       # imm = 0xFFFF9FFF
jg 0x1b491
addl $0xffff8000, %esi       # imm = 0xFFFF8000
movb %r15b, 0xa100(%rbx,%rsi)
cmpl $0x97ff, %r14d          # imm = 0x97FF
ja 0x1b4c5
movq %rbx, %rdi
movl %r14d, %esi
callq 0x1b84c
jmp 0x1b4c5
movzwl %ax, %eax
cmpl $0xc000, %eax           # imm = 0xC000
jne 0x1b4a3
addl $0xffff4000, %esi       # imm = 0xFFFF4000
jmp 0x1b4bd
leal 0x2000(%rsi), %eax
movzwl %ax, %eax
cmpl $0x1dff, %eax           # imm = 0x1DFF
ja 0x1b558
addl $0xffff2000, %esi       # imm = 0xFFFF2000
movb %r15b, 0xc200(%rbx,%rsi)
cmpl $0xff50, %r14d          # imm = 0xFF50
setne %al
cmpb $0x1, %r15b
setne %cl
orb %al, %cl
jne 0x1b4e1
movb $0x0, 0xe398(%rbx)
cmpl $0xff02, %r14d          # imm = 0xFF02
jne 0x1b530
movzbl 0xa001(%rbx), %eax
cmpl $0xd, %eax
je 0x1b4fb
cmpl $0xa, %eax
jne 0x1b53b
movq 0xeac6(%rip), %r14      # 0x29fc8
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x4340
movsbl %al, %esi
movq %r14, %rdi
callq 0x4050
movq %rax, %rdi
callq 0x42a0
movb $0x1, 0xe399(%rbx)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
cmpb $0x20, %al
jl 0x1b530
leaq -0x19(%rbp), %rsi
movb %al, (%rsi)
movq 0xea7c(%rip), %rdi      # 0x29fc8
movl $0x1, %edx
callq 0x4410
jmp 0x1b530
movl %esi, %eax
andl $0xff00, %eax           # imm = 0xFF00
cmpl $0xfe00, %eax           # imm = 0xFE00
jne 0x1b579
addl $0xffff0200, %esi       # imm = 0xFFFF0200
movb %r15b, 0xc100(%rbx,%rsi)
jmp 0x1b4c5
leal 0x80(%rsi), %eax
cmpw $0x7e, %ax
ja 0x1b598
addl $0xffff0080, %esi       # imm = 0xFFFF0080
movb %r15b, 0xe200(%rbx,%rsi)
jmp 0x1b4c5
movl %esi, %eax
andl $0xff80, %eax           # imm = 0xFF80
cmpl $0xff00, %eax           # imm = 0xFF00
jne 0x1b5ce
movzbl %sil, %eax
leal -0x40(%rax), %ecx
cmpl $0x9, %ecx
ja 0x1b5e4
leaq 0x4cb7(%rip), %rax      # 0x20270
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movb %r15b, 0xa040(%rbx)
jmp 0x1b4c5
cmpw $-0x1, %si
jne 0x1b4c5
movb %r15b, 0xe280(%rbx)
jmp 0x1b4c5
cmpl $0x4, %eax
je 0x1b6fc
cmpl $0xf, %eax
jne 0x1b60b
cmpb $0x0, 0xe280(%rbx)
je 0x1b4c5
movb %r15b, 0xa00f(%rbx)
jmp 0x1b4c5
addl $0xffff0100, %esi       # imm = 0xFFFF0100
movb %r15b, 0xa000(%rbx,%rsi)
jmp 0x1b4c5
movzbl %r15b, %edx
shll $0x8, %edx
movl $0xa0, %ecx
movq %rbx, %rdi
movl $0xfe00, %esi           # imm = 0xFE00
callq 0x1b8b4
jmp 0x1b4c5
movb %r15b, 0xa043(%rbx)
jmp 0x1b4c5
movb %r15b, 0xa042(%rbx)
jmp 0x1b4c5
movzbl %r15b, %eax
leaq 0xe3a6(%rbx), %rdx
xorl %ecx, %ecx
movl %eax, %esi
shrl %cl, %esi
andl $0x3, %esi
movb 0xe39a(%rbx,%rsi), %sil
movb %sil, (%rdx)
addq $0x2, %rcx
incq %rdx
cmpq $0x8, %rcx
jne 0x1b661
movb %r15b, 0xa049(%rbx)
jmp 0x1b4c5
movzbl %r15b, %eax
leaq 0xe3a2(%rbx), %rdx
xorl %ecx, %ecx
movl %eax, %esi
shrl %cl, %esi
andl $0x3, %esi
movb 0xe39a(%rbx,%rsi), %sil
movb %sil, (%rdx)
addq $0x2, %rcx
incq %rdx
cmpq $0x8, %rcx
jne 0x1b699
movb %r15b, 0xa048(%rbx)
jmp 0x1b4c5
movzbl %r15b, %eax
leaq 0xe39e(%rbx), %rdx
xorl %ecx, %ecx
movl %eax, %esi
shrl %cl, %esi
andl $0x3, %esi
movb 0xe39a(%rbx,%rsi), %sil
movb %sil, (%rdx)
addq $0x2, %rcx
incq %rdx
cmpq $0x8, %rcx
jne 0x1b6d1
movb %r15b, 0xa047(%rbx)
jmp 0x1b4c5
movw $0x0, 0xa004(%rbx)
jmp 0x1b4c5