// File: /workspace/github_cpp_makefile_star2_O3/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 %r14
pushq %rbx
subq $0x10, %rsp
movq %rdi, %rbx
movl %esi, %eax
andl $0xe000, %eax           # imm = 0xE000
cmpl $0xa000, %eax           # imm = 0xA000
jne 0x1a127
addl $0xffff6000, %esi       # imm = 0xFFFF6000
movb %dl, 0x8000(%rbx,%rsi)
jmp 0x1a18a
movswl %si, %ecx
cmpl $0xffff9fff, %ecx       # imm = 0xFFFF9FFF
jg 0x1a15b
movl %esi, %eax
addl $0xffff8000, %eax       # imm = 0xFFFF8000
movb %dl, 0xa100(%rbx,%rax)
movzwl %si, %esi
cmpl $0x97ff, %esi           # imm = 0x97FF
ja 0x1a18a
movq %rbx, %rdi
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
jmp 0x1a510
movzwl %ax, %eax
cmpl $0xc000, %eax           # imm = 0xC000
jne 0x1a16d
addl $0xffff4000, %esi       # imm = 0xFFFF4000
jmp 0x1a183
leal 0x2000(%rsi), %eax
movzwl %ax, %eax
cmpl $0x1dff, %eax           # imm = 0x1DFF
ja 0x1a193
addl $0xffff2000, %esi       # imm = 0xFFFF2000
movb %dl, 0xc200(%rbx,%rsi)
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
retq
movl %esi, %eax
andl $0xff00, %eax           # imm = 0xFF00
cmpl $0xfe00, %eax           # imm = 0xFE00
jne 0x1a1b0
addl $0xffff0200, %esi       # imm = 0xFFFF0200
movb %dl, 0xc100(%rbx,%rsi)
jmp 0x1a18a
leal 0x80(%rsi), %eax
cmpw $0x7e, %ax
ja 0x1a1cb
addl $0xffff0080, %esi       # imm = 0xFFFF0080
movb %dl, 0xe200(%rbx,%rsi)
jmp 0x1a18a
movl %esi, %eax
andl $0xff80, %eax           # imm = 0xFF80
cmpl $0xff00, %eax           # imm = 0xFF00
jne 0x1a1fd
movzbl %sil, %eax
leal -0x40(%rax), %ecx
cmpl $0x9, %ecx
ja 0x1a20e
leaq 0x4040(%rip), %rax      # 0x1e22c
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movb %dl, 0xa040(%rbx)
jmp 0x1a18a
cmpw $-0x1, %si
jne 0x1a18a
movb %dl, 0xe280(%rbx)
jmp 0x1a18a
cmpl $0x4, %eax
je 0x1a39b
cmpl $0xf, %eax
jne 0x1a234
cmpb $0x0, 0xe280(%rbx)
je 0x1a18a
movb %dl, 0xa00f(%rbx)
jmp 0x1a18a
movl %esi, %eax
addl $0xffff0100, %eax       # imm = 0xFFFF0100
addq %rbx, %rax
addq $0xa000, %rax           # imm = 0xA000
jmp 0x1a322
movzbl %dl, %edx
shll $0x8, %edx
movl $0xa0, %ecx
movq %rbx, %rdi
movl $0xfe00, %esi           # imm = 0xFE00
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
jmp 0x1a578
movb %dl, 0xa043(%rbx)
jmp 0x1a18a
movb %dl, 0xa042(%rbx)
jmp 0x1a18a
movzbl %dl, %eax
leaq 0xe3a6(%rbx), %rdi
xorl %ecx, %ecx
movl %eax, %r8d
shrl %cl, %r8d
andl $0x3, %r8d
movb 0xe39a(%rbx,%r8), %r8b
movb %r8b, (%rdi)
addq $0x2, %rcx
incq %rdi
cmpq $0x8, %rcx
jne 0x1a28b
leaq 0xa049(%rbx), %rax
jmp 0x1a322
movzbl %dl, %eax
leaq 0xe3a2(%rbx), %rdi
xorl %ecx, %ecx
movl %eax, %r8d
shrl %cl, %r8d
andl $0x3, %r8d
movb 0xe39a(%rbx,%r8), %r8b
movb %r8b, (%rdi)
addq $0x2, %rcx
incq %rdi
cmpq $0x8, %rcx
jne 0x1a2c2
leaq 0xa048(%rbx), %rax
jmp 0x1a322
movzbl %dl, %eax
leaq 0xe39e(%rbx), %rdi
xorl %ecx, %ecx
movl %eax, %r8d
shrl %cl, %r8d
andl $0x3, %r8d
movb 0xe39a(%rbx,%r8), %r8b
movb %r8b, (%rdi)
addq $0x2, %rcx
incq %rdi
cmpq $0x8, %rcx
jne 0x1a2f9
leaq 0xa047(%rbx), %rax
movb %dl, (%rax)
movzwl %si, %eax
cmpl $0xff50, %eax           # imm = 0xFF50
setne %cl
cmpb $0x1, %dl
setne %dl
orb %cl, %dl
jne 0x1a345
movb $0x0, 0xe398(%rbx)
jmp 0x1a18a
cmpl $0xff02, %eax           # imm = 0xFF02
jne 0x1a18a
movzbl 0xa001(%rbx), %eax
cmpl $0xd, %eax
je 0x1a361
cmpl $0xa, %eax
jne 0x1a3a9
movq 0xdc60(%rip), %r14      # 0x27fc8
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)
jmp 0x1a18a
movw $0x0, 0xa004(%rbx)
jmp 0x1a18a
cmpb $0x20, %al
jl 0x1a18a
leaq -0x11(%rbp), %rsi
movb %al, (%rsi)
movq 0xdc0a(%rip), %rdi      # 0x27fc8
movl $0x1, %edx
callq 0x4400
jmp 0x1a18a
nop