
bank zeropage @ 0x00 : [vardata; 256];
bank stack @ 0x100 : [vardata; 256];
bank ram @ 0x200 : [vardata; 1536];
bank prg @ 0x8000 : [constdata; 32768];
bank chr : [chrdata; 8192];

import "nes";

in zeropage {
    var b0, b1, b2, b3, b4, b5, b6, b7 : u8;
    var ptr0 @ &b0, ptr2 @ &b2 : *u8;
}

in prg {
    func main() {
        // Disable decimal arithmetic (though not actually supported on 2A03 anyway)
        decimal = false;
        // Disable interrupts.
        nointerrupt = true;
        // Prepare stack.
        s = x = 0xFF;

        // Turn off rendering.
        nes.ppu.control = x = 0;
        nes.ppu.mask = x;
        // Disable DMC interrupts.
        nes.apu.frame_counter = a = nes.apu.FRAME_COUNTER_IRQ_DISABLE;

        // Wait for the PPU to be ready to use, which takes 2 vertical blanks.
        do {
            do {} while !nes.ppu.status$7;
            x++;
        } while x != 2;

        // Read PPU status to reset the PPU high/low latch.
        a = nes.ppu.status;
        // Now setup the PPU for copying to the nametable.
        nes.ppu.address = a = >:nes.ppu.ADDRESS_NAMETABLE_DATA;
        nes.ppu.address = a = <:nes.ppu.ADDRESS_NAMETABLE_DATA;
        // Clear the nametable.
        x = >:nes.ppu.NAMETABLE_SIZE * 2;
        do {
            y = 0;
            do {
                nes.ppu.data = a;
                y++;
            } while !zero;

            x--;
        } while !zero;

        // Read PPU status to reset the PPU high/low latch.
        a = nes.ppu.status;
        // Now setup the PPU for copying to the palette.
        nes.ppu.address = a = >:nes.ppu.ADDRESS_PALETTE_DATA;
        nes.ppu.address = a = <:nes.ppu.ADDRESS_PALETTE_DATA;
        // Clear the palette.
        x = 0;            
        do {
            nes.ppu.data = a = palette[x++];
        } while x != palette.len;

        {
            let START_X = 10;
            let START_Y = 13;
            let TILE_ADDRESS = nes.ppu.ADDRESS_NAMETABLE_DATA + START_Y * 32 + START_X;

            // Read PPU status to reset the PPU high/low latch.
            a = nes.ppu.status;
            // Now setup the PPU for copying to the nametable.
            nes.ppu.address = a = >:TILE_ADDRESS;
            nes.ppu.address = a = <:TILE_ADDRESS;            
            // Copy the message.
            x = 0;
            while {
                a = message[y];
            } && !zero {
                y++;
                nes.ppu.data = a;
            }
        }

        a = nes.ppu.status; 
        nes.ppu.scroll = a = 0;
        nes.ppu.scroll = a;        
        
        // We're finally ready to show the screen!
        nes.ppu.control = a = nes.ppu.CONTROL_NMI;
        nes.ppu.mask = a = nes.ppu.MASK_LEFTMOST_BG | nes.ppu.MASK_RENDER_BG;

        // Enable interrupts.
        nointerrupt = false;

        while true {}
    }

    #[nmi] func draw() {
        push(a);
        a = x; push(a);
        a = y; push(a);
        a = nes.ppu.status; 
        nes.ppu.scroll = a = 0;
        nes.ppu.scroll = a;
        y = a = pop();
        x = a = pop();
        a = pop();
    }

    #[irq] func scanline() {
        push(a);
        a = x; push(a);
        a = y; push(a);
        y = a = pop();
        x = a = pop();
        a = pop();
    }

    const message = "HELLO  WORLD\0";

    const palette : [u8] = [
        // Tiles
        0x0F, 0x00, 0x10, 0x30,
        0x0F, 0x00, 0x10, 0x30,
        0x0F, 0x00, 0x10, 0x30,
        0x0F, 0x00, 0x10, 0x30,
        // Sprites
        0x0F, 0x00, 0x10, 0x30,
        0x0F, 0x00, 0x10, 0x30,
        0x0F, 0x00, 0x10, 0x30,
        0x0F, 0x00, 0x10, 0x30
    ];

    const @ 0xFFFA = [draw, main, scanline];
}

in chr {
    const = embed "hello_tiles.chr";
}
