// A simple usage of the flexible sprite multiplexer routine
import "c64"
import "multiplexer"

// Location of screen & sprites
byte* SCREEN = $400;

byte[0x100] align(0x100) YSIN = kickasm {{
    .var min = 50
    .var max = 250-21
    .var ampl = max-min;
    .for(var i=0;i<256;i++)
        .byte round(min+(ampl/2)+(ampl/2)*sin(toRadians(360*i/256)))
}};

byte* SPRITE = $2000;
kickasm(pc SPRITE, resource "balloon.png") {{
    .var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
    .for (var y=0; y<21; y++)
        .for (var x=0;x<3; x++)
            .byte pic.getSinglecolorByte(x,y)
}}

void main() {
    asm { sei }
    init();
    loop();
}

// Initialize the program
void init() {
    *D011 = VIC_DEN | VIC_RSEL | 3;
    // Initialize the multiplexer
    plexInit(SCREEN);
    // Set the x-positions & pointers
    word xp = 32;
    for(byte sx: 0..PLEX_COUNT-1) {
        PLEX_PTR[sx] = (byte)(SPRITE/$40);
        PLEX_XPOS[sx] = xp;
        xp += 9;
    }
    // Enable & initialize sprites
    *SPRITES_ENABLE = $ff;
    for(byte ss: 0..7) {
        SPRITES_COLS[ss] = GREEN;
    }
}

// The raster loop
void loop() {
    // The current index into the y-sinus
    byte sin_idx = 0;
    while(true) {
        while(*RASTER!=$ff) {}
        // Assign sinus positions
        (*BORDERCOL)++;
        byte y_idx = sin_idx;
        for(byte sy: 0..PLEX_COUNT-1) {
            PLEX_YPOS[sy] = YSIN[y_idx];
            y_idx += 8;
        }
        sin_idx +=1;
        // Sort the sprites by y-position
        (*BORDERCOL)++;
        plexSort();
        *BORDERCOL = BLACK;
        while((*D011&VIC_RST8)!=0) {}
        // Show the sprites
        for( byte ss: 0..PLEX_COUNT-1) {
            *BORDERCOL = BLACK;
            byte rasterY = plexFreeNextYpos();
            while(*RASTER<rasterY) {}
            (*BORDERCOL)++;
            plexShowSprite();
        }
        *BORDERCOL = BLACK;
    }
}