// File: /workspace/github_cpp_makefile_star2_O3/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 %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x108, %rsp            # imm = 0x108
movq %rdi, %rbx
cmpl $0x800, %esi            # imm = 0x800
jb 0x43fc
movzwl %si, %eax
cmpl $0xfff, %eax            # imm = 0xFFF
ja 0x43df
addl $0xfffff800, %esi       # imm = 0xFFFFF800
jmp 0x43fc
cmpl $0x17ff, %eax           # imm = 0x17FF
ja 0x43ee
addl $0xfffff000, %esi       # imm = 0xFFFFF000
jmp 0x43fc
leal -0x1800(%rax), %esi
cmpl $0x2000, %eax           # imm = 0x2000
cmovael %eax, %esi
leal -0x2008(%rsi), %edi
movl $0xffff, %ecx           # imm = 0xFFFF
andl %ecx, %edi
movl %esi, %eax
andl $0x2007, %eax           # imm = 0x2007
cmpl $0x1ff8, %edi           # imm = 0x1FF8
cmovael %esi, %eax
andl %eax, %ecx
leal -0x2000(%rcx), %esi
cmpl $0x7, %esi
ja 0x4453
leaq 0x213b(%rip), %rcx      # 0x6568
movslq (%rcx,%rsi,4), %rsi
addq %rcx, %rsi
jmpq *%rsi
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4950
cmpl $0x4014, %ecx           # imm = 0x4014
jne 0x4488
movzbl %dl, %esi
shll $0x8, %esi
addq %rbx, %rsi
movq %rsp, %r14
movl $0x100, %edx            # imm = 0x100
movq %r14, %rdi
callq 0x2110
movq 0x10000(%rbx), %rdi
movq %r14, %rsi
callq 0x4b64
jmp 0x46f3
movzwl %ax, %eax
cmpb $0x1, %dl
jne 0x46dc
cmpl $0x4016, %eax           # imm = 0x4016
jne 0x46dc
movw $0x0, 0x10008(%rbx)
movq 0x10010(%rbx), %rdi
callq 0x2130
testl %eax, %eax
je 0x461d
movq %rsp, %r14
leaq 0x20c2(%rip), %r15      # 0x6588
leaq 0x20d3(%rip), %r12      # 0x65a0
movq 0x10010(%rbx), %rdi
movq %r14, %rsi
callq 0x21c0
movl (%rsp), %eax
cmpl $0x2, %eax
je 0x451e
cmpl $0x3, %eax
jne 0x4609
movl 0x54(%rsp), %eax
cmpl $0x34, %eax
jg 0x4547
cmpl $0x16, %eax
je 0x4583
cmpl $0x24, %eax
je 0x4597
cmpl $0x34, %eax
jne 0x4609
movb 0x1000a(%rbx), %al
andb $-0x2, %al
jmp 0x4603
movl 0x54(%rsp), %eax
cmpl $0x34, %eax
jg 0x4565
cmpl $0x16, %eax
je 0x458d
cmpl $0x24, %eax
je 0x45a1
cmpl $0x34, %eax
jne 0x4609
movb 0x1000a(%rbx), %al
orb $0x1, %al
jmp 0x4603
leal -0x6f(%rax), %ecx
cmpl $0x5, %ecx
ja 0x45ab
movslq (%r12,%rcx,4), %rax
addq %r12, %rax
jmpq *%rax
movb 0x1000a(%rbx), %al
andb $-0x11, %al
jmp 0x4603
leal -0x6f(%rax), %ecx
cmpl $0x5, %ecx
ja 0x45ba
movslq (%r15,%rcx,4), %rax
addq %r15, %rax
jmpq *%rax
movb 0x1000a(%rbx), %al
orb $0x10, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
andb $-0x5, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
orb $0x4, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
andb $-0x9, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
orb $0x8, %al
jmp 0x4603
cmpl $0x35, %eax
jne 0x4609
movb 0x1000a(%rbx), %al
andb $-0x3, %al
jmp 0x4603
cmpl $0x35, %eax
jne 0x4609
movb 0x1000a(%rbx), %al
orb $0x2, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
andb $-0x21, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
orb $0x20, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
andb $-0x41, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
andb $0x7f, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
orb $0x40, %al
jmp 0x4603
movb 0x1000a(%rbx), %al
orb $-0x80, %al
movb %al, 0x1000a(%rbx)
movq 0x10010(%rbx), %rdi
callq 0x2130
testl %eax, %eax
jne 0x44cd
movb 0x1000a(%rbx), %al
movb %al, 0x10008(%rbx)
jmp 0x46f3
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4a4a
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4ae6
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4b4e
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4b84
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4b8c
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x496e
testb %dl, %dl
jne 0x46f0
cmpl $0x4016, %eax           # imm = 0x4016
jne 0x46f0
movb $0x1, 0x10009(%rbx)
jmp 0x46f3
movb %dl, (%rbx,%rax)
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
retq
nop