// File: khedoros[P]khednes/ppu3.cpp
// Function: ppu::reg_read(unsigned int, unsigned int)
unsigned char ppu::reg_read(const unsigned int addr, unsigned int cycle) {
    //cout<<"!! "<<phases[phase(cycle)]<<" Read address: 0x"<<hex<<addr<<dec<<" Cycle: "<<cycle<<endl;
    if(phase(cycle) == RENDER) ++s.reads_during_render;
    unsigned char retval = 0;
    switch(addr) {
    case 0x2002:
        if(!cleared_vsync && (phase(cycle) == VINT || cycle >= cycles_per_frame - 85)) {
            retval |= 0x80;
            cleared_vsync = true;
            //TODO: Reduce reliance on hard-coded cycle counts
            if(cycle >= cycles_per_frame - 85) late_vsync_clear = true;
        }
        if(s0_hit_cycle(cycle) <= cycle) {
            retval |= 0x40;
        }
        if(overflow_cycle(cycle) <= cycle) {
            retval |= 0x20;
        }
        scroll_latch = false;
        ++s.twok2_reads;
        break;
    case 0x2004:
        retval = sprites[spraddr/4].val[spraddr%4];
        break;
    case 0x2007:
        //cout<<"0x2007 (0x"<<hex<<vram_ptr.pointer<<dec<<"): (";
        if(vram_ptr.pointer < 0x2000) {
            //cout<<"Reading from Pattern Table)";
            retval = ppu_ram_buffer;
            ppu_ram_buffer = cart.get_cbyte(vram_ptr.pointer);
        }
        else {
            unsigned int ptr = vram_ptr.pointer;
            retval = ppu_ram_buffer;
            if(ptr >= 0x3000 && ptr < 0x3F00) ptr -= 0x1000;
            if(ptr < 0x23C0) {
                //cout<<"Reading from Name Table 0)";
                ppu_ram_buffer = nt[0][ptr - 0x2000];
            }
            else if(ptr < 0x2400) {
                //cout<<"Reading from Attribute Table 0)";
                ppu_ram_buffer = at[0][ptr - 0x23C0];
            }
            else if(ptr < 0x27C0) {
                //cout<<"Reading from Name Table 1)";
                ppu_ram_buffer = nt[1][ptr - 0x2400];
            }
            else if(ptr < 0x2800) {
                //cout<<"Reading from Attribute Table 1)";
                ppu_ram_buffer = at[1][ptr - 0x27C0];
            }
            else if(ptr < 0x2BC0) {
                //cout<<"Reading from Name Table 2)";
                ppu_ram_buffer = nt[2][ptr - 0x2800];
            }
            else if(ptr < 0x2C00) {
                //cout<<"Reading from Attribute Table 2)";
                ppu_ram_buffer = at[2][ptr - 0x2BC0];
            }
            else if(ptr < 0x2FC0) {
                //cout<<"Reading from Name Table 3)";
                ppu_ram_buffer = nt[3][ptr - 0x2C00];
            }
            else if(ptr < 0x3000) {
                //cout<<"Reading from Attribute Table 3)";
                ppu_ram_buffer = at[3][ptr - 0x2FC0];
            }
            else {
                ptr &= 0x1f;
                if(ptr < 0x10) {
                    //cout<<"Reading from Background Palette)";
                }
                else {
                    //cout<<"Reading from Sprite Palette)";
                }
                retval = *(pal[ptr]);
                ppu_ram_buffer = retval;
            }
        }
        //cout<<hex<<": 0x"<<int(retval)<<dec<<endl;
        vram_ptr.pointer++;
        if(control0.v_inc_down) vram_ptr.pointer +=31;
        break;
    default:
        //cout<<"Reading from register 0x"<<hex<<addr<<" isn't handled."<<dec<<endl;
        retval = control1.reg;
        break;
    }
    ++s.reads;
    return retval;
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x30(%rsp)
movl %esi, 0x2c(%rsp)
movl %edx, 0x28(%rsp)
movq 0x30(%rsp), %rdi
movq %rdi, 0x18(%rsp)
movl 0x28(%rsp), %esi
callq 0x1dc80
cmpl $0x3, %eax
jne 0x1e52d
movq 0x18(%rsp), %rax
movl 0x1c0(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x1c0(%rax)
movb $0x0, 0x27(%rsp)
movl 0x2c(%rsp), %eax
movl %eax, 0x14(%rsp)
subl $0x2002, %eax           # imm = 0x2002
je 0x1e568
jmp 0x1e543
movl 0x14(%rsp), %eax
subl $0x2004, %eax           # imm = 0x2004
je 0x1e638
jmp 0x1e554
movl 0x14(%rsp), %eax
subl $0x2007, %eax           # imm = 0x2007
je 0x1e68f
jmp 0x1e963
movq 0x18(%rsp), %rax
testb $0x1, 0x6e3(%rax)
jne 0x1e5d8
movq 0x18(%rsp), %rdi
movl 0x28(%rsp), %esi
callq 0x1dc80
cmpl $0x1, %eax
je 0x1e59f
movq 0x18(%rsp), %rcx
movl 0x28(%rsp), %eax
movl 0x6e8(%rcx), %ecx
subl $0x55, %ecx
cmpl %ecx, %eax
jb 0x1e5d8
movq 0x18(%rsp), %rcx
movzbl 0x27(%rsp), %eax
orl $0x80, %eax
movb %al, 0x27(%rsp)
movb $0x1, 0x6e3(%rcx)
movl 0x28(%rsp), %eax
movl 0x6e8(%rcx), %ecx
subl $0x55, %ecx
cmpl %ecx, %eax
jb 0x1e5d6
movq 0x18(%rsp), %rax
movb $0x1, 0x6e4(%rax)
jmp 0x1e5d8
movq 0x18(%rsp), %rdi
movl 0x28(%rsp), %esi
callq 0x1dd70
cmpl 0x28(%rsp), %eax
ja 0x1e5f8
movzbl 0x27(%rsp), %eax
orl $0x40, %eax
movb %al, 0x27(%rsp)
movq 0x18(%rsp), %rdi
movl 0x28(%rsp), %esi
callq 0x1e240
cmpl 0x28(%rsp), %eax
ja 0x1e618
movzbl 0x27(%rsp), %eax
orl $0x20, %eax
movb %al, 0x27(%rsp)
movq 0x18(%rsp), %rax
movb $0x0, 0x6e2(%rax)
movl 0x1bc(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x1bc(%rax)
jmp 0x1e972
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x208, %rcx            # imm = 0x208
movzbl 0x308(%rax), %eax
movl $0x4, %esi
cltd
idivl %esi
movl %eax, %edx
movq 0x18(%rsp), %rax
movslq %edx, %rdx
shlq $0x2, %rdx
addq %rdx, %rcx
movq %rcx, 0x8(%rsp)
movzbl 0x308(%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movq 0x8(%rsp), %rax
movslq %edx, %rcx
movb (%rax,%rcx), %al
movb %al, 0x27(%rsp)
jmp 0x1e972
movq 0x18(%rsp), %rax
movw 0x6dc(%rax), %ax
andw $0x3fff, %ax            # imm = 0x3FFF
movzwl %ax, %eax
cmpl $0x2000, %eax           # imm = 0x2000
jge 0x1e6e0
movq 0x18(%rsp), %rax
movb 0x6e1(%rax), %cl
movb %cl, 0x27(%rsp)
movq (%rax), %rdi
movw 0x6dc(%rax), %ax
andw $0x3fff, %ax            # imm = 0x3FFF
movzwl %ax, %esi
callq 0x11180
movl %eax, %ecx
movq 0x18(%rsp), %rax
movb %cl, 0x6e1(%rax)
jmp 0x1e8e4
movq 0x18(%rsp), %rax
movw 0x6dc(%rax), %cx
andw $0x3fff, %cx            # imm = 0x3FFF
movzwl %cx, %ecx
movl %ecx, 0x20(%rsp)
movb 0x6e1(%rax), %al
movb %al, 0x27(%rsp)
cmpl $0x3000, 0x20(%rsp)     # imm = 0x3000
jb 0x1e723
cmpl $0x3f00, 0x20(%rsp)     # imm = 0x3F00
jae 0x1e723
movl 0x20(%rsp), %eax
subl $0x1000, %eax           # imm = 0x1000
movl %eax, 0x20(%rsp)
cmpl $0x23c0, 0x20(%rsp)     # imm = 0x23C0
jae 0x1e753
movq 0x18(%rsp), %rax
movq 0x16f0(%rax), %rcx
movl 0x20(%rsp), %edx
subl $0x2000, %edx           # imm = 0x2000
movl %edx, %edx
movb (%rcx,%rdx), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8e2
cmpl $0x2400, 0x20(%rsp)     # imm = 0x2400
jae 0x1e783
movq 0x18(%rsp), %rax
movq 0x1710(%rax), %rcx
movl 0x20(%rsp), %edx
subl $0x23c0, %edx           # imm = 0x23C0
movl %edx, %edx
movb (%rcx,%rdx), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8e0
cmpl $0x27c0, 0x20(%rsp)     # imm = 0x27C0
jae 0x1e7b3
movq 0x18(%rsp), %rax
movq 0x16f8(%rax), %rcx
movl 0x20(%rsp), %edx
subl $0x2400, %edx           # imm = 0x2400
movl %edx, %edx
movb (%rcx,%rdx), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8de
cmpl $0x2800, 0x20(%rsp)     # imm = 0x2800
jae 0x1e7e3
movq 0x18(%rsp), %rax
movq 0x1718(%rax), %rcx
movl 0x20(%rsp), %edx
subl $0x27c0, %edx           # imm = 0x27C0
movl %edx, %edx
movb (%rcx,%rdx), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8dc
cmpl $0x2bc0, 0x20(%rsp)     # imm = 0x2BC0
jae 0x1e813
movq 0x18(%rsp), %rax
movq 0x1700(%rax), %rcx
movl 0x20(%rsp), %edx
subl $0x2800, %edx           # imm = 0x2800
movl %edx, %edx
movb (%rcx,%rdx), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8da
cmpl $0x2c00, 0x20(%rsp)     # imm = 0x2C00
jae 0x1e843
movq 0x18(%rsp), %rax
movq 0x1720(%rax), %rcx
movl 0x20(%rsp), %edx
subl $0x2bc0, %edx           # imm = 0x2BC0
movl %edx, %edx
movb (%rcx,%rdx), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8d8
cmpl $0x2fc0, 0x20(%rsp)     # imm = 0x2FC0
jae 0x1e870
movq 0x18(%rsp), %rax
movq 0x1708(%rax), %rcx
movl 0x20(%rsp), %edx
subl $0x2c00, %edx           # imm = 0x2C00
movl %edx, %edx
movb (%rcx,%rdx), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8d6
cmpl $0x3000, 0x20(%rsp)     # imm = 0x3000
jae 0x1e89d
movq 0x18(%rsp), %rax
movq 0x1728(%rax), %rcx
movl 0x20(%rsp), %edx
subl $0x2fc0, %edx           # imm = 0x2FC0
movl %edx, %edx
movb (%rcx,%rdx), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8d4
movl 0x20(%rsp), %eax
andl $0x1f, %eax
movl %eax, 0x20(%rsp)
cmpl $0x10, 0x20(%rsp)
jae 0x1e8b1
jmp 0x1e8b3
jmp 0x1e8b3
movq 0x18(%rsp), %rax
movl 0x20(%rsp), %ecx
movq 0x1750(%rax,%rcx,8), %rcx
movb (%rcx), %cl
movb %cl, 0x27(%rsp)
movb 0x27(%rsp), %cl
movb %cl, 0x6e1(%rax)
jmp 0x1e8d6
jmp 0x1e8d8
jmp 0x1e8da
jmp 0x1e8dc
jmp 0x1e8de
jmp 0x1e8e0
jmp 0x1e8e2
jmp 0x1e8e4
movq 0x18(%rsp), %rax
movw 0x6dc(%rax), %cx
andw $0x3fff, %cx            # imm = 0x3FFF
movzwl %cx, %ecx
addl $0x1, %ecx
movw %cx, %dx
movw 0x6dc(%rax), %cx
andw $0x3fff, %dx            # imm = 0x3FFF
andw $0xc000, %cx            # imm = 0xC000
orw %dx, %cx
movw %cx, 0x6dc(%rax)
movb 0x21850(%rax), %al
shrb $0x2, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x1e961
movq 0x18(%rsp), %rax
movw 0x6dc(%rax), %cx
andw $0x3fff, %cx            # imm = 0x3FFF
movzwl %cx, %ecx
addl $0x1f, %ecx
movw %cx, %dx
movw 0x6dc(%rax), %cx
andw $0x3fff, %dx            # imm = 0x3FFF
andw $0xc000, %cx            # imm = 0xC000
orw %dx, %cx
movw %cx, 0x6dc(%rax)
jmp 0x1e972
movq 0x18(%rsp), %rax
movb 0x21854(%rax), %al
movb %al, 0x27(%rsp)
movq 0x18(%rsp), %rax
movl 0x1b8(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x1b8(%rax)
movb 0x27(%rsp), %al
addq $0x38, %rsp
retq
nop