// File: NGageMegaman[P]NEScutre/main.cpp
// Function: main
int main() {
    int count = 0, n_scanline;
    unsigned int next_vblank = 89342;
    unsigned int next_vblank_end = 89342 + 7746;
    unsigned int next_sprite = 89342 + 7746 + 340;
    Clock nes_clock;
    Mem_ppu nes_mem_ppu;
    nes_mem_ppu.load_rom("smb.nes");
    Cpu nes_cpu;
    nes_cpu.clock = &nes_clock;
    nes_cpu.mem.mem_ppu = &nes_mem_ppu;
    Ppu nes_ppu;
    nes_ppu.cpu = &nes_cpu;
    nes_ppu.mem_ppu = &nes_mem_ppu;
    nes_cpu.mem.di = nes_ppu.di;
    while(1) {
	    nes_cpu.execute();
	    if (nes_clock.cycles >= next_vblank) {
		//usleep(400000);
		for (int i = 0; i<240; ++i)
		    nes_ppu.drawSprites(i);
		nes_ppu.drawScreen();
		count++;
		n_scanline = 0;
	        next_vblank += 89342;
		next_sprite = next_vblank_end + 340;
	        nes_ppu.vblank();
	    }
	    if (nes_clock.cycles >= next_vblank_end) {
		next_vblank_end = next_vblank + 7746;
		nes_mem_ppu.vblank_end();
		nes_mem_ppu.PPUSTATUS = nes_mem_ppu.PPUSTATUS & 0xbf;
	    }
	    //Draw for each scanline
	    //We assume the first sprite always does s0h
	    if (n_scanline != 0xee && nes_clock.cycles >= next_sprite) {
		nes_ppu.draw(n_scanline);
		nes_ppu.checkSprite0Hit(n_scanline);
		next_sprite = next_sprite + 340;
		n_scanline++;
	    }
	   
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x4c1b0, %rsp          # imm = 0x4C1B0
movl $0x0, -0x4(%rbp)
movl $0x0, -0x8(%rbp)
movl $0x15cfe, -0x10(%rbp)   # imm = 0x15CFE
movl $0x17b40, -0x14(%rbp)   # imm = 0x17B40
movl $0x17c94, -0x18(%rbp)   # imm = 0x17C94
leaq -0x1c(%rbp), %rdi
callq 0x1420
leaq -0x3c040(%rbp), %rdi
callq 0x5240
leaq -0x3c040(%rbp), %rdi
leaq 0xbe4(%rip), %rsi       # 0x7545
callq 0x5560
leaq -0x4c070(%rbp), %rdi
callq 0x1440
leaq -0x1c(%rbp), %rax
movq %rax, -0x4c070(%rbp)
leaq -0x3c040(%rbp), %rax
movq %rax, -0x3c068(%rbp)
leaq -0x4c1a8(%rbp), %rdi
callq 0x5bd0
leaq -0x4c070(%rbp), %rax
movq %rax, -0x4c1a8(%rbp)
leaq -0x3c040(%rbp), %rax
movq %rax, -0x4c1a0(%rbp)
movq -0x4c198(%rbp), %rax
movq %rax, -0x3c058(%rbp)
leaq -0x4c070(%rbp), %rdi
callq 0x14e0
movl -0x1c(%rbp), %eax
cmpl -0x10(%rbp), %eax
jb 0x6a4c
movl $0x0, -0x4c1ac(%rbp)
cmpl $0xf0, -0x4c1ac(%rbp)
jge 0x6a0e
movl -0x4c1ac(%rbp), %esi
leaq -0x4c1a8(%rbp), %rdi
callq 0x5ff0
movl -0x4c1ac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c1ac(%rbp)
jmp 0x69df
leaq -0x4c1a8(%rbp), %rdi
callq 0x6810
movl -0x8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8(%rbp)
movl $0x0, -0xc(%rbp)
movl -0x10(%rbp), %eax
addl $0x15cfe, %eax          # imm = 0x15CFE
movl %eax, -0x10(%rbp)
movl -0x14(%rbp), %eax
addl $0x154, %eax            # imm = 0x154
movl %eax, -0x18(%rbp)
leaq -0x4c1a8(%rbp), %rdi
callq 0x68a0
movl -0x1c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jb 0x6a77
movl -0x10(%rbp), %eax
addl $0x1e42, %eax           # imm = 0x1E42
movl %eax, -0x14(%rbp)
leaq -0x3c040(%rbp), %rdi
callq 0x5ba0
movzbl -0x2b(%rbp), %eax
andl $0xbf, %eax
movb %al, -0x2b(%rbp)
cmpl $0xee, -0xc(%rbp)
je 0x6aba
movl -0x1c(%rbp), %eax
cmpl -0x18(%rbp), %eax
jb 0x6aba
movl -0xc(%rbp), %esi
leaq -0x4c1a8(%rbp), %rdi
callq 0x64e0
movl -0xc(%rbp), %esi
leaq -0x4c1a8(%rbp), %rdi
callq 0x5fa0
movl -0x18(%rbp), %eax
addl $0x154, %eax            # imm = 0x154
movl %eax, -0x18(%rbp)
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x69c1