// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq %rsi, -0x40(%rsp)
movq %rdi, -0x68(%rsp)
movq 0x8(%rdi), %rdi
movb 0x3c019(%rdi), %al
movb %al, -0x6e(%rsp)
testb $0x10, %al
je 0x50a8
movq 0x8(%rdi), %rax
movq %rax, -0x38(%rsp)
movq -0x40(%rsp), %rcx
leal 0x7(%rcx), %eax
movl %eax, -0x50(%rsp)
leal 0x10(%rcx), %eax
movq %rax, -0x18(%rsp)
leal 0x17(%rcx), %eax
movl %eax, -0x58(%rsp)
xorl %ecx, %ecx
movq %rdi, -0x28(%rsp)
movq -0x38(%rsp), %rax
movq %rcx, -0x30(%rsp)
movzbl (%rax,%rcx,4), %eax
movq %rax, -0x8(%rsp)
cmpl -0x40(%rsp), %eax
jne 0x5096
movq -0x30(%rsp), %rdx
leaq (,%rdx,4), %rax
movq -0x38(%rsp), %rcx
movb 0x3(%rcx,%rdx,4), %dl
movq %rdx, -0x60(%rsp)
movzbl 0x2(%rcx,%rax), %ebp
movzbl 0x1(%rcx,%rax), %eax
movq %rax, -0x48(%rsp)
movb 0x3c010(%rdi), %r9b
testb $0x4, -0x6e(%rsp)
jne 0x4e4b
cmpb $0x9, -0x60(%rsp)
jb 0x5096
movq -0x60(%rsp), %rcx
movzbl %cl, %esi
movl %ebp, %r8d
andl $0x3, %r8d
movq -0x48(%rsp), %rdx
movl %edx, %eax
andb $-0x2, %al
movb %r9b, -0x6d(%rsp)
testb $0x20, %r9b
movzbl %al, %eax
cmovel %edx, %eax
movzbl %al, %eax
shll $0x4, %eax
movq %rax, -0x10(%rsp)
movq (%rdi), %r13
movq %r8, %rax
movq %r8, -0x20(%rsp)
shll $0x2, %eax
movl %eax, -0x6c(%rsp)
addl $0x7, %esi
movl %esi, -0x54(%rsp)
leal 0x7(%rcx), %eax
movl %eax, -0x4c(%rsp)
xorl %r11d, %r11d
movq -0x10(%rsp), %rdx
leaq (%r11,%rdx), %r12
movl -0x50(%rsp), %eax
subl %r11d, %eax
movq -0x8(%rsp), %rcx
addl %r11d, %ecx
testb %bpl, %bpl
leaq 0x8(%r11,%rdx), %r15
movzbl %cl, %r9d
cmovsl %eax, %r9d
movzbl %r9b, %ebx
shll $0x8, %ebx
movl $0x7, %ecx
movq -0x60(%rsp), %rax
movl %eax, %r14d
movl -0x4c(%rsp), %eax
movl %eax, %r8d
movzbl (%r13,%r12), %eax
xorl %esi, %esi
btl %ecx, %eax
setb %sil
movzbl (%r13,%r15), %eax
shrl %cl, %eax
andl $0x1, %eax
leal (%rsi,%rax,2), %esi
testb $0x40, %bpl
movzbl %r14b, %r10d
movzbl %r8b, %eax
cmovel %r10d, %eax
testl %esi, %esi
je 0x4f5e
cmpb $-0x11, %r9b
ja 0x4f5e
orl -0x6c(%rsp), %esi
movzbl 0x3f10(%r13,%rsi), %r10d
movzbl %al, %eax
orl %ebx, %eax
movl %eax, %esi
testb $0x20, %bpl
je 0x4f50
movl 0x10(%rdi,%rsi,4), %eax
movzbl 0x3f00(%r13), %edx
movq -0x68(%rsp), %rdi
cmpl 0x38(%rdi,%rdx,4), %eax
movq -0x28(%rsp), %rdi
jne 0x4f5e
movq -0x68(%rsp), %rax
movl 0x38(%rax,%r10,4), %eax
movl %eax, 0x10(%rdi,%rsi,4)
decb %r8b
incb %r14b
addl $-0x1, %ecx
jb 0x4ee3
incq %r11
cmpq $0x8, %r11
jne 0x4ea0
testb $0x20, -0x6d(%rsp)
je 0x5096
cmpb $0x8, -0x60(%rsp)
ja 0x4fad
testb $0x4, -0x6e(%rsp)
je 0x5096
movq (%rdi), %r13
movq -0x20(%rsp), %rax
leal (,%rax,4), %eax
movzbl %al, %eax
movl %eax, -0x6c(%rsp)
movq -0x48(%rsp), %rsi
orq $0x1, %rsi
shll $0x4, %esi
addl $0x3f04, -0x6c(%rsp)    # imm = 0x3F04
xorl %r12d, %r12d
leaq (%r12,%rsi), %r8
movl -0x58(%rsp), %eax
subl %r12d, %eax
movq -0x18(%rsp), %rcx
addl %r12d, %ecx
testb %bpl, %bpl
leaq 0x8(%r12,%rsi), %r10
cmovsl %eax, %ecx
shll $0x8, %ecx
movzwl %cx, %r9d
movl $0x7, %ecx
movq -0x60(%rsp), %rax
movl %eax, %r11d
movl -0x54(%rsp), %eax
movl %eax, %ebx
movzbl (%r13,%r8), %eax
xorl %edx, %edx
btl %ecx, %eax
setb %dl
movzbl (%r13,%r10), %eax
shrl %cl, %eax
andl $0x1, %eax
leal (%rdx,%rax,2), %eax
testb $0x40, %bpl
movzbl %r11b, %edx
movzbl %bl, %r15d
cmovel %edx, %r15d
testl %eax, %eax
je 0x507b
cmpl $0xefff, %r9d           # imm = 0xEFFF
ja 0x507b
orl -0x6c(%rsp), %eax
movzbl (%r13,%rax), %r14d
movzbl %r15b, %eax
orl %r9d, %eax
movl %eax, %r15d
testb $0x20, %bpl
je 0x506c
movl 0x10(%rdi,%r15,4), %eax
movzbl 0x3f00(%r13), %edx
movq -0x68(%rsp), %rdi
cmpl 0x38(%rdi,%rdx,4), %eax
movq -0x28(%rsp), %rdi
jne 0x507b
movq -0x68(%rsp), %rax
movl 0x38(%rax,%r14,4), %eax
movl %eax, 0x10(%rdi,%r15,4)
decb %bl
incb %r11b
addl $-0x1, %ecx
jb 0x4ffc
incq %r12
cmpq $0x8, %r12
jne 0x4fc4
movq -0x30(%rsp), %rcx
incq %rcx
cmpq $0x40, %rcx
jne 0x4deb
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop