// File: NGageMegaman[P]NEScutre/src/mem.cpp
// Function: Mem::write_byte(unsigned short, unsigned char)
void Mem::write_byte(uint16_t addr, uint8_t data) {
    //Mirroring
    if (addr > 0x07FF) {
	if (addr < 0x1000)
	    addr -= 0x0800;
	else if (addr < 0x1800)
	    addr -= 0x1000;
	else if (addr < 0x2000)
	    addr -= 0x1800;
    }
    //PPU regs mirroring
    if (addr > 0x2007 && addr < 0x4000) {
	addr = (addr & 7) + 0x2000;
    }
    
    if (addr == 0x2000)
	mem_ppu->write_PPUCTRL(data);
    else if (addr == 0x2001)
	mem_ppu->write_PPUMASK(data);
    //else if (addr == 0x2002)
	//ppu->PPUSTATUS = data;
    else if (addr == 0x2003)
	mem_ppu->write_OAMADDR(data);
    else if (addr == 0x2004)
	mem_ppu->write_OAMDATA(data);
    else if (addr == 0x2005)
	mem_ppu->write_PPUSCROLL(data);
    else if (addr == 0x2006)
	mem_ppu->write_PPUADDR(data);
    else if (addr == 0x2007)
	mem_ppu->write_PPUDATA(data);
    else if (addr == 0x4014) {
	uint8_t data_array[256];
	for (int i = 0; i < 256; ++i) 
	    data_array[i] = ram[(unsigned) (data << 8) + i];
	    
	mem_ppu->write_OAMDMA(data_array);
    }
    else if (addr == 0x4016 && data == 1) {
	controller_read_latch = 0;
	controller_latch = 0;
	XEvent event;
	while (XPending(di)) {
	    XNextEvent(di, &event);
	    int a;
	    if (event.type == KeyRelease) {
		a = event.xkey.keycode;
		if (a == 52)       //z_key
	    	    controller_inputs &= 0xfe;
	    	else if (a == 53)  //x_key
	    	    controller_inputs &= 0xfd;
	    	else if (a == 22)  //backspace_key
	    	    controller_inputs &= 0xfb;
	    	else if (a == 36)  //enter_key
	    	    controller_inputs &= 0xf7;
	    	else if (a == 111)  //up_key
	    	    controller_inputs &= 0xef;
	    	else if (a == 116)  //down_key
	    	    controller_inputs &= 0xdf;
	    	else if (a == 113)  //left_key
	    	    controller_inputs &= 0xbf;
	    	else if (a == 114)  //right_key
	    	    controller_inputs &= 0x7f;
	    }
	    if (event.type == KeyPress) {
		a = event.xkey.keycode;
		if (a == 52)       //z_key
	    	    controller_inputs |= 0x01;
	    	else if (a == 53)  //x_key
	    	    controller_inputs |= 0x02;
	    	else if (a == 22)  //backspace_key
	    	    controller_inputs |= 0x04;
	    	else if (a == 36)  //enter_key
	    	    controller_inputs |= 0x08;
	    	else if (a == 111)  //up_key
	    	    controller_inputs |= 0x10;
	    	else if (a == 116)  //down_key
	    	    controller_inputs |= 0x20;
	    	else if (a == 113)  //left_key
	    	    controller_inputs |= 0x40;
	    	else if (a == 114)  //right_key
	    	    controller_inputs |= 0x80;
	    }
	}
	controller_latch = controller_inputs;
    }
    else if (addr == 0x4016 && data == 0) {
	controller_read_latch = 1;
    }
    else
	ram[addr] = data;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1f0, %rsp            # imm = 0x1F0
movb %dl, %al
movw %si, %cx
movq %rdi, -0x8(%rbp)
movw %cx, -0xa(%rbp)
movb %al, -0xb(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x1e8(%rbp)
movzwl -0xa(%rbp), %eax
cmpl $0x7ff, %eax            # imm = 0x7FF
jle 0x4d13
movzwl -0xa(%rbp), %eax
cmpl $0x1000, %eax           # imm = 0x1000
jge 0x4cdb
movzwl -0xa(%rbp), %eax
subl $0x800, %eax            # imm = 0x800
movw %ax, -0xa(%rbp)
jmp 0x4d11
movzwl -0xa(%rbp), %eax
cmpl $0x1800, %eax           # imm = 0x1800
jge 0x4cf5
movzwl -0xa(%rbp), %eax
subl $0x1000, %eax           # imm = 0x1000
movw %ax, -0xa(%rbp)
jmp 0x4d0f
movzwl -0xa(%rbp), %eax
cmpl $0x2000, %eax           # imm = 0x2000
jge 0x4d0d
movzwl -0xa(%rbp), %eax
subl $0x1800, %eax           # imm = 0x1800
movw %ax, -0xa(%rbp)
jmp 0x4d0f
jmp 0x4d11
jmp 0x4d13
movzwl -0xa(%rbp), %eax
cmpl $0x2007, %eax           # imm = 0x2007
jle 0x4d39
movzwl -0xa(%rbp), %eax
cmpl $0x4000, %eax           # imm = 0x4000
jge 0x4d39
movzwl -0xa(%rbp), %eax
andl $0x7, %eax
addl $0x2000, %eax           # imm = 0x2000
movw %ax, -0xa(%rbp)
movzwl -0xa(%rbp), %eax
cmpl $0x2000, %eax           # imm = 0x2000
jne 0x4d60
movq -0x1e8(%rbp), %rax
movq 0x10000(%rax), %rdi
movzbl -0xb(%rbp), %esi
callq 0x56b0
jmp 0x5228
movzwl -0xa(%rbp), %eax
cmpl $0x2001, %eax           # imm = 0x2001
jne 0x4d87
movq -0x1e8(%rbp), %rax
movq 0x10000(%rax), %rdi
movzbl -0xb(%rbp), %esi
callq 0x5af0
jmp 0x5226
movzwl -0xa(%rbp), %eax
cmpl $0x2003, %eax           # imm = 0x2003
jne 0x4dae
movq -0x1e8(%rbp), %rax
movq 0x10000(%rax), %rdi
movzbl -0xb(%rbp), %esi
callq 0x5950
jmp 0x5224
movzwl -0xa(%rbp), %eax
cmpl $0x2004, %eax           # imm = 0x2004
jne 0x4dd5
movq -0x1e8(%rbp), %rax
movq 0x10000(%rax), %rdi
movzbl -0xb(%rbp), %esi
callq 0x5a40
jmp 0x5222
movzwl -0xa(%rbp), %eax
cmpl $0x2005, %eax           # imm = 0x2005
jne 0x4dfc
movq -0x1e8(%rbp), %rax
movq 0x10000(%rax), %rdi
movzbl -0xb(%rbp), %esi
callq 0x5b10
jmp 0x5220
movzwl -0xa(%rbp), %eax
cmpl $0x2006, %eax           # imm = 0x2006
jne 0x4e23
movq -0x1e8(%rbp), %rax
movq 0x10000(%rax), %rdi
movzbl -0xb(%rbp), %esi
callq 0x56f0
jmp 0x521e
movzwl -0xa(%rbp), %eax
cmpl $0x2007, %eax           # imm = 0x2007
jne 0x4e4a
movq -0x1e8(%rbp), %rax
movq 0x10000(%rax), %rdi
movzbl -0xb(%rbp), %esi
callq 0x58b0
jmp 0x521c
movzwl -0xa(%rbp), %eax
cmpl $0x4014, %eax           # imm = 0x4014
jne 0x4ec2
movl $0x0, -0x114(%rbp)
cmpl $0x100, -0x114(%rbp)    # imm = 0x100
jge 0x4ea3
movq -0x1e8(%rbp), %rax
movzbl -0xb(%rbp), %ecx
shll $0x8, %ecx
addl -0x114(%rbp), %ecx
movl %ecx, %ecx
movb (%rax,%rcx), %cl
movslq -0x114(%rbp), %rax
movb %cl, -0x110(%rbp,%rax)
movl -0x114(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x114(%rbp)
jmp 0x4e5f
movq -0x1e8(%rbp), %rax
movq 0x10000(%rax), %rdi
leaq -0x110(%rbp), %rsi
callq 0x5a80
jmp 0x521a
movzwl -0xa(%rbp), %eax
cmpl $0x4016, %eax           # imm = 0x4016
jne 0x51e1
movzbl -0xb(%rbp), %eax
cmpl $0x1, %eax
jne 0x51e1
movq -0x1e8(%rbp), %rax
movb $0x0, 0x10009(%rax)
movb $0x0, 0x10008(%rax)
movq -0x1e8(%rbp), %rax
movq 0x10010(%rax), %rdi
callq 0x10f0
cmpl $0x0, %eax
je 0x51cc
movq -0x1e8(%rbp), %rax
movq 0x10010(%rax), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x1190
cmpl $0x3, -0x1d8(%rbp)
jne 0x5081
movl -0x184(%rbp), %eax
movl %eax, -0x1dc(%rbp)
cmpl $0x34, -0x1dc(%rbp)
jne 0x4f6a
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
andl $0xfe, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x507f
cmpl $0x35, -0x1dc(%rbp)
jne 0x4f92
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
andl $0xfd, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x507d
cmpl $0x16, -0x1dc(%rbp)
jne 0x4fba
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
andl $0xfb, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x507b
cmpl $0x24, -0x1dc(%rbp)
jne 0x4fe2
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
andl $0xf7, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x5079
cmpl $0x6f, -0x1dc(%rbp)
jne 0x5007
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
andl $0xef, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x5077
cmpl $0x74, -0x1dc(%rbp)
jne 0x502c
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
andl $0xdf, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x5075
cmpl $0x71, -0x1dc(%rbp)
jne 0x5051
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
andl $0xbf, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x5073
cmpl $0x72, -0x1dc(%rbp)
jne 0x5071
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
andl $0x7f, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x5073
jmp 0x5075
jmp 0x5077
jmp 0x5079
jmp 0x507b
jmp 0x507d
jmp 0x507f
jmp 0x5081
cmpl $0x2, -0x1d8(%rbp)
jne 0x51c7
movl -0x184(%rbp), %eax
movl %eax, -0x1dc(%rbp)
cmpl $0x34, -0x1dc(%rbp)
jne 0x50bf
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
orl $0x1, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x51c5
cmpl $0x35, -0x1dc(%rbp)
jne 0x50e4
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
orl $0x2, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x51c3
cmpl $0x16, -0x1dc(%rbp)
jne 0x5109
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
orl $0x4, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x51c1
cmpl $0x24, -0x1dc(%rbp)
jne 0x512e
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
orl $0x8, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x51bf
cmpl $0x6f, -0x1dc(%rbp)
jne 0x5150
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
orl $0x10, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x51bd
cmpl $0x74, -0x1dc(%rbp)
jne 0x5172
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
orl $0x20, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x51bb
cmpl $0x71, -0x1dc(%rbp)
jne 0x5194
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
orl $0x40, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x51b9
cmpl $0x72, -0x1dc(%rbp)
jne 0x51b7
movq -0x1e8(%rbp), %rax
movzbl 0x1000a(%rax), %ecx
orl $0x80, %ecx
movb %cl, 0x1000a(%rax)
jmp 0x51b9
jmp 0x51bb
jmp 0x51bd
jmp 0x51bf
jmp 0x51c1
jmp 0x51c3
jmp 0x51c5
jmp 0x51c7
jmp 0x4ef3
movq -0x1e8(%rbp), %rax
movb 0x1000a(%rax), %cl
movb %cl, 0x10008(%rax)
jmp 0x5218
movzwl -0xa(%rbp), %eax
cmpl $0x4016, %eax           # imm = 0x4016
jne 0x5205
movzbl -0xb(%rbp), %eax
cmpl $0x0, %eax
jne 0x5205
movq -0x1e8(%rbp), %rax
movb $0x1, 0x10009(%rax)
jmp 0x5216
movq -0x1e8(%rbp), %rax
movb -0xb(%rbp), %dl
movzwl -0xa(%rbp), %ecx
movb %dl, (%rax,%rcx)
jmp 0x5218
jmp 0x521a
jmp 0x521c
jmp 0x521e
jmp 0x5220
jmp 0x5222
jmp 0x5224
jmp 0x5226
jmp 0x5228
addq $0x1f0, %rsp            # imm = 0x1F0
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)