// File: nicoeps[P]NicoGB/src/memory.cpp
// Function: Memory::read(unsigned short)
uint8_t Memory::read(uint16_t address) {
    if (address < 0x100 && bootEnabled) {
        return boot[address];
    } else if (address <= 0x7FFF && cartridge.loaded == true) {
        return cartridge.read(address);
    } else if (address >= 0x8000 && address <= 0x9FFF) {
        return vram[address - 0x8000];
    } else if (address >= 0xA000 && address <= 0xBFFF) {
        return cartridge.read(address);
    } else if (address >= 0xC000 && address <= 0xDFFF) {
        return wram[address - 0xC000];
    } else if (address >= 0xE000 && address <= 0xFDFF) {
        return wram[address - 0xE000];
    } else if (address >= 0xFE00 && address <= 0xFE9F) {
        return oam[address - 0xFE00];
    } else if ((address >= 0xFF00 && address <= 0xFF7F) || address == 0xFFFF) {
        switch (address) {
            case 0xFF00: return joypad.read();
            case 0xFF04: return timer.divider;
            case 0xFF05: return timer.tima;
            case 0xFF06: return timer.tma;
            case 0xFF07: return timer.tac | 0xF8;
            case 0xFF13: return 0xFF; // NR13
            case 0xFF40: return lcd.lcdc;
            case 0xFF41: return lcd.stat | 0x80;
            case 0xFF42: return lcd.scy;
            case 0xFF43: return lcd.scx;
            case 0xFF44: return lcd.ly;
            case 0xFF45: return lcd.lyc;
            case 0xFF47: return lcd.bgp;
            case 0xFF48: return lcd.obp0;
            case 0xFF49: return lcd.obp1;
            case 0xFF4A: return lcd.wy;
            case 0xFF4B: return lcd.wx;
            case 0xFFFF: return io[0xFF]; // IE
            case 0xFF0F: return io[0x0F] | 0xE0; // IF
            default:     return io[address - 0xFF00];
        }
    } else if (address >= 0xFF80 && address <= 0xFFFE) {
        return hram[address - 0xFF80];
    } else {
        return 0xFF;
    }
}

// Assembly:
subq $0x28, %rsp
movw %si, %ax
movq %rdi, 0x18(%rsp)
movw %ax, 0x16(%rsp)
movq 0x18(%rsp), %rax
movq %rax, 0x8(%rsp)
movzwl 0x16(%rsp), %eax
cmpl $0x100, %eax            # imm = 0x100
jge 0xefd5
movq 0x8(%rsp), %rax
testb $0x1, 0x23(%rax)
je 0xefd5
movq 0x8(%rsp), %rdi
addq $0xa0, %rdi
movzwl 0x16(%rsp), %eax
movl %eax, %esi
callq 0x40f0
movb (%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movzwl 0x16(%rsp), %eax
cmpl $0x7fff, %eax           # imm = 0x7FFF
jg 0xf011
movq 0x8(%rsp), %rax
movq (%rax), %rax
movb 0x20(%rax), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x1, %eax
jne 0xf011
movq 0x8(%rsp), %rax
movq (%rax), %rdi
movzwl 0x16(%rsp), %esi
callq 0x3e40
movb %al, 0x27(%rsp)
jmp 0xf490
movzwl 0x16(%rsp), %eax
cmpl $0x8000, %eax           # imm = 0x8000
jl 0xf04f
movzwl 0x16(%rsp), %eax
cmpl $0x9fff, %eax           # imm = 0x9FFF
jg 0xf04f
movq 0x8(%rsp), %rdi
addq $0x28, %rdi
movzwl 0x16(%rsp), %eax
subl $0x8000, %eax           # imm = 0x8000
movslq %eax, %rsi
callq 0x40f0
movb (%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movzwl 0x16(%rsp), %eax
cmpl $0xa000, %eax           # imm = 0xA000
jl 0xf082
movzwl 0x16(%rsp), %eax
cmpl $0xbfff, %eax           # imm = 0xBFFF
jg 0xf082
movq 0x8(%rsp), %rax
movq (%rax), %rdi
movzwl 0x16(%rsp), %esi
callq 0x3e40
movb %al, 0x27(%rsp)
jmp 0xf490
movzwl 0x16(%rsp), %eax
cmpl $0xc000, %eax           # imm = 0xC000
jl 0xf0c0
movzwl 0x16(%rsp), %eax
cmpl $0xdfff, %eax           # imm = 0xDFFF
jg 0xf0c0
movq 0x8(%rsp), %rdi
addq $0x40, %rdi
movzwl 0x16(%rsp), %eax
subl $0xc000, %eax           # imm = 0xC000
movslq %eax, %rsi
callq 0x40f0
movb (%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movzwl 0x16(%rsp), %eax
cmpl $0xe000, %eax           # imm = 0xE000
jl 0xf0fe
movzwl 0x16(%rsp), %eax
cmpl $0xfdff, %eax           # imm = 0xFDFF
jg 0xf0fe
movq 0x8(%rsp), %rdi
addq $0x40, %rdi
movzwl 0x16(%rsp), %eax
subl $0xe000, %eax           # imm = 0xE000
movslq %eax, %rsi
callq 0x40f0
movb (%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movzwl 0x16(%rsp), %eax
cmpl $0xfe00, %eax           # imm = 0xFE00
jl 0xf13c
movzwl 0x16(%rsp), %eax
cmpl $0xfe9f, %eax           # imm = 0xFE9F
jg 0xf13c
movq 0x8(%rsp), %rdi
addq $0x58, %rdi
movzwl 0x16(%rsp), %eax
subl $0xfe00, %eax           # imm = 0xFE00
movslq %eax, %rsi
callq 0x40f0
movb (%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movzwl 0x16(%rsp), %eax
cmpl $0xff00, %eax           # imm = 0xFF00
jl 0xf154
movzwl 0x16(%rsp), %eax
cmpl $0xff7f, %eax           # imm = 0xFF7F
jle 0xf164
movzwl 0x16(%rsp), %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
jne 0xf44d
movzwl 0x16(%rsp), %eax
movl %eax, 0x4(%rsp)
subl $0xff00, %eax           # imm = 0xFF00
je 0xf2af
jmp 0xf17a
movl 0x4(%rsp), %eax
subl $0xff04, %eax           # imm = 0xFF04
je 0xf2c6
jmp 0xf18b
movl 0x4(%rsp), %eax
subl $0xff05, %eax           # imm = 0xFF05
je 0xf2db
jmp 0xf19c
movl 0x4(%rsp), %eax
subl $0xff06, %eax           # imm = 0xFF06
je 0xf2f0
jmp 0xf1ad
movl 0x4(%rsp), %eax
subl $0xff07, %eax           # imm = 0xFF07
je 0xf305
jmp 0xf1be
movl 0x4(%rsp), %eax
subl $0xff0f, %eax           # imm = 0xFF0F
je 0xf409
jmp 0xf1cf
movl 0x4(%rsp), %eax
subl $0xff13, %eax           # imm = 0xFF13
je 0xf320
jmp 0xf1e0
movl 0x4(%rsp), %eax
subl $0xff40, %eax           # imm = 0xFF40
je 0xf32a
jmp 0xf1f1
movl 0x4(%rsp), %eax
subl $0xff41, %eax           # imm = 0xFF41
je 0xf33b
jmp 0xf202
movl 0x4(%rsp), %eax
subl $0xff42, %eax           # imm = 0xFF42
je 0xf352
jmp 0xf213
movl 0x4(%rsp), %eax
subl $0xff43, %eax           # imm = 0xFF43
je 0xf363
jmp 0xf224
movl 0x4(%rsp), %eax
subl $0xff44, %eax           # imm = 0xFF44
je 0xf374
jmp 0xf235
movl 0x4(%rsp), %eax
subl $0xff45, %eax           # imm = 0xFF45
je 0xf385
jmp 0xf246
movl 0x4(%rsp), %eax
subl $0xff47, %eax           # imm = 0xFF47
je 0xf396
jmp 0xf257
movl 0x4(%rsp), %eax
subl $0xff48, %eax           # imm = 0xFF48
je 0xf3a7
jmp 0xf268
movl 0x4(%rsp), %eax
subl $0xff49, %eax           # imm = 0xFF49
je 0xf3b8
jmp 0xf279
movl 0x4(%rsp), %eax
subl $0xff4a, %eax           # imm = 0xFF4A
je 0xf3c9
jmp 0xf28a
movl 0x4(%rsp), %eax
subl $0xff4b, %eax           # imm = 0xFF4B
je 0xf3da
jmp 0xf29b
movl 0x4(%rsp), %eax
subl $0xffff, %eax           # imm = 0xFFFF
je 0xf3eb
jmp 0xf42a
movq 0x8(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0xc500
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movq 0x10(%rax), %rax
movb 0x1(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movq 0x10(%rax), %rax
movb 0x2(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movq 0x10(%rax), %rax
movb 0x3(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movq 0x10(%rax), %rax
movzbl 0x4(%rax), %eax
orl $0xf8, %eax
movb %al, 0x27(%rsp)
jmp 0xf490
movb $-0x1, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x18(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movzbl 0x19(%rax), %eax
orl $0x80, %eax
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x1a(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x1b(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x1c(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x1d(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x1e(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x1f(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x20(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x21(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rax
movb 0x22(%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rdi
addq $0x70, %rdi
movl $0xff, %esi
callq 0x40f0
movb (%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rdi
addq $0x70, %rdi
movl $0xf, %esi
callq 0x40f0
movzbl (%rax), %eax
orl $0xe0, %eax
movb %al, 0x27(%rsp)
jmp 0xf490
movq 0x8(%rsp), %rdi
addq $0x70, %rdi
movzwl 0x16(%rsp), %eax
subl $0xff00, %eax           # imm = 0xFF00
movslq %eax, %rsi
callq 0x40f0
movb (%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movzwl 0x16(%rsp), %eax
cmpl $0xff80, %eax           # imm = 0xFF80
jl 0xf48b
movzwl 0x16(%rsp), %eax
cmpl $0xfffe, %eax           # imm = 0xFFFE
jg 0xf48b
movq 0x8(%rsp), %rdi
addq $0x88, %rdi
movzwl 0x16(%rsp), %eax
subl $0xff80, %eax           # imm = 0xFF80
movslq %eax, %rsi
callq 0x40f0
movb (%rax), %al
movb %al, 0x27(%rsp)
jmp 0xf490
movb $-0x1, 0x27(%rsp)
movb 0x27(%rsp), %al
addq $0x28, %rsp
retq
nopl (%rax)