// File: /workspace/github_cpp_makefile_star2_O1/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 0x4424
movzwl %si, %eax
cmpl $0xfff, %eax            # imm = 0xFFF
ja 0x4407
addl $0xfffff800, %esi       # imm = 0xFFFFF800
jmp 0x4424
cmpl $0x17ff, %eax           # imm = 0x17FF
ja 0x4416
addl $0xfffff000, %esi       # imm = 0xFFFFF000
jmp 0x4424
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 0x447b
leaq 0x2113(%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 0x4904
cmpl $0x4014, %ecx           # imm = 0x4014
jne 0x44b0
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 0x4b18
jmp 0x46a8
movzwl %ax, %eax
cmpb $0x1, %dl
jne 0x4691
cmpl $0x4016, %eax           # imm = 0x4016
jne 0x4691
movw $0x0, 0x10008(%rbx)
movq 0x10010(%rbx), %rdi
callq 0x2130
testl %eax, %eax
je 0x45d2
movq %rsp, %r14
leaq 0x20b2(%rip), %r15      # 0x65a0
leaq 0x2093(%rip), %r12      # 0x6588
movq 0x10010(%rbx), %rdi
movq %r14, %rsi
callq 0x21c0
movl (%rsp), %eax
cmpl $0x2, %eax
je 0x456c
cmpl $0x3, %eax
jne 0x45be
movl 0x54(%rsp), %edx
cmpl $0x34, %edx
jg 0x4531
cmpl $0x16, %edx
je 0x4546
cmpl $0x24, %edx
je 0x454a
movb $-0x2, %cl
cmpl $0x34, %edx
je 0x4561
jmp 0x4567
leal -0x6f(%rdx), %ecx
cmpl $0x5, %ecx
ja 0x454e
movslq (%r12,%rcx,4), %rcx
addq %r12, %rcx
jmpq *%rcx
movb $-0x11, %cl
jmp 0x4561
movb $-0x5, %cl
jmp 0x4561
movb $-0x9, %cl
jmp 0x4561
cmpl $0x35, %edx
jne 0x4567
movb $-0x3, %cl
jmp 0x4561
movb $-0x21, %cl
jmp 0x4561
movb $-0x41, %cl
jmp 0x4561
movb $0x7f, %cl
andb %cl, 0x1000a(%rbx)
cmpl $0x2, %eax
jne 0x45be
movl 0x54(%rsp), %ecx
cmpl $0x34, %ecx
jg 0x4588
cmpl $0x16, %ecx
je 0x459d
cmpl $0x24, %ecx
je 0x45a1
movb $0x1, %al
cmpl $0x34, %ecx
je 0x45b8
jmp 0x45be
leal -0x6f(%rcx), %eax
cmpl $0x5, %eax
ja 0x45a5
movslq (%r15,%rax,4), %rax
addq %r15, %rax
jmpq *%rax
movb $0x10, %al
jmp 0x45b8
movb $0x4, %al
jmp 0x45b8
movb $0x8, %al
jmp 0x45b8
cmpl $0x35, %ecx
jne 0x45be
movb $0x2, %al
jmp 0x45b8
movb $0x20, %al
jmp 0x45b8
movb $0x40, %al
jmp 0x45b8
movb $-0x80, %al
orb %al, 0x1000a(%rbx)
movq 0x10010(%rbx), %rdi
callq 0x2130
testl %eax, %eax
jne 0x44f5
movb 0x1000a(%rbx), %al
movb %al, 0x10008(%rbx)
jmp 0x46a8
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x49fe
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4a9a
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4b02
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4b38
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4b40
movq 0x10000(%rbx), %rdi
movzbl %dl, %esi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x4922
testb %dl, %dl
jne 0x46a5
cmpl $0x4016, %eax           # imm = 0x4016
jne 0x46a5
movb $0x1, 0x10009(%rbx)
jmp 0x46a8
movb %dl, (%rbx,%rax)
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r14
popq %r15
retq
nop