How to load graphics or binara data in the cx16 various ram banks!

@jespergravgaard ,

Would you know how to load various data (bitmaps, graphics, binary data etc) in the CX16 RAM banks? I've based a new sprite demo on the methods you've created earlier using kickasm, loading one sprite. But how can i load let's say 120 sprites in the 512KB of the CX16???

Any ideas?

Sven

// Example program for the Commander X16
// Displays 32 64*64 TUT sprites

#pragma target(cx16) 
#include <cx16.h>
#include <6502.h>
#include <veralib.h>
#include <conio.h>
#include <printf.h>


const byte NUM_SPRITES = 17;

// A 64*64 8bpp TUT sprite and palette
char SPRITE_PIXELS[32+64*64*NUM_SPRITES/2] = kickasm(resource "Ship_1\ship_1_360_1.png") {{
    .var pic = LoadPicture("Ship_1\ship_1_360_1.png")
    // palette: rgb->idx
    .var palette = Hashtable()
    // RGB value for each palette index
    .var palList = List()
    // Next palette index
    .var nxt_idx = 0;
    // Extract palette while outputting pixels as palete index values
    .for (var y=0; y<64; y++) {
        .for (var x=0;x<64; x++) {
            // Find palette index (add if not known)
            .var rgb = pic.getPixel(x,y);
            .var idx = palette.get(rgb)
            .if(idx==null) {
                .eval idx = nxt_idx++;
                .eval palette.put(rgb,idx);
                .eval palList.add(rgb)
            }
        }
    }
    .if(nxt_idx>16) .error "Image has too many colours "+nxt_idx
    
    .for(var i=0;i<palList.size();i++) {
        .var rgb = palList.get(i)
        .var red = floor(rgb / [256*256])
        .var green = floor(rgb/256) & 255
        .var blue = rgb & 255
        // bits 4-8: green, bits 0-3 blue
        .byte green&$f0  | blue/16
        // bits bits 0-3 red
        .byte red/16
    }
    .for(var p=1;p<=NUM_SPRITES;p++) {
        .var pic = LoadPicture("Ship_1\ship_1_360_" + p + ".png")
        .for (var y=0; y<64; y++) {
            .for (var x=0;x<64; x+=2) {
                // Find palette index (add if not known)
                .var rgb = pic.getPixel(x,y);
                .var idx1 = palette.get(rgb)
                .if(idx1==null) {
                    .printnow "unknown rgb value!"
                }
                // Find palette index (add if not known)
                .eval rgb = pic.getPixel(x+1,y);
                .var idx2 = palette.get(rgb)
                .if(idx2==null) {
                    .printnow "unknown rgb value!"
                }
                .byte idx1*16+idx2;
            }
        }
    }
}};


word sprite_offset = <(SPRITE_PIXELS_VRAM/32)|VERA_SPRITE_4BPP;
// Sprite attributes: 8bpp, in front, 64x64, address SPRITE_PIXELS_VRAM
struct VERA_SPRITE SPRITE_ATTR = { <(SPRITE_PIXELS_VRAM/32)|VERA_SPRITE_8BPP, 320-32, 240-32, 0x0c, 0xf1 };

word sprites[NUM_SPRITES];

// Address to use for sprite pixels in VRAM
const unsigned long SPRITE_PIXELS_VRAM = 0x00000; 

void main() {

    memcpy_in_vram(1, 0xF000, VERA_INC_1, 0, 0xF800, VERA_INC_1, 256*8); // We copy the 128 character set of 8 bytes each.

    vera_layer_mode_tile(1, 0x14000, 0x1F000, 128, 64, 8, 8, 1);
    screenlayer(1);

    textcolor(WHITE);
    bgcolor(BLUE);
    clrscr();

    printf("hello world");

    // Copy sprite data to VRAM
    memcpy_to_vram((char)>SPRITE_PIXELS_VRAM, <SPRITE_PIXELS_VRAM, SPRITE_PIXELS+32, 64*64*NUM_SPRITES/2);
    // Copy sprite palette to VRAM
    memcpy_to_vram((char)>VERA_PALETTE, <VERA_PALETTE+32, SPRITE_PIXELS, 32);
    // Copy 8* sprite attributes to VRAM    
    char* vram_sprite_attr = <VERA_SPRITE_ATTR;
    for(char s=0;s<NUM_SPRITES;s++) {
        sprites[s] = sprite_offset;
        SPRITE_ATTR.ADDR = sprite_offset;
        SPRITE_ATTR.X += 68;
        SPRITE_ATTR.Y = 100;
        memcpy_to_vram((char)>VERA_SPRITE_ATTR, vram_sprite_attr, &SPRITE_ATTR, sizeof(SPRITE_ATTR));
        vram_sprite_attr += sizeof(SPRITE_ATTR);
        sprite_offset += 64;
    }    
    // Enable sprites
    *VERA_CTRL &= ~VERA_DCSEL;
    *VERA_DC_VIDEO |= VERA_SPRITES_ENABLE;
    // Enable VSYNC IRQ (also set line bit 8 to 0)
    SEI();
    *KERNEL_IRQ = &irq_vsync;
    *VERA_IEN = VERA_VSYNC; 
    CLI();
}

volatile byte i = 0;
volatile byte a = 8;

// VSYNC Interrupt Routine
__interrupt(rom_sys_cx16) void irq_vsync() {
    // Move the sprite around

    a--;
    if(a==0) {
        a=8;
        const char vram_sprite_attr_bank = (char)>VERA_SPRITE_ATTR;
        char *vram_sprite_attr = <VERA_SPRITE_ATTR;
        unsigned int i_x = 0;
        unsigned int i_y = 0;
        for(word s=0;s<NUM_SPRITES;s++) {
            word x = s+i;
            if(x>NUM_SPRITES) {
                x-=NUM_SPRITES;
            }
            SPRITE_ATTR.ADDR = sprites[x];
            SPRITE_ATTR.X = 40+(s&03)*68;
            SPRITE_ATTR.Y = 100+(s>>2)*68;
            // Copy sprite positions to VRAM (the 4 relevant bytes in VERA_SPRITE_ATTR)
            memcpy_to_vram(vram_sprite_attr_bank, vram_sprite_attr, &SPRITE_ATTR, 6);
            vram_sprite_attr += sizeof(SPRITE_ATTR);
        }

        i++;
        if(i>NUM_SPRITES) i=0;

        // Reset the VSYNC interrupt
        *VERA_ISR = VERA_VSYNC;
    }
}