// File: NGageMegaman[P]NEScutre/src/ppu.cpp
// Function: Ppu::drawSprites(int)
void Ppu::drawSprites(int n_scanline) {
    //Select what events the window will listen to
    uint8_t index, attribute, palette;
    int pos_x, pos_y;
    unsigned int patterntable, line_addr, h_offset, large_sprite;
    bool flip_h, flip_v, priority;

    //Show sprites ppumask bit
    if ((mem_ppu->PPUMASK >> 4)&1) {
	for (int i = 0; i<64; ++i) {
	    pos_y     = mem_ppu->oam[(i*4) + 0];
	    index     = mem_ppu->oam[(i*4) + 1];
	    attribute = mem_ppu->oam[(i*4) + 2];
	    pos_x     = mem_ppu->oam[(i*4) + 3];

	    if (n_scanline == pos_y) {

	    	palette = attribute & 3;
	    	priority = (attribute >> 5) & 1;
	    	flip_h = (attribute >> 6) & 1;
	    	flip_v = (attribute >> 7) & 1;

	    	large_sprite = (mem_ppu->PPUCTRL >> 5) & 1;
	    	if (large_sprite) {
	    	    patterntable = index & 1;
	    	    index = index & 0xfe;
	    	}
	    	else {
	    	    patterntable = (mem_ppu->PPUCTRL >> 3) & 1;
	    	}

	    	if (patterntable)
	    	    index += 256;

	    	if (pos_x > 8 || ((mem_ppu->PPUMASK >> 2)&1)) {
	    	    for (int i2 = 0; i2<8; ++i2) {
	    	        for (int j2 = 0; j2<8; ++j2) {
			    line_addr = (index * 16) + i2;
	    	            h_offset = (7-j2);
	    	            unsigned char bitplane =
	    	                (((mem_ppu->ram[line_addr])>>h_offset)&1) +
	    	               ((((mem_ppu->ram[line_addr+8])>>h_offset)&1)<<1);
            	            
	    	            unsigned char color = mem_ppu->ram[0x3f10 + (palette << 2) + bitplane];
	    	    	    uint8_t tmp_pos_x;
	    	    	    uint8_t tmp_pos_y;
	    	    	    if (flip_h)
	    	    	        tmp_pos_x = pos_x + 7 - j2;
	    	    	    else
	    	    	        tmp_pos_x = pos_x + j2;
	    	    	    if (flip_v)
	    	    	        tmp_pos_y = pos_y + 7 - i2;
	    	    	    else
	    	    	        tmp_pos_y = pos_y + i2;

			    int position = (tmp_pos_y*256) + tmp_pos_x;
			    if (bitplane != 0 && position < 61440) {
				if (priority == 0) {
				    mem_ppu->vram[position] = colors[color];
				}
				else if (mem_ppu->vram[position] == colors[mem_ppu->ram[0x3f00]]) {
				    mem_ppu->vram[position] = colors[color];
				}
			    }
	    	        }
	    	    }
	    	}

	    	if (large_sprite) {
	    	    index += 1;
	    	    pos_y += 16;
	    	    if (pos_x > 8 || ((mem_ppu->PPUMASK >> 2)&1)) {
	    	        for (int i2 = 0; i2<8; ++i2) {
	    		    for (int j2 = 0; j2<8; ++j2) {
				line_addr = (index * 16) + i2;
	    		        h_offset = (7-j2);
	    		        unsigned char bitplane =
	    		            (((mem_ppu->ram[line_addr])>>h_offset)&1) +
	    		           ((((mem_ppu->ram[line_addr+8])>>h_offset)&1)<<1);
            		            
	    		        unsigned char color = mem_ppu->ram[0x3f00 + (palette << 2) + 0x04 + bitplane];
			        uint8_t tmp_pos_x;
			        uint8_t tmp_pos_y;
	    	    	        if (flip_h)
				    tmp_pos_x = pos_x + 7 - j2;
	    	    	        else
				    tmp_pos_x = pos_x + j2;
	    	    	        if (flip_v)
				    tmp_pos_y = pos_y + 7 - i2;
	    	    	        else
				    tmp_pos_y = pos_y + i2;

				int position = (tmp_pos_y*256) + tmp_pos_x;

			    	if (bitplane != 0 && position < 61440) {
			    	    if (priority == 0) {
					mem_ppu->vram[position] = colors[color];
			    	    }
			    	    else if (mem_ppu->vram[position] == colors[mem_ppu->ram[0x3f00]]) {
					mem_ppu->vram[position] = colors[color];
			    	    }
			    	}
	    		    }
	    		}
	    	    }
	    	}
	    }
	}
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x58(%rbp)
movq 0x8(%rax), %rax
movzbl 0x3c019(%rax), %eax
sarl $0x4, %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x64de
movl $0x0, -0x30(%rbp)
cmpl $0x40, -0x30(%rbp)
jge 0x64dc
movq -0x58(%rbp), %rax
movq 0x8(%rax), %rcx
movq 0x8(%rcx), %rcx
movl -0x30(%rbp), %edx
shll $0x2, %edx
addl $0x0, %edx
movslq %edx, %rdx
movzbl (%rcx,%rdx), %ecx
movl %ecx, -0x18(%rbp)
movq 0x8(%rax), %rcx
movq 0x8(%rcx), %rcx
movl -0x30(%rbp), %edx
shll $0x2, %edx
addl $0x1, %edx
movslq %edx, %rdx
movb (%rcx,%rdx), %cl
movb %cl, -0xd(%rbp)
movq 0x8(%rax), %rcx
movq 0x8(%rcx), %rcx
movl -0x30(%rbp), %edx
shll $0x2, %edx
addl $0x2, %edx
movslq %edx, %rdx
movb (%rcx,%rdx), %cl
movb %cl, -0xe(%rbp)
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movl -0x30(%rbp), %ecx
shll $0x2, %ecx
addl $0x3, %ecx
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, -0x14(%rbp)
movl -0xc(%rbp), %eax
cmpl -0x18(%rbp), %eax
jne 0x64cc
movq -0x58(%rbp), %rax
movzbl -0xe(%rbp), %ecx
andl $0x3, %ecx
movb %cl, -0xf(%rbp)
movzbl -0xe(%rbp), %ecx
sarl $0x5, %ecx
andl $0x1, %ecx
cmpl $0x0, %ecx
setne %cl
andb $0x1, %cl
movb %cl, -0x2b(%rbp)
movzbl -0xe(%rbp), %ecx
sarl $0x6, %ecx
andl $0x1, %ecx
cmpl $0x0, %ecx
setne %cl
andb $0x1, %cl
movb %cl, -0x29(%rbp)
movzbl -0xe(%rbp), %ecx
sarl $0x7, %ecx
andl $0x1, %ecx
cmpl $0x0, %ecx
setne %cl
andb $0x1, %cl
movb %cl, -0x2a(%rbp)
movq 0x8(%rax), %rax
movzbl 0x3c010(%rax), %eax
sarl $0x5, %eax
andl $0x1, %eax
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
je 0x612a
movzbl -0xd(%rbp), %eax
andl $0x1, %eax
movl %eax, -0x1c(%rbp)
movzbl -0xd(%rbp), %eax
andl $0xfe, %eax
movb %al, -0xd(%rbp)
jmp 0x6142
movq -0x58(%rbp), %rax
movq 0x8(%rax), %rax
movzbl 0x3c010(%rax), %eax
sarl $0x3, %eax
andl $0x1, %eax
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
je 0x6154
movzbl -0xd(%rbp), %eax
addl $0x100, %eax            # imm = 0x100
movb %al, -0xd(%rbp)
cmpl $0x8, -0x14(%rbp)
jg 0x6178
movq -0x58(%rbp), %rax
movq 0x8(%rax), %rax
movzbl 0x3c019(%rax), %eax
sarl $0x2, %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x62fe
movl $0x0, -0x34(%rbp)
cmpl $0x8, -0x34(%rbp)
jge 0x62fc
movl $0x0, -0x38(%rbp)
cmpl $0x8, -0x38(%rbp)
jge 0x62ec
movq -0x58(%rbp), %rax
movzbl -0xd(%rbp), %ecx
shll $0x4, %ecx
addl -0x34(%rbp), %ecx
movl %ecx, -0x20(%rbp)
movl $0x7, %ecx
subl -0x38(%rbp), %ecx
movl %ecx, -0x24(%rbp)
movq 0x8(%rax), %rcx
movq (%rcx), %rcx
movl -0x20(%rbp), %edx
movzbl (%rcx,%rdx), %edx
movl -0x24(%rbp), %ecx
sarl %cl, %edx
movl %edx, %ecx
andl $0x1, %ecx
movl %ecx, -0x5c(%rbp)
movq 0x8(%rax), %rcx
movq (%rcx), %rcx
movl -0x20(%rbp), %edx
addl $0x8, %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %edx
movl -0x24(%rbp), %ecx
sarl %cl, %edx
movl -0x5c(%rbp), %ecx
andl $0x1, %edx
shll %edx
addl %edx, %ecx
movb %cl, -0x39(%rbp)
movq 0x8(%rax), %rax
movq (%rax), %rax
movzbl -0xf(%rbp), %ecx
shll $0x2, %ecx
addl $0x3f10, %ecx           # imm = 0x3F10
movzbl -0x39(%rbp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %al
movb %al, -0x3a(%rbp)
testb $0x1, -0x29(%rbp)
je 0x622d
movl -0x14(%rbp), %eax
addl $0x7, %eax
subl -0x38(%rbp), %eax
movb %al, -0x3b(%rbp)
jmp 0x6236
movl -0x14(%rbp), %eax
addl -0x38(%rbp), %eax
movb %al, -0x3b(%rbp)
testb $0x1, -0x2a(%rbp)
je 0x624a
movl -0x18(%rbp), %eax
addl $0x7, %eax
subl -0x34(%rbp), %eax
movb %al, -0x3c(%rbp)
jmp 0x6253
movl -0x18(%rbp), %eax
addl -0x34(%rbp), %eax
movb %al, -0x3c(%rbp)
movzbl -0x3c(%rbp), %eax
shll $0x8, %eax
movzbl -0x3b(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x40(%rbp)
movzbl -0x39(%rbp), %eax
cmpl $0x0, %eax
je 0x62dc
cmpl $0xf000, -0x40(%rbp)    # imm = 0xF000
jge 0x62dc
movb -0x2b(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x629c
movq -0x58(%rbp), %rax
movzbl -0x3a(%rbp), %ecx
movl 0x38(%rax,%rcx,4), %edx
movq 0x8(%rax), %rax
movslq -0x40(%rbp), %rcx
movl %edx, 0x10(%rax,%rcx,4)
jmp 0x62da
movq -0x58(%rbp), %rcx
movq 0x8(%rcx), %rax
movslq -0x40(%rbp), %rdx
movl 0x10(%rax,%rdx,4), %eax
movq 0x8(%rcx), %rdx
movq (%rdx), %rdx
movzbl 0x3f00(%rdx), %edx
cmpl 0x38(%rcx,%rdx,4), %eax
jne 0x62d8
movq -0x58(%rbp), %rax
movzbl -0x3a(%rbp), %ecx
movl 0x38(%rax,%rcx,4), %edx
movq 0x8(%rax), %rax
movslq -0x40(%rbp), %rcx
movl %edx, 0x10(%rax,%rcx,4)
jmp 0x62da
jmp 0x62dc
jmp 0x62de
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x6190
jmp 0x62ee
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x617f
jmp 0x62fe
cmpl $0x0, -0x28(%rbp)
je 0x64ca
movzbl -0xd(%rbp), %eax
addl $0x1, %eax
movb %al, -0xd(%rbp)
movl -0x18(%rbp), %eax
addl $0x10, %eax
movl %eax, -0x18(%rbp)
cmpl $0x8, -0x14(%rbp)
jg 0x633f
movq -0x58(%rbp), %rax
movq 0x8(%rax), %rax
movzbl 0x3c019(%rax), %eax
sarl $0x2, %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x64c8
movl $0x0, -0x44(%rbp)
cmpl $0x8, -0x44(%rbp)
jge 0x64c6
movl $0x0, -0x48(%rbp)
cmpl $0x8, -0x48(%rbp)
jge 0x64b6
movq -0x58(%rbp), %rax
movzbl -0xd(%rbp), %ecx
shll $0x4, %ecx
addl -0x44(%rbp), %ecx
movl %ecx, -0x20(%rbp)
movl $0x7, %ecx
subl -0x48(%rbp), %ecx
movl %ecx, -0x24(%rbp)
movq 0x8(%rax), %rcx
movq (%rcx), %rcx
movl -0x20(%rbp), %edx
movzbl (%rcx,%rdx), %edx
movl -0x24(%rbp), %ecx
sarl %cl, %edx
movl %edx, %ecx
andl $0x1, %ecx
movl %ecx, -0x60(%rbp)
movq 0x8(%rax), %rcx
movq (%rcx), %rcx
movl -0x20(%rbp), %edx
addl $0x8, %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %edx
movl -0x24(%rbp), %ecx
sarl %cl, %edx
movl -0x60(%rbp), %ecx
andl $0x1, %edx
shll %edx
addl %edx, %ecx
movb %cl, -0x49(%rbp)
movq 0x8(%rax), %rax
movq (%rax), %rax
movzbl -0xf(%rbp), %ecx
shll $0x2, %ecx
addl $0x3f00, %ecx           # imm = 0x3F00
addl $0x4, %ecx
movzbl -0x49(%rbp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %al
movb %al, -0x4a(%rbp)
testb $0x1, -0x29(%rbp)
je 0x63f7
movl -0x14(%rbp), %eax
addl $0x7, %eax
subl -0x48(%rbp), %eax
movb %al, -0x4b(%rbp)
jmp 0x6400
movl -0x14(%rbp), %eax
addl -0x48(%rbp), %eax
movb %al, -0x4b(%rbp)
testb $0x1, -0x2a(%rbp)
je 0x6414
movl -0x18(%rbp), %eax
addl $0x7, %eax
subl -0x44(%rbp), %eax
movb %al, -0x4c(%rbp)
jmp 0x641d
movl -0x18(%rbp), %eax
addl -0x44(%rbp), %eax
movb %al, -0x4c(%rbp)
movzbl -0x4c(%rbp), %eax
shll $0x8, %eax
movzbl -0x4b(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x50(%rbp)
movzbl -0x49(%rbp), %eax
cmpl $0x0, %eax
je 0x64a6
cmpl $0xf000, -0x50(%rbp)    # imm = 0xF000
jge 0x64a6
movb -0x2b(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x6466
movq -0x58(%rbp), %rax
movzbl -0x4a(%rbp), %ecx
movl 0x38(%rax,%rcx,4), %edx
movq 0x8(%rax), %rax
movslq -0x50(%rbp), %rcx
movl %edx, 0x10(%rax,%rcx,4)
jmp 0x64a4
movq -0x58(%rbp), %rcx
movq 0x8(%rcx), %rax
movslq -0x50(%rbp), %rdx
movl 0x10(%rax,%rdx,4), %eax
movq 0x8(%rcx), %rdx
movq (%rdx), %rdx
movzbl 0x3f00(%rdx), %edx
cmpl 0x38(%rcx,%rdx,4), %eax
jne 0x64a2
movq -0x58(%rbp), %rax
movzbl -0x4a(%rbp), %ecx
movl 0x38(%rax,%rcx,4), %edx
movq 0x8(%rax), %rax
movslq -0x50(%rbp), %rcx
movl %edx, 0x10(%rax,%rcx,4)
jmp 0x64a4
jmp 0x64a6
jmp 0x64a8
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x6357
jmp 0x64b8
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x6346
jmp 0x64c8
jmp 0x64ca
jmp 0x64cc
jmp 0x64ce
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x6024
jmp 0x64de
popq %rbp
retq