// File: khedoros[P]khednes/ppu3.cpp
// Function: ppu::calc()
int ppu::calc() {

    int crom_update = cart.changed_crom();
    if((crom_update&1) == 1) clear_surfaces(false);
    if((crom_update&2) == 2) clear_surfaces(true);

    //cout<<"Total cycles: "<<s.cycles<<" Total frames: "<<frame<<endl;
    s.cycles += cycles_per_frame;
    ++frame;

    if(!late_vsync_clear) {
        cleared_vsync = false;
    }
    else late_vsync_clear = false;

    if(frame % 2 == 0) cycles_per_frame = CLK_PER_LINE * LINE_PER_FRAME;
    else cycles_per_frame = CLK_PER_LINE * LINE_PER_FRAME - 1;

    if(table_view) {
        //Draw 64 sprites, always, since I can change the blit location easily in compositor::flip()
        for(int spr=63;spr>=0;--spr) {
            blit_sprite(spr);           
        }
        //Draw the palette
        for(int palnum = 0; palnum < 16; ++palnum) {
            for(int x=palnum*16; x < palnum*16 + 16; ++x)
                for(int y=0; y < 16; ++y) {
                    screen.pset(x,y+480,*pal[palnum]);
                    screen.pset(x,y+496,*pal[palnum+16]);
                }
        }
        //Draw the state of the name table
        for(int table = 0; table < 4; ++table) {
            for(int tile_x = 0; tile_x < 32; ++tile_x) {
                for(int tile_y = 0; tile_y < 30; ++tile_y) {
                    int val = nt[table][tile_y * 32 + tile_x];
                    int pal = get_nt_pal(table, tile_x, tile_y);
                    //screen.erase_nt(x,y);
                    int x_offset = 0;
                    int y_offset = 0;
                    if(table == 1)
                        x_offset = 256;
                    else if(table == 2)
                        y_offset = 240;
                    else if(table == 3) {
                        y_offset=240;
                        x_offset=256;
                    }
                    screen.blit_nt(get_Surface(control0.bg_table, val, pal, 0,0), tile_x*8+x_offset, tile_y*8+y_offset);
                }
            }
        }

        for(int table = 0; table < 2; table++) {
            for(int tile_y = 0; tile_y < 16; tile_y++) {
                for(int tile_x = 0; tile_x < 16; tile_x++) {
                    for(int j=0;j<8;++j) {
                        for(int i=0;i<8;++i) {
                            int x = 768+tile_x*8+i;
                            int y = table*128+tile_y*8+j;
                            int col = get_color(table*256+tile_y*16+tile_x,i,j);
                            int map[] = {74, 64, 67, 71};
                            col = map[col];
                            screen.pset(x, y, col);
                        }
                    }
                }
            }
        }
    }
    else if(control1.bits.show_bg) { //Normal game render

        int xspix = init_scroll_x;
        int yspix = init_scroll_y;

        int xstile = xspix / 8;
        int ystile = yspix / 8;

        int xepix = xspix + 256;
        int xetile = xepix / 8 + 1;

        int yepix = 0;
        //int yetile = 0;

        int curytile = 0;

        unsigned int odd_diff = ((frame % 2 == 0)?0:1);
        bool process = true;
        while(process) {
            if(scroll_shifts.size() > 0) {
                yepix = scroll_shifts.front().second + init_scroll_y;
            }
            else {
                yepix = init_scroll_y + 240;
                process = false;
            }
            int yetile = yepix / 8 + 1;

            for(int yt = ystile; yt < yetile; ++yt) {
                unsigned int curcycle = (unsigned int)((VINT_LINES + PRE_RENDER_LINES) * CLK_PER_LINE - odd_diff) + curytile * 8 * CLK_PER_LINE;
                apply_updates_to(curcycle);

                //Draw sprites that should show by now
                if(control1.bits.show_sprites)
                    for(int i=0;i<64;++i)
                        if(sprites[i].y <= curytile * 8)
                            blit_sprite(i);

                //Draw this line of tiles
                for(int xt = xstile; xt < xetile; ++xt) {
                    int table = ((xt / 32) % 2) + (((yt / 30) % 2) * 2);
                    int tile_x = xt % 32;
                    int tile_y = yt % 30;
                    int pal = get_nt_pal(table, tile_x, tile_y);
                    int val = nt[table][tile_y * 32 + tile_x];
                    screen.blit_nt(get_Surface(control0.bg_table, val, pal, 0, 0), xt*8, yt*8);
                }
                ++curytile;
            }
            //Send that region to compositor to be rendered
            screen.add_nt_area(xspix, yspix, xepix, yepix);

            //Process the rest of the shifts, then delete the entry
            if(scroll_shifts.size() > 0) {
                xspix = scroll_shifts.front().first;
                xstile = xspix / 8;

                xepix = xspix + 256;
                xetile = xepix / 8 + 1;

                yspix = yepix;
                ystile = yetile - 1;
                scroll_shifts.pop_front();
            }
        }
        apply_updates_to(100000); //way past end of frame
    }

    if(control1.bits.show_bg || control1.bits.show_sprites) {
        //Set background color
        screen.fill(*pal[0]);
    }
    //Composite the image and display it
    screen.flip();
    if(control0.generate_vblank) {
        //cout<<"Returning 1 (NMI vblank)"<<endl;
        return 1;
    }
    else {
        //cout<<"Returning 0 (no NMI)"<<endl;
        return 0;
    }
}

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xd8(%rsp)
movq 0xd8(%rsp), %rax
movq %rax, 0x18(%rsp)
movq (%rax), %rdi
callq 0x11220
movl %eax, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
andl $0x1, %eax
cmpl $0x1, %eax
jne 0x1e9d6
movq 0x18(%rsp), %rdi
xorl %esi, %esi
callq 0x1cb70
movl 0xd4(%rsp), %eax
andl $0x2, %eax
cmpl $0x2, %eax
jne 0x1e9f4
movq 0x18(%rsp), %rdi
movl $0x1, %esi
callq 0x1cb70
movq 0x18(%rsp), %rax
movl 0x6e8(%rax), %ecx
addq 0x1d8(%rax), %rcx
movq %rcx, 0x1d8(%rax)
movl 0x2185c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x2185c(%rax)
testb $0x1, 0x6e4(%rax)
jne 0x1ea33
movq 0x18(%rsp), %rax
movb $0x0, 0x6e3(%rax)
jmp 0x1ea3f
movq 0x18(%rsp), %rax
movb $0x0, 0x6e4(%rax)
movq 0x18(%rsp), %rax
movl 0x2185c(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x1ea68
movq 0x18(%rsp), %rax
movl $0x15cfe, 0x6e8(%rax)   # imm = 0x15CFE
jmp 0x1ea77
movq 0x18(%rsp), %rax
movl $0x15cfd, 0x6e8(%rax)   # imm = 0x15CFD
movq 0x18(%rsp), %rax
testb $0x1, 0x21860(%rax)
je 0x1ef54
movl $0x3f, 0xd0(%rsp)
cmpl $0x0, 0xd0(%rsp)
jl 0x1eac2
movq 0x18(%rsp), %rdi
movl 0xd0(%rsp), %esi
callq 0x1f3a0
movl 0xd0(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0xd0(%rsp)
jmp 0x1ea94
movl $0x0, 0xcc(%rsp)
cmpl $0x10, 0xcc(%rsp)
jge 0x1ebdc
movl 0xcc(%rsp), %eax
shll $0x4, %eax
movl %eax, 0xc8(%rsp)
movl 0xc8(%rsp), %eax
movl 0xcc(%rsp), %ecx
shll $0x4, %ecx
addl $0x10, %ecx
cmpl %ecx, %eax
jge 0x1ebc4
movl $0x0, 0xc4(%rsp)
cmpl $0x10, 0xc4(%rsp)
jge 0x1ebac
movq 0x18(%rsp), %rax
movq %rax, %rdi
addq $0x8, %rdi
movl 0xc8(%rsp), %esi
movl 0xc4(%rsp), %edx
addl $0x1e0, %edx            # imm = 0x1E0
movslq 0xcc(%rsp), %rcx
movq 0x1750(%rax,%rcx,8), %rax
movzbl (%rax), %ecx
callq 0x25eb0
movq 0x18(%rsp), %rax
movq %rax, %rdi
addq $0x8, %rdi
movl 0xc8(%rsp), %esi
movl 0xc4(%rsp), %edx
addl $0x1f0, %edx            # imm = 0x1F0
movl 0xcc(%rsp), %ecx
addl $0x10, %ecx
movslq %ecx, %rcx
movq 0x1750(%rax,%rcx,8), %rax
movzbl (%rax), %ecx
callq 0x25eb0
movl 0xc4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc4(%rsp)
jmp 0x1eb13
jmp 0x1ebae
movl 0xc8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc8(%rsp)
jmp 0x1eaec
jmp 0x1ebc6
movl 0xcc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xcc(%rsp)
jmp 0x1eacd
movl $0x0, 0xc0(%rsp)
cmpl $0x4, 0xc0(%rsp)
jge 0x1ed91
movl $0x0, 0xbc(%rsp)
cmpl $0x20, 0xbc(%rsp)
jge 0x1ed79
movl $0x0, 0xb8(%rsp)
cmpl $0x1e, 0xb8(%rsp)
jge 0x1ed61
movq 0x18(%rsp), %rdi
movslq 0xc0(%rsp), %rax
movq 0x16f0(%rdi,%rax,8), %rax
movl 0xb8(%rsp), %ecx
shll $0x5, %ecx
addl 0xbc(%rsp), %ecx
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, 0xb4(%rsp)
movl 0xc0(%rsp), %esi
movl 0xbc(%rsp), %edx
movl 0xb8(%rsp), %ecx
callq 0x1f880
movl %eax, 0xb0(%rsp)
movl $0x0, 0xac(%rsp)
movl $0x0, 0xa8(%rsp)
cmpl $0x1, 0xc0(%rsp)
jne 0x1eca9
movl $0x100, 0xac(%rsp) # imm = 0x100
jmp 0x1ece4
cmpl $0x2, 0xc0(%rsp)
jne 0x1ecc0
movl $0xf0, 0xa8(%rsp)
jmp 0x1ece2
cmpl $0x3, 0xc0(%rsp)
jne 0x1ece0
movl $0xf0, 0xa8(%rsp)
movl $0x100, 0xac(%rsp) # imm = 0x100
jmp 0x1ece2
jmp 0x1ece4
movq 0x18(%rsp), %rdi
movq %rdi, %rax
addq $0x8, %rax
movq %rax, 0x10(%rsp)
movb 0x21850(%rdi), %al
shrb $0x4, %al
andb $0x1, %al
movzbl %al, %esi
movl 0xb4(%rsp), %edx
movl 0xb0(%rsp), %ecx
xorl %r9d, %r9d
movl %r9d, %r8d
callq 0x1df60
movq 0x10(%rsp), %rdi
movq %rax, %rsi
movl 0xbc(%rsp), %edx
shll $0x3, %edx
addl 0xac(%rsp), %edx
movl 0xb8(%rsp), %ecx
shll $0x3, %ecx
addl 0xa8(%rsp), %ecx
callq 0x26130
movl 0xb8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb8(%rsp)
jmp 0x1ec19
jmp 0x1ed63
movl 0xbc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xbc(%rsp)
jmp 0x1ec00
jmp 0x1ed7b
movl 0xc0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc0(%rsp)
jmp 0x1ebe7
movl $0x0, 0xa4(%rsp)
cmpl $0x2, 0xa4(%rsp)
jge 0x1ef4f
movl $0x0, 0xa0(%rsp)
cmpl $0x10, 0xa0(%rsp)
jge 0x1ef37
movl $0x0, 0x9c(%rsp)
cmpl $0x10, 0x9c(%rsp)
jge 0x1ef1f
movl $0x0, 0x98(%rsp)
cmpl $0x8, 0x98(%rsp)
jge 0x1ef07
movl $0x0, 0x94(%rsp)
cmpl $0x8, 0x94(%rsp)
jge 0x1eeef
movq 0x18(%rsp), %rdi
movl 0x9c(%rsp), %eax
shll $0x3, %eax
addl $0x300, %eax            # imm = 0x300
addl 0x94(%rsp), %eax
movl %eax, 0x90(%rsp)
movl 0xa4(%rsp), %eax
shll $0x7, %eax
movl 0xa0(%rsp), %ecx
shll $0x3, %ecx
addl %ecx, %eax
addl 0x98(%rsp), %eax
movl %eax, 0x8c(%rsp)
movl 0xa4(%rsp), %esi
shll $0x8, %esi
movl 0xa0(%rsp), %eax
shll $0x4, %eax
addl %eax, %esi
addl 0x9c(%rsp), %esi
movl 0x94(%rsp), %edx
movl 0x98(%rsp), %ecx
callq 0x1f970
movq 0x18(%rsp), %rdi
movl %eax, 0x88(%rsp)
movq 0xd889(%rip), %rax      # 0x2c720
movq %rax, 0x70(%rsp)
movq 0xd885(%rip), %rax      # 0x2c728
movq %rax, 0x78(%rsp)
movslq 0x88(%rsp), %rax
movl 0x70(%rsp,%rax,4), %eax
movl %eax, 0x88(%rsp)
addq $0x8, %rdi
movl 0x90(%rsp), %esi
movl 0x8c(%rsp), %edx
movl 0x88(%rsp), %ecx
callq 0x25eb0
movl 0x94(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x94(%rsp)
jmp 0x1ee00
jmp 0x1eef1
movl 0x98(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x98(%rsp)
jmp 0x1ede7
jmp 0x1ef09
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x1edce
jmp 0x1ef21
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x1edb5
jmp 0x1ef39
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x1ed9c
jmp 0x1f2fa
movq 0x18(%rsp), %rax
movb 0x21854(%rax), %al
shrb $0x3, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x1f2f8
movq 0x18(%rsp), %rax
movl 0x1e8(%rax), %ecx
movl %ecx, 0x6c(%rsp)
movl 0x1ec(%rax), %eax
movl %eax, 0x68(%rsp)
movl 0x6c(%rsp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, 0x64(%rsp)
movl 0x68(%rsp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, 0x60(%rsp)
movl 0x6c(%rsp), %eax
addl $0x100, %eax            # imm = 0x100
movl %eax, 0x5c(%rsp)
movl 0x5c(%rsp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq 0x18(%rsp), %rax
addl $0x1, %ecx
movl %ecx, 0x58(%rsp)
movl $0x0, 0x54(%rsp)
movl $0x0, 0x50(%rsp)
movl 0x2185c(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl $0x1, %eax
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovel %ecx, %eax
movl %eax, 0x4c(%rsp)
movb $0x1, 0x4b(%rsp)
testb $0x1, 0x4b(%rsp)
je 0x1f2e9
movq 0x18(%rsp), %rdi
addq $0x1f0, %rdi            # imm = 0x1F0
callq 0x20110
cmpq $0x0, %rax
jbe 0x1f04b
movq 0x18(%rsp), %rdi
addq $0x1f0, %rdi            # imm = 0x1F0
callq 0x20170
movq 0x18(%rsp), %rcx
movl 0x4(%rax), %eax
addl 0x1ec(%rcx), %eax
movl %eax, 0x54(%rsp)
jmp 0x1f064
movq 0x18(%rsp), %rax
movl 0x1ec(%rax), %eax
addl $0xf0, %eax
movl %eax, 0x54(%rsp)
movb $0x0, 0x4b(%rsp)
movl 0x54(%rsp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
addl $0x1, %eax
movl %eax, 0x44(%rsp)
movl 0x60(%rsp), %eax
movl %eax, 0x40(%rsp)
movl 0x40(%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x1f243
movq 0x18(%rsp), %rdi
movl $0x1bf9, %eax           # imm = 0x1BF9
subl 0x4c(%rsp), %eax
movl 0x50(%rsp), %ecx
shll $0x3, %ecx
imull $0x155, %ecx, %ecx      # imm = 0x155
addl %ecx, %eax
movl %eax, 0x3c(%rsp)
movl 0x3c(%rsp), %esi
callq 0x1fac0
movq 0x18(%rsp), %rax
movb 0x21854(%rax), %al
shrb $0x4, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x1f11e
movl $0x0, 0x38(%rsp)
cmpl $0x40, 0x38(%rsp)
jge 0x1f11c
movq 0x18(%rsp), %rax
movslq 0x38(%rsp), %rcx
movl 0x208(%rax,%rcx,4), %eax
andl $0xff, %eax
movl 0x50(%rsp), %ecx
shll $0x3, %ecx
cmpl %ecx, %eax
jg 0x1f10d
movq 0x18(%rsp), %rdi
movl 0x38(%rsp), %esi
callq 0x1f3a0
jmp 0x1f10f
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0x1f0d7
jmp 0x1f11e
movl 0x64(%rsp), %eax
movl %eax, 0x34(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x58(%rsp), %eax
jge 0x1f228
movq 0x18(%rsp), %rdi
movl 0x34(%rsp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl $0x2, %ecx
cltd
idivl %ecx
movl %edx, 0x4(%rsp)
movl 0x40(%rsp), %eax
movl $0x1e, %ecx
cltd
idivl %ecx
movl $0x2, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl 0x4(%rsp), %edx
shll %eax
addl %eax, %edx
movl %edx, 0x30(%rsp)
movl 0x34(%rsp), %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl %edx, 0x2c(%rsp)
movl 0x40(%rsp), %eax
movl $0x1e, %ecx
cltd
idivl %ecx
movl %edx, 0x28(%rsp)
movl 0x30(%rsp), %esi
movl 0x2c(%rsp), %edx
movl 0x28(%rsp), %ecx
callq 0x1f880
movq 0x18(%rsp), %rdi
movl %eax, 0x24(%rsp)
movslq 0x30(%rsp), %rax
movq 0x16f0(%rdi,%rax,8), %rax
movl 0x28(%rsp), %ecx
shll $0x5, %ecx
addl 0x2c(%rsp), %ecx
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, 0x20(%rsp)
movq %rdi, %rax
addq $0x8, %rax
movq %rax, 0x8(%rsp)
movb 0x21850(%rdi), %al
shrb $0x4, %al
andb $0x1, %al
movzbl %al, %esi
movl 0x20(%rsp), %edx
movl 0x24(%rsp), %ecx
xorl %r9d, %r9d
movl %r9d, %r8d
callq 0x1df60
movq 0x8(%rsp), %rdi
movq %rax, %rsi
movl 0x34(%rsp), %edx
shll $0x3, %edx
movl 0x40(%rsp), %ecx
shll $0x3, %ecx
callq 0x26130
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0x1f126
movl 0x50(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x50(%rsp)
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x1f07f
movq 0x18(%rsp), %rdi
addq $0x8, %rdi
movl 0x6c(%rsp), %esi
movl 0x68(%rsp), %edx
movl 0x5c(%rsp), %ecx
movl 0x54(%rsp), %r8d
callq 0x26210
movq 0x18(%rsp), %rdi
addq $0x1f0, %rdi            # imm = 0x1F0
callq 0x20110
cmpq $0x0, %rax
jbe 0x1f2e4
movq 0x18(%rsp), %rdi
addq $0x1f0, %rdi            # imm = 0x1F0
callq 0x20170
movq 0x18(%rsp), %rdi
movl (%rax), %eax
movl %eax, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, 0x64(%rsp)
movl 0x6c(%rsp), %eax
addl $0x100, %eax            # imm = 0x100
movl %eax, 0x5c(%rsp)
movl 0x5c(%rsp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
addl $0x1, %eax
movl %eax, 0x58(%rsp)
movl 0x54(%rsp), %eax
movl %eax, 0x68(%rsp)
movl 0x44(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x60(%rsp)
addq $0x1f0, %rdi            # imm = 0x1F0
callq 0x20140
jmp 0x1f004
movq 0x18(%rsp), %rdi
movl $0x186a0, %esi          # imm = 0x186A0
callq 0x1fac0
jmp 0x1f2fa
movq 0x18(%rsp), %rax
movb 0x21854(%rax), %al
shrb $0x3, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x1f32a
movq 0x18(%rsp), %rax
movb 0x21854(%rax), %al
shrb $0x4, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x1f349
movq 0x18(%rsp), %rax
movq %rax, %rdi
addq $0x8, %rdi
movq 0x1750(%rax), %rax
movzbl (%rax), %esi
xorl %eax, %eax
movl %eax, %edx
callq 0x25a20
movq 0x18(%rsp), %rdi
addq $0x8, %rdi
callq 0x25650
movq 0x18(%rsp), %rax
movb 0x21850(%rax), %al
shrb $0x7, %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x1f37a
movl $0x1, 0xe4(%rsp)
jmp 0x1f385
movl $0x0, 0xe4(%rsp)
movl 0xe4(%rsp), %eax
addq $0xe8, %rsp
retq
nopw %cs:(%rax,%rax)