1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-22 16:33:48 +00:00

2BPP 8x8 first explanation done.

Created new vera functions to set the mode of a layer, in one call, and to paint an area with a tile. More functions like this will be made. (like tile increment, tile template fill, etc, etc).
This commit is contained in:
FlightControl 2021-01-14 21:47:18 +01:00
parent 72dd0f044c
commit d45e58a1be
10 changed files with 1319 additions and 3606 deletions

File diff suppressed because it is too large Load Diff

View File

@ -141,20 +141,20 @@ char * const VERA_DC_VSTOP = 0x9f2c;
// Configuration work tables
// Bit 4-5. Map Width (0:32 tiles, 1:64 tiles, 2:128 tiles, 3:256 tiles)
byte const VERA_LAYER_CONFIG_WIDTH_32 = 0x00;
byte const VERA_LAYER_CONFIG_WIDTH_64 = 0x10;
byte const VERA_LAYER_CONFIG_WIDTH_128 = 0x20;
byte const VERA_LAYER_CONFIG_WIDTH_256 = 0x30;
byte const VERA_LAYER_CONFIG_WIDTH_MASK = 0x30;
word const VERA_LAYER_CONFIG_WIDTH[4] = {32, 64, 128, 256};
byte const VERA_LAYER_WIDTH_32 = 0x00;
byte const VERA_LAYER_WIDTH_64 = 0x10;
byte const VERA_LAYER_WIDTH_128 = 0x20;
byte const VERA_LAYER_WIDTH_256 = 0x30;
byte const VERA_LAYER_WIDTH_MASK = 0x30;
word const VERA_LAYER_WIDTH[4] = {32, 64, 128, 256};
// Bit 6-7: Map Height (0:32 tiles, 1:64 tiles, 2:128 tiles, 3:256 tiles)
byte const VERA_LAYER_CONFIG_HEIGHT_32 = 0x00;
byte const VERA_LAYER_CONFIG_HEIGHT_64 = 0x40;
byte const VERA_LAYER_CONFIG_HEIGHT_128 = 0x80;
byte const VERA_LAYER_CONFIG_HEIGHT_256 = 0xC0;
byte const VERA_LAYER_CONFIG_HEIGHT_MASK = 0xC0;
word const VERA_LAYER_CONFIG_HEIGHT[4] = {32, 64, 128, 256};
byte const VERA_LAYER_HEIGHT_32 = 0x00;
byte const VERA_LAYER_HEIGHT_64 = 0x40;
byte const VERA_LAYER_HEIGHT_128 = 0x80;
byte const VERA_LAYER_HEIGHT_256 = 0xC0;
byte const VERA_LAYER_HEIGHT_MASK = 0xC0;
word const VERA_LAYER_HEIGHT[4] = {32, 64, 128, 256};
// Bit 0-1: Color Depth (0: 1 bpp, 1: 2 bpp, 2: 4 bpp, 3: 8 bpp)
byte const VERA_LAYER_COLOR_DEPTH_1BPP = 0x00;
@ -178,6 +178,13 @@ char * const VERA_L0_MAPBASE = 0x9f2e;
// $9F2F L0_TILEBASE Layer 0 Tile Base
// Bit 2-7: Tile Base Address (16:11)
// Bit 1: Tile Height (0:8 pixels, 1:16 pixels)
byte const VERA_TILEBASE_WIDTH_8 = 0x00;
byte const VERA_TILEBASE_WIDTH_16 = 0x01;
byte const VERA_TILEBASE_WIDTH_MASK = 0x01;
byte const VERA_TILEBASE_HEIGHT_8 = 0x00;
byte const VERA_TILEBASE_HEIGHT_16 = 0x02;
byte const VERA_TILEBASE_HEIGHT_MASK = 0x02;
byte const VERA_TILEBASE_MASK = 0xfC;
// Bit 0: Tile Width (0:8 pixels, 1:16 pixels)
char * const VERA_L0_TILEBASE = 0x9f2f;
// $9F30 L0_HSCROLL_L Layer 0 H-Scroll (7:0)

View File

@ -9,6 +9,21 @@
// --- VERA function encapsulation ---
// --- VERA layer management ---
word vera_mapbase_word[2] = {0,0};
byte vera_mapbase_bank[2] = {0,0};
dword vera_mapbase_dword[2] = {0,0};
word vera_tilebase_word[2] = {0,0};
byte vera_tilebase_bank[2] = {0,0};
dword vera_tilebase_dword[2] = {0,0};
byte vera_row_shift[2] = {0,0};
const byte vera_layer_hflip[2] = {0,0x04};
const byte vera_layer_vflip[2] = {0,0x08};
byte* vera_layer_config[2] = {VERA_L0_CONFIG, VERA_L1_CONFIG};
byte vera_layer_enable[2] = { VERA_LAYER0_ENABLE, VERA_LAYER1_ENABLE };
@ -46,6 +61,19 @@ void vera_vram_address1(dword bankaddr, byte incr) {
*VERA_ADDRX_H = <(*word_h) | incr;
}
// Get the map base address of the tiles for the layer.
// - layer: Value of 0 or 1.
// - return: Specifies the map base address of the layer, which is returned as a dword.
// Note that the register only specifies bits 16:9 of the 17 total bit-address,
// so the resulting address in the VERA VRAM is always aligned to a multiple of 512 bytes!
dword vera_get_layer_mapbase_address(byte layer) {
layer &= $1;
byte mapbase = *vera_layer_mapbase[layer];
dword address = mapbase;
address <<= 8;
address <<= 1;
return address;
}
// --- VERA layer management ---
// Set the configuration of the layer.
@ -70,58 +98,58 @@ char vera_get_layer_config(char layer) {
// - layer: Value of 0 or 1.
inline void vera_set_layer_map_width_32(unsigned byte layer) {
byte* addr = vera_layer_config[layer];
*addr &= ~VERA_LAYER_CONFIG_WIDTH_MASK;
*addr |= VERA_LAYER_CONFIG_WIDTH_32;
*addr &= ~VERA_LAYER_WIDTH_MASK;
*addr |= VERA_LAYER_WIDTH_32;
}
inline void vera_set_layer_map_width_64(unsigned byte layer) {
byte* addr = vera_layer_config[layer];
//*addr &= (~VERA_CONFIG_WIDTH_MASK) | VERA_CONFIG_WIDTH_64;
*addr &= ~VERA_LAYER_CONFIG_WIDTH_MASK;
*addr |= VERA_LAYER_CONFIG_WIDTH_64;
*addr &= ~VERA_LAYER_WIDTH_MASK;
*addr |= VERA_LAYER_WIDTH_64;
}
inline void vera_set_layer_map_width_128(unsigned byte layer) {
byte* addr = vera_layer_config[layer];
*addr &= ~VERA_LAYER_CONFIG_WIDTH_MASK;
*addr |= VERA_LAYER_CONFIG_WIDTH_128;
*addr &= ~VERA_LAYER_WIDTH_MASK;
*addr |= VERA_LAYER_WIDTH_128;
}
inline void vera_set_layer_map_width_256(unsigned byte layer) {
byte* addr = vera_layer_config[layer];
*addr &= ~VERA_LAYER_CONFIG_WIDTH_MASK;
*addr |= VERA_LAYER_CONFIG_WIDTH_256;
*addr &= ~VERA_LAYER_WIDTH_MASK;
*addr |= VERA_LAYER_WIDTH_256;
}
inline void vera_set_layer_map_height_32(unsigned byte layer) {
byte* addr = vera_layer_config[layer];
*addr &= ~VERA_LAYER_CONFIG_HEIGHT_MASK;
*addr |= VERA_LAYER_CONFIG_HEIGHT_32;
*addr &= ~VERA_LAYER_HEIGHT_MASK;
*addr |= VERA_LAYER_HEIGHT_32;
}
inline void vera_set_layer_map_height_64(unsigned byte layer) {
byte* addr = vera_layer_config[layer];
*addr &= ~VERA_LAYER_CONFIG_HEIGHT_MASK;
*addr |= VERA_LAYER_CONFIG_HEIGHT_64;
*addr &= ~VERA_LAYER_HEIGHT_MASK;
*addr |= VERA_LAYER_HEIGHT_64;
}
inline void vera_set_layer_map_height_128(unsigned byte layer) {
byte* addr = vera_layer_config[layer];
*addr &= ~VERA_LAYER_CONFIG_HEIGHT_MASK;
*addr |= VERA_LAYER_CONFIG_HEIGHT_128;
*addr &= ~VERA_LAYER_HEIGHT_MASK;
*addr |= VERA_LAYER_HEIGHT_128;
}
inline void vera_set_layer_map_height_256(unsigned byte layer) {
byte* addr = vera_layer_config[layer];
*addr &= ~VERA_LAYER_CONFIG_HEIGHT_MASK;
*addr |= VERA_LAYER_CONFIG_HEIGHT_256;
*addr &= ~VERA_LAYER_HEIGHT_MASK;
*addr |= VERA_LAYER_HEIGHT_256;
}
// Get the map width or height of the layer.
// - layer: Value of 0 or 1.
word vera_get_layer_map_width(unsigned byte layer) {
byte* config = vera_layer_config[layer];
byte mask = (byte)VERA_LAYER_CONFIG_WIDTH_MASK;
return VERA_LAYER_CONFIG_WIDTH[ (*config & mask) >> 4];
byte mask = (byte)VERA_LAYER_WIDTH_MASK;
return VERA_LAYER_WIDTH[ (*config & mask) >> 4];
}
word vera_get_layer_map_height(unsigned byte layer) {
byte* config = vera_layer_config[layer];
byte mask = VERA_LAYER_CONFIG_HEIGHT_MASK;
return VERA_LAYER_CONFIG_HEIGHT[ (*config & mask) >> 6];
byte mask = VERA_LAYER_HEIGHT_MASK;
return VERA_LAYER_HEIGHT[ (*config & mask) >> 6];
}
// Set the color depth of the layer in terms of bit per pixel (BPP) of the tile base.
@ -308,3 +336,129 @@ inline void vera_set_layer_vertical_scroll(byte layer, word scroll) {
*vera_layer_vscroll_l[layer] = <scroll;
*vera_layer_vscroll_h[layer] = >scroll;
}
void vera_mode_tile(byte layer, dword mapbase_dw, dword tilebase_dw, word mapwidth, word mapheight, byte tilewidth, byte tileheight, byte color_depth ) {
// config
byte config = 0x00;
switch(color_depth) {
case 1:
config |= VERA_LAYER_COLOR_DEPTH_1BPP;
break;
case 2:
config |= VERA_LAYER_COLOR_DEPTH_2BPP;
break;
case 4:
config |= VERA_LAYER_COLOR_DEPTH_4BPP;
break;
case 8:
config |= VERA_LAYER_COLOR_DEPTH_8BPP;
break;
}
switch(mapwidth) {
case 32:
config |= VERA_LAYER_WIDTH_32;
vera_row_shift[layer] = 6;
break;
case 64:
config |= VERA_LAYER_WIDTH_64;
vera_row_shift[layer] = 7;
break;
case 128:
config |= VERA_LAYER_WIDTH_128;
vera_row_shift[layer] = 8;
break;
case 256:
config |= VERA_LAYER_WIDTH_256;
vera_row_shift[layer] = 9;
break;
}
switch(mapheight) {
case 32:
config |= VERA_LAYER_HEIGHT_32;
break;
case 64:
config |= VERA_LAYER_HEIGHT_64;
break;
case 128:
config |= VERA_LAYER_HEIGHT_128;
break;
case 256:
config |= VERA_LAYER_HEIGHT_256;
break;
}
vera_set_layer_config(layer, config);
// mapbase
vera_mapbase_word[layer] = <mapbase_dw;
vera_mapbase_bank[layer] = (byte)>mapbase_dw;
vera_mapbase_dword[layer] = mapbase_dw;
mapbase_dw = mapbase_dw >> 1;
byte mapbase = (byte)<(mapbase_dw >> 8);
vera_set_layer_mapbase(layer,mapbase);
//printf("%lx\n",mapbase_dw);
// tilebase
vera_tilebase_word[layer] = <tilebase_dw;
vera_tilebase_bank[layer] = (byte)>tilebase_dw;
vera_tilebase_dword[layer] = tilebase_dw;
//printf("tilebase word = %x\n",vera_tilebase_word[layer]);
//printf("tilebase bank = %x\n",vera_tilebase_bank[layer]);
//printf("tilebase dword = %lx\n",vera_tilebase_dword[layer]);
tilebase_dw = tilebase_dw >> 1;
byte tilebase = (byte)<(tilebase_dw >> 8);
tilebase &= VERA_TILEBASE_MASK;
switch(tilewidth) {
case 8:
tilebase |= VERA_TILEBASE_WIDTH_8;
break;
case 16:
tilebase |= VERA_TILEBASE_WIDTH_16;
break;
}
switch(tileheight) {
case 8:
tilebase |= VERA_TILEBASE_HEIGHT_8;
break;
case 16:
tilebase |= VERA_TILEBASE_HEIGHT_16;
break;
}
//printf("tilebase = %x\n",tilebase);
vera_set_layer_tilebase(layer,tilebase);
}
// --- TILE FUNCTIONS ---
void vera_tile_area(byte layer, word tileindex, byte x, byte y, byte w, byte h, byte hflip, byte vflip, byte offset) {
dword mapbase = vera_mapbase_dword[layer];
byte shift = vera_row_shift[layer];
word rowskip = (word)1 << shift;
hflip = vera_layer_hflip[hflip];
vflip = vera_layer_vflip[vflip];
offset = offset << 4;
byte index_l = <tileindex;
byte index_h = >tileindex;
index_h |= hflip;
index_h |= vflip;
index_h |= offset;
mapbase += ((word)y << shift);
mapbase += (x << 1);
for(byte r=0; r<h; r++) {
vera_vram_address0(mapbase,VERA_INC_1);
for(byte c=0; c<w; c++) {
*VERA_DATA0 = index_l;
*VERA_DATA0 = index_h;
}
mapbase += rowskip;
}
}

View File

@ -20,12 +20,14 @@ void main() {
clrscr();
// Now we set the tile map width and height.
vera_set_layer_mapbase(0,0x80); // Set the map base to address 0x10000 in VERA VRAM!
vera_set_layer_config(0, vera_get_layer_config(1));
vera_set_layer_tilebase(0, vera_get_layer_tilebase(1));
vera_set_layer_map_width_128(0);
vera_set_layer_map_height_128(0);
dword tilebase = vera_get_layer_tilebase_address(0);
// vera_set_layer_mapbase(0,0x80); // Set the map base to address 0x10000 in VERA VRAM!
// vera_set_layer_config(0, vera_get_layer_config(1));
// vera_set_layer_tilebase(0, vera_get_layer_tilebase(1));
// vera_set_layer_map_width_128(0);
// vera_set_layer_map_height_128(0);
dword tilebase = vera_get_layer_tilebase_address(1);
vera_mode_tile(0, 0x10000, 0xF800, 128, 128, 8, 8, 1);
screenlayer(0);
scroll(0); // Scrolling on conio is deactivated, so conio will output beyond the borders of the visible screen.

View File

@ -1,170 +0,0 @@
// Example program for the Commander X16.
// Demonstrates the usage of the VERA tile map modes and layering.
// Author: Sven Van de Velde
// The default layer of the CX16 is layer 1, but the tiles are written on layer 0.
// The CX16 starts in tile map mode, 2BPP in 4 color mode, and uses 8x8 tiles.
// The map base is address 0x10000 in VERA VRAM.
// The tile base is address 0x0800 in VERA VRAM.
// We are displaying 128 tiles vertically and 128 tiles horizontally.
// The tile base is from 64 tiles.
#include <veralib.h>
#include <printf.h>
#include <6502.h>
void main() {
textcolor(WHITE);
bgcolor(BLACK);
clrscr();
// Now we set the tile map width and height.
vera_set_layer_mapbase(0,0x80); // Set the map base to address 0x10000 in VERA VRAM!
vera_set_layer_config(0, vera_get_layer_config(1));
vera_set_layer_color_depth_2BPP(0);
vera_set_layer_tilebase(0, 0xA0);
vera_set_layer_map_width_128(0);
vera_set_layer_map_height_64(0);
dword tilebase = vera_get_layer_tilebase_address(0);
vera_show_layer(0);
byte tile[64] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
byte map[16] = {0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00};
memcpy_to_vram(1, 0x4000, tile, 64);
memcpy_to_vram(1, 0x0000, map, 16);
tilebase = 0;
dword mapbase = ver_get_vera_layer_mapbase_address(0);
for(byte y:0..15) {
tilerow = tilebase;
for(byte r:0..3) {
tilecolumn = tilerow;
for(byte x:0..15) {
for(byte c: 0..1) {
vera_vram_address0(mapbase,VERA_INC_1);
*VERA_DATA0 = map[x];
*VERA_DATA0 = map[x];
}
byte bit = data;
tilecolumn += 8;
printf("");
}
//printf("\n");
tilerow += 1;
}
}
while(!kbhit());
screenlayer(0);
scroll(1); // Scrolling on conio is activated, so conio will not output beyond the borders of the visible screen.
textcolor(WHITE);
bgcolor(GREEN);
draw_characters(tilebase);
while(!kbhit());
// Enable VSYNC IRQ (also set line bit 8 to 0)
SEI();
*KERNEL_IRQ = &irq_vsync;
*VERA_IEN = VERA_VSYNC;
CLI();
vera_hide_layer(0);
textcolor(GREY);
bgcolor(GREEN);
draw_characters(tilebase);
vera_show_layer(0);
screenlayer(1);
textcolor(WHITE);
bgcolor(BLACK);
printf("\n\nthis demo displays the design of the standard x16 commander\n");
printf("character set on the vera layer 0. it's the character set i grew up with :-).\n");
printf("\nthe smooth scrolling is implemented by manipulating the scrolling \n");
printf("registers of layer 0. at each raster line interrupt, \n");
printf("the x and y scrolling registers are manipulated. the cx16 terminal \n");
printf("works on layer 1. when layer 0 is enabled with the scrolling, \n");
printf("it gives a nice background effect. this technique can be used to implement\n");
printf("smooth scrolling backgrounds using tile layouts in games or demos.\n");
textcolor(YELLOW);
printf("\npress a key to continue ...");
while(!kbhit());
screenlayer(0);
vera_hide_layer(0);
textcolor(DARK_GREY);
bgcolor(BLACK);
draw_characters(tilebase);
vera_show_layer(0);
screenlayer(1);
gotoxy(0,20);
}
void draw_characters(dword tilebase) {
dword tilecolumn = tilebase;
dword tilerow = tilebase;
clrscr();
for(byte y:0..15) {
printf("@");
}
}
// X sine index
volatile int scroll_x = 0;
volatile int scroll_y = 0;
volatile int delta_x = 2;
volatile int delta_y = 0;
volatile int speed = 2;
// VSYNC Interrupt Routine
__interrupt(rom_sys_cx16) void irq_vsync() {
scroll_x += delta_x;
scroll_y += delta_y;
if( scroll_x>(128*8-80*8)) {
delta_x = 0;
delta_y = speed;
scroll_x = (128*8-80*8);
}
if( scroll_y>(128*8-60*8)) {
delta_x = -speed;
delta_y = 0;
scroll_y = (128*8-60*8);
}
if(scroll_x<0) {
delta_x = 0;
delta_y = -speed;
scroll_x = 0;
}
if(scroll_y<0) {
delta_x = speed;
delta_y = 0;
scroll_y = 0;
}
vera_set_layer_horizontal_scroll(0,(word)scroll_x);
vera_set_layer_vertical_scroll(0,(word)scroll_y);
// Reset the VSYNC interrupt
*VERA_ISR = VERA_VSYNC;
}

View File

@ -0,0 +1,74 @@
// Example program for the Commander X16.
// Demonstrates the usage of the VERA tile map modes and layering.
// Author: Sven Van de Velde
// The default layer of the CX16 is layer 1, but the tiles are written on layer 0.
// The CX16 starts in tile map mode, 2BPP in 4 color mode, and uses 8x8 tiles.
// An explanation is given how this mode is organized, and how the tiles display and coloring works.
// Pälette offsets are explained also.
#include <veralib.h>
#include <printf.h>
void main() {
textcolor(WHITE);
bgcolor(BLACK);
clrscr();
vera_mode_tile(0, 0x04000, 0x14000, 128, 128, 8, 8, 2);
byte tiles[64] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
byte map[16] = {0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00};
memcpy_to_vram(1, 0x4000, tiles, 64);
//vera_tile_area(byte layer, word tileindex, byte x, byte y, byte w, byte h, byte hflip, byte vflip, byte offset)
vera_tile_area(0, 0, 0, 0, 80, 60, 0, 0, 0);
// Draw 4 squares with each tile, staring from row 2, width 10, height 10, separated by 2 characters.
vera_tile_area(0, 0, 4, 4, 10, 10, 0, 0, 0);
vera_tile_area(0, 1, 16, 4, 10, 10, 0, 0, 0);
vera_tile_area(0, 2, 28, 4, 10, 10, 0, 0, 0);
vera_tile_area(0, 3, 40, 4, 10, 10, 0, 0, 0);
word tile = 0;
byte offset = 0;
byte row = 22;
for(byte r:0..3) {
byte column = 4;
for(byte c:0..15) {
vera_tile_area(0, tile, column, row, 3, 3, 0, 0, offset);
column+=4;
offset++;
}
tile++;
tile &= 0x3;
row += 4;
}
vera_show_layer(0);
gotoxy(0,40);
printf("vera in tile mode 8 x 8, color depth 2 bits per pixel.\n");
printf("in this mode, tiles are 8 pixels wide and 8 pixels tall.\n");
printf("each tile can have a variation of 4 colors.\n");
printf("the vera palette of 256 colors, can be used by setting the palette\n");
printf("offset for each tile.\n");
printf("here each column is displaying the same tile, but with different offsets!\n");
printf("each offset aligns to multiples of 16 colors, and only the first 4 colors\n");
printf("can be used per offset!\n");
printf("however, the first color will always be transparent (black).\n");
while(!kbhit());
}

View File

@ -1,514 +0,0 @@
// Example program for the Commander X16
// Displays 32 64*64 TUT sprites
.cpu _65c02
// Commodore 64 PRG executable file
.file [name="sprites.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(__start)
.const VERA_INC_1 = $10
.const VERA_DCSEL = 2
.const VERA_ADDRSEL = 1
.const VERA_VSYNC = 1
// VERA Palette address in VRAM $1FA00 - $1FBFF
// 256 entries of 2 bytes
// byte 0 bits 4-7: Green
// byte 0 bits 0-3: Blue
// byte 1 bits 0-3: Red
.const VERA_PALETTE = $1fa00
// Sprite Attributes address in VERA VRAM $1FC00 - $1FFFF
.const VERA_SPRITE_ATTR = $1fc00
// 8BPP sprite mode (add to VERA_SPRITE.ADDR to enable)
.const VERA_SPRITE_8BPP = $8000
// Address to use for sprite pixels in VRAM
.const SPRITE_PIXELS_VRAM = $8000
// X sine [0;640-64]
.const SINX_LEN = $f1
// Y sine [0;480-64]
.const SINY_LEN = $fb
.const SIZEOF_STRUCT_VERA_SPRITE = 8
.const OFFSET_STRUCT_VERA_SPRITE_X = 2
.const OFFSET_STRUCT_VERA_SPRITE_Y = 4
.const VERA_SPRITES_ENABLE = $40
// $9F20 VRAM Address (7:0)
.label VERA_ADDRX_L = $9f20
// $9F21 VRAM Address (15:8)
.label VERA_ADDRX_M = $9f21
// $9F22 VRAM Address (7:0)
// Bit 4-7: Address Increment The following is the amount incremented per value value:increment
// 0:0, 1:1, 2:2, 3:4, 4:8, 5:16, 6:32, 7:64, 8:128, 9:256, 10:512, 11:40, 12:80, 13:160, 14:320, 15:640
// Bit 3: DECR Setting the DECR bit, will decrement instead of increment by the value set by the 'Address Increment' field.
// Bit 0: VRAM Address (16)
.label VERA_ADDRX_H = $9f22
// $9F23 DATA0 VRAM Data port 0
.label VERA_DATA0 = $9f23
// $9F25 CTRL Control
// Bit 7: Reset
// Bit 1: DCSEL
// Bit 2: ADDRSEL
.label VERA_CTRL = $9f25
// $9F26 IEN Interrupt Enable
// Bit 7: IRQ line (8)
// Bit 3: AFLOW
// Bit 2: SPRCOL
// Bit 1: LINE
// Bit 0: VSYNC
.label VERA_IEN = $9f26
// $9F27 ISR Interrupt Status
// Interrupts will be generated for the interrupt sources set in the lower 4 bits of IEN. ISR will indicate the interrupts that have occurred.
// Writing a 1 to one of the lower 3 bits in ISR will clear that interrupt status. AFLOW can only be cleared by filling the audio FIFO for at least 1/4.
// Bit 4-7: Sprite Collisions. This field indicates which groups of sprites have collided.
// Bit 3: AFLOW
// Bit 2: SPRCOL
// Bit 1: LINE
// Bit 0: VSYNC
.label VERA_ISR = $9f27
// $9F29 DC_VIDEO (DCSEL=0)
// Bit 7: Current Field Read-only bit which reflects the active interlaced field in composite and RGB modes. (0: even, 1: odd)
// Bit 6: Sprites Enable Enable output from the Sprites renderer
// Bit 5: Layer1 Enable Enable output from the Layer1 renderer
// Bit 4: Layer0 Enable Enable output from the Layer0 renderer
// Bit 2: Chroma Disable Setting 'Chroma Disable' disables output of chroma in NTSC composite mode and will give a better picture on a monochrome display. (Setting this bit will also disable the chroma output on the S-video output.)
// Bit 0-1: Output Mode 0: Video disabled, 1: VGA output, 2: NTSC composite, 3: RGB interlaced, composite sync (via VGA connector)
.label VERA_DC_VIDEO = $9f29
// $0314 (RAM) IRQ vector - The vector used when the KERNAL serves IRQ interrupts
.label KERNEL_IRQ = $314
// X sine index
.label sin_idx_x = $12
// Y sine index
.label sin_idx_y = $14
.segment Code
__start: {
// sin_idx_x = 119
lda #<$77
sta.z sin_idx_x
lda #>$77
sta.z sin_idx_x+1
// sin_idx_y = 79
lda #<$4f
sta.z sin_idx_y
lda #>$4f
sta.z sin_idx_y+1
jsr main
rts
}
// VSYNC Interrupt Routine
irq_vsync: {
.const vram_sprite_attr_bank = VERA_SPRITE_ATTR>>$10
.label __11 = $16
.label __12 = $18
.label i_x = 3
.label i_y = 5
.label vram_sprite_pos = 7
.label s = 2
.label __13 = $16
.label __14 = $18
// if(++sin_idx_x==SINX_LEN)
inc.z sin_idx_x
bne !+
inc.z sin_idx_x+1
!:
lda.z sin_idx_x+1
cmp #>SINX_LEN
bne __b1
lda.z sin_idx_x
cmp #<SINX_LEN
bne __b1
// sin_idx_x = 0
lda #<0
sta.z sin_idx_x
sta.z sin_idx_x+1
__b1:
// if(--sin_idx_y==0xffff)
lda.z sin_idx_y
bne !+
dec.z sin_idx_y+1
!:
dec.z sin_idx_y
lda.z sin_idx_y+1
cmp #>$ffff
bne __b2
lda.z sin_idx_y
cmp #<$ffff
bne __b2
// sin_idx_y = SINY_LEN-1
lda #<SINY_LEN-1
sta.z sin_idx_y
lda #>SINY_LEN-1
sta.z sin_idx_y+1
__b2:
// i_x = sin_idx_x
lda.z sin_idx_x
sta.z i_x
lda.z sin_idx_x+1
sta.z i_x+1
// i_y = sin_idx_y
lda.z sin_idx_y
sta.z i_y
lda.z sin_idx_y+1
sta.z i_y+1
lda #<VERA_SPRITE_ATTR+2&$ffff
sta.z vram_sprite_pos
lda #>VERA_SPRITE_ATTR+2&$ffff
sta.z vram_sprite_pos+1
lda #0
sta.z s
__b5:
// for(char s=0;s<NUM_SPRITES;s++)
lda.z s
cmp #$20
bcc __b6
// *VERA_ISR = VERA_VSYNC
// Reset the VSYNC interrupt
lda #VERA_VSYNC
sta VERA_ISR
// asm
// Exit CX16 KERNAL IRQ
jmp $e034
// }
__b6:
// SPRITE_ATTR.X = SINX[i_x]
lda.z i_x
asl
sta.z __11
lda.z i_x+1
rol
sta.z __11+1
clc
lda.z __13
adc #<SINX
sta.z __13
lda.z __13+1
adc #>SINX
sta.z __13+1
ldy #0
lda (__13),y
sta SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X
iny
lda (__13),y
sta SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X+1
// SPRITE_ATTR.Y = SINY[i_y]
lda.z i_y
asl
sta.z __12
lda.z i_y+1
rol
sta.z __12+1
clc
lda.z __14
adc #<SINY
sta.z __14
lda.z __14+1
adc #>SINY
sta.z __14+1
ldy #0
lda (__14),y
sta SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y
iny
lda (__14),y
sta SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y+1
// memcpy_to_vram(vram_sprite_attr_bank, vram_sprite_pos, &SPRITE_ATTR+2, 4)
lda.z vram_sprite_pos
sta.z memcpy_to_vram.vdest
lda.z vram_sprite_pos+1
sta.z memcpy_to_vram.vdest+1
// Copy sprite positions to VRAM (the 4 relevant bytes in VERA_SPRITE_ATTR)
lda #<4
sta.z memcpy_to_vram.num
lda #>4
sta.z memcpy_to_vram.num+1
lda #<SPRITE_ATTR+2
sta.z memcpy_to_vram.src
lda #>SPRITE_ATTR+2
sta.z memcpy_to_vram.src+1
ldx #vram_sprite_attr_bank
jsr memcpy_to_vram
// vram_sprite_pos += sizeof(SPRITE_ATTR)
lda #SIZEOF_STRUCT_VERA_SPRITE
clc
adc.z vram_sprite_pos
sta.z vram_sprite_pos
bcc !+
inc.z vram_sprite_pos+1
!:
// i_x += 25
lda #$19
clc
adc.z i_x
sta.z i_x
bcc !+
inc.z i_x+1
!:
// if(i_x>=SINX_LEN)
lda.z i_x+1
bne !+
lda.z i_x
cmp #SINX_LEN
bcc __b8
!:
// i_x -= SINX_LEN
sec
lda.z i_x
sbc #SINX_LEN
sta.z i_x
lda.z i_x+1
sbc #0
sta.z i_x+1
__b8:
// i_y += 19
lda #$13
clc
adc.z i_y
sta.z i_y
bcc !+
inc.z i_y+1
!:
// if(i_y>=SINY_LEN)
lda.z i_y+1
bne !+
lda.z i_y
cmp #SINY_LEN
bcc __b9
!:
// i_y -= SINY_LEN
sec
lda.z i_y
sbc #SINY_LEN
sta.z i_y
lda.z i_y+1
sbc #0
sta.z i_y+1
__b9:
// for(char s=0;s<NUM_SPRITES;s++)
inc.z s
jmp __b5
}
main: {
// Copy 8* sprite attributes to VRAM
.label vram_sprite_attr = $a
.label s = 9
// memcpy_to_vram((char)>SPRITE_PIXELS_VRAM, <SPRITE_PIXELS_VRAM, SPRITE_PIXELS, 64*64)
// Copy sprite data to VRAM
lda #<$40*$40
sta.z memcpy_to_vram.num
lda #>$40*$40
sta.z memcpy_to_vram.num+1
lda #<SPRITE_PIXELS
sta.z memcpy_to_vram.src
lda #>SPRITE_PIXELS
sta.z memcpy_to_vram.src+1
ldx #0
lda #<SPRITE_PIXELS_VRAM&$ffff
sta.z memcpy_to_vram.vdest
lda #>SPRITE_PIXELS_VRAM&$ffff
sta.z memcpy_to_vram.vdest+1
jsr memcpy_to_vram
// memcpy_to_vram((char)>VERA_PALETTE, <VERA_PALETTE, SPRITE_PIXELS+64*64, 0x200)
// Copy sprite palette to VRAM
lda #<$200
sta.z memcpy_to_vram.num
lda #>$200
sta.z memcpy_to_vram.num+1
lda #<SPRITE_PIXELS+$40*$40
sta.z memcpy_to_vram.src
lda #>SPRITE_PIXELS+$40*$40
sta.z memcpy_to_vram.src+1
ldx #VERA_PALETTE>>$10
lda #<VERA_PALETTE&$ffff
sta.z memcpy_to_vram.vdest
lda #>VERA_PALETTE&$ffff
sta.z memcpy_to_vram.vdest+1
jsr memcpy_to_vram
lda #<VERA_SPRITE_ATTR&$ffff
sta.z vram_sprite_attr
lda #>VERA_SPRITE_ATTR&$ffff
sta.z vram_sprite_attr+1
lda #0
sta.z s
__b1:
// for(char s=0;s<NUM_SPRITES;s++)
lda.z s
cmp #$20
bcc __b2
// *VERA_CTRL &= ~VERA_DCSEL
// Enable sprites
lda #VERA_DCSEL^$ff
and VERA_CTRL
sta VERA_CTRL
// *VERA_DC_VIDEO |= VERA_SPRITES_ENABLE
lda #VERA_SPRITES_ENABLE
ora VERA_DC_VIDEO
sta VERA_DC_VIDEO
// asm
sei
// *KERNEL_IRQ = &irq_vsync
lda #<irq_vsync
sta KERNEL_IRQ
lda #>irq_vsync
sta KERNEL_IRQ+1
// *VERA_IEN = VERA_VSYNC
lda #VERA_VSYNC
sta VERA_IEN
// asm
cli
// }
rts
__b2:
// SPRITE_ATTR.X += 10
lda #<$a
clc
adc SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X
sta SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X
lda #>$a
adc SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X+1
sta SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X+1
// SPRITE_ATTR.Y += 10
lda #<$a
clc
adc SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y
sta SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y
lda #>$a
adc SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y+1
sta SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y+1
// memcpy_to_vram((char)>VERA_SPRITE_ATTR, vram_sprite_attr, &SPRITE_ATTR, sizeof(SPRITE_ATTR))
lda.z vram_sprite_attr
sta.z memcpy_to_vram.vdest
lda.z vram_sprite_attr+1
sta.z memcpy_to_vram.vdest+1
lda #<SIZEOF_STRUCT_VERA_SPRITE
sta.z memcpy_to_vram.num
lda #>SIZEOF_STRUCT_VERA_SPRITE
sta.z memcpy_to_vram.num+1
lda #<SPRITE_ATTR
sta.z memcpy_to_vram.src
lda #>SPRITE_ATTR
sta.z memcpy_to_vram.src+1
ldx #VERA_SPRITE_ATTR>>$10
jsr memcpy_to_vram
// vram_sprite_attr += sizeof(SPRITE_ATTR)
lda #SIZEOF_STRUCT_VERA_SPRITE
clc
adc.z vram_sprite_attr
sta.z vram_sprite_attr
bcc !+
inc.z vram_sprite_attr+1
!:
// for(char s=0;s<NUM_SPRITES;s++)
inc.z s
jmp __b1
}
// Copy block of memory (from RAM to VRAM)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination in VRAM.
// - vbank: Which 64K VRAM bank to put data into (0/1)
// - vdest: The destination address in VRAM
// - src: The source address in RAM
// - num: The number of bytes to copy
// memcpy_to_vram(byte register(X) vbank, void* zp($c) vdest, void* zp($e) src, word zp($10) num)
memcpy_to_vram: {
.label end = $10
.label s = $e
.label vdest = $c
.label src = $e
.label num = $10
// *VERA_CTRL &= ~VERA_ADDRSEL
// Select DATA0
lda #VERA_ADDRSEL^$ff
and VERA_CTRL
sta VERA_CTRL
// <vdest
lda.z vdest
// *VERA_ADDRX_L = <vdest
// Set address
sta VERA_ADDRX_L
// >vdest
lda.z vdest+1
// *VERA_ADDRX_M = >vdest
sta VERA_ADDRX_M
// VERA_INC_1 | vbank
txa
ora #VERA_INC_1
// *VERA_ADDRX_H = VERA_INC_1 | vbank
sta VERA_ADDRX_H
// end = (char*)src+num
lda.z end
clc
adc.z src
sta.z end
lda.z end+1
adc.z src+1
sta.z end+1
__b1:
// for(char *s = src; s!=end; s++)
lda.z s+1
cmp.z end+1
bne __b2
lda.z s
cmp.z end
bne __b2
// }
rts
__b2:
// *VERA_DATA0 = *s
ldy #0
lda (s),y
sta VERA_DATA0
// for(char *s = src; s!=end; s++)
inc.z s
bne !+
inc.z s+1
!:
jmp __b1
}
.segment Data
// A 64*64 8bpp TUT sprite and palette
.align $1000
SPRITE_PIXELS:
.var pic = LoadPicture("tut.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)
}
// Output pixel as palette index
.byte idx
}
}
.if(nxt_idx>256) .error "Image has too many colours "+nxt_idx
// Output sprite palette (at offset 64*64 bytes)
.for(var i=0;i<256;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
}
.align $100
SINX:
.fillword 256, 288+288*sin(i*2*PI/SINX_LEN)
.align $100
SINY:
.fillword 256, 208+208*sin(i*2*PI/SINY_LEN)
// Sprite attributes: 8bpp, in front, 64x64, address SPRITE_PIXELS_VRAM
SPRITE_ATTR: .word (SPRITE_PIXELS_VRAM/$20&$ffff)|VERA_SPRITE_8BPP, $140-$20, $f0-$20
.byte $c, $f0

View File

@ -1,150 +0,0 @@
void __start()
__start: scope:[__start] from
[0] phi()
to:__start::__init1
__start::__init1: scope:[__start] from __start
[1] sin_idx_x = $77
[2] sin_idx_y = $4f
to:__start::@1
__start::@1: scope:[__start] from __start::__init1
[3] phi()
[4] call main
to:__start::@return
__start::@return: scope:[__start] from __start::@1
[5] return
to:@return
__interrupt(rom_sys_cx16) void irq_vsync()
irq_vsync: scope:[irq_vsync] from
[6] sin_idx_x = ++ sin_idx_x
[7] if(sin_idx_x!=SINX_LEN) goto irq_vsync::@1
to:irq_vsync::@3
irq_vsync::@3: scope:[irq_vsync] from irq_vsync
[8] sin_idx_x = 0
to:irq_vsync::@1
irq_vsync::@1: scope:[irq_vsync] from irq_vsync irq_vsync::@3
[9] sin_idx_y = -- sin_idx_y
[10] if(sin_idx_y!=$ffff) goto irq_vsync::@2
to:irq_vsync::@4
irq_vsync::@4: scope:[irq_vsync] from irq_vsync::@1
[11] sin_idx_y = SINY_LEN-1
to:irq_vsync::@2
irq_vsync::@2: scope:[irq_vsync] from irq_vsync::@1 irq_vsync::@4
[12] irq_vsync::i_x#0 = sin_idx_x
[13] irq_vsync::i_y#0 = sin_idx_y
to:irq_vsync::@5
irq_vsync::@5: scope:[irq_vsync] from irq_vsync::@2 irq_vsync::@9
[14] irq_vsync::vram_sprite_pos#2 = phi( irq_vsync::@2/(byte*)<VERA_SPRITE_ATTR+2, irq_vsync::@9/irq_vsync::vram_sprite_pos#1 )
[14] irq_vsync::i_y#3 = phi( irq_vsync::@2/irq_vsync::i_y#0, irq_vsync::@9/irq_vsync::i_y#9 )
[14] irq_vsync::i_x#3 = phi( irq_vsync::@2/irq_vsync::i_x#0, irq_vsync::@9/irq_vsync::i_x#7 )
[14] irq_vsync::s#2 = phi( irq_vsync::@2/0, irq_vsync::@9/irq_vsync::s#1 )
[15] if(irq_vsync::s#2<$20) goto irq_vsync::@6
to:irq_vsync::@7
irq_vsync::@7: scope:[irq_vsync] from irq_vsync::@5
[16] *VERA_ISR = VERA_VSYNC
asm { jmp$e034 }
to:irq_vsync::@return
irq_vsync::@return: scope:[irq_vsync] from irq_vsync::@7
[18] return
to:@return
irq_vsync::@6: scope:[irq_vsync] from irq_vsync::@5
[19] irq_vsync::$11 = irq_vsync::i_x#3 << 1
[20] irq_vsync::$13 = SINX + irq_vsync::$11
[21] *((word*)&SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X) = *irq_vsync::$13
[22] irq_vsync::$12 = irq_vsync::i_y#3 << 1
[23] irq_vsync::$14 = SINY + irq_vsync::$12
[24] *((word*)&SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y) = *irq_vsync::$14
[25] memcpy_to_vram::vdest#3 = (void*)irq_vsync::vram_sprite_pos#2
[26] call memcpy_to_vram
to:irq_vsync::@12
irq_vsync::@12: scope:[irq_vsync] from irq_vsync::@6
[27] irq_vsync::vram_sprite_pos#1 = irq_vsync::vram_sprite_pos#2 + SIZEOF_STRUCT_VERA_SPRITE
[28] irq_vsync::i_x#1 = irq_vsync::i_x#3 + $19
[29] if(irq_vsync::i_x#1<SINX_LEN) goto irq_vsync::@8
to:irq_vsync::@10
irq_vsync::@10: scope:[irq_vsync] from irq_vsync::@12
[30] irq_vsync::i_x#2 = irq_vsync::i_x#1 - SINX_LEN
to:irq_vsync::@8
irq_vsync::@8: scope:[irq_vsync] from irq_vsync::@10 irq_vsync::@12
[31] irq_vsync::i_x#7 = phi( irq_vsync::@10/irq_vsync::i_x#2, irq_vsync::@12/irq_vsync::i_x#1 )
[32] irq_vsync::i_y#1 = irq_vsync::i_y#3 + $13
[33] if(irq_vsync::i_y#1<SINY_LEN) goto irq_vsync::@9
to:irq_vsync::@11
irq_vsync::@11: scope:[irq_vsync] from irq_vsync::@8
[34] irq_vsync::i_y#2 = irq_vsync::i_y#1 - SINY_LEN
to:irq_vsync::@9
irq_vsync::@9: scope:[irq_vsync] from irq_vsync::@11 irq_vsync::@8
[35] irq_vsync::i_y#9 = phi( irq_vsync::@11/irq_vsync::i_y#2, irq_vsync::@8/irq_vsync::i_y#1 )
[36] irq_vsync::s#1 = ++ irq_vsync::s#2
to:irq_vsync::@5
void main()
main: scope:[main] from __start::@1
[37] phi()
[38] call memcpy_to_vram
to:main::@5
main::@5: scope:[main] from main
[39] phi()
[40] call memcpy_to_vram
to:main::@1
main::@1: scope:[main] from main::@5 main::@6
[41] main::vram_sprite_attr#2 = phi( main::@5/(byte*)<VERA_SPRITE_ATTR, main::@6/main::vram_sprite_attr#1 )
[41] main::s#2 = phi( main::@5/0, main::@6/main::s#1 )
[42] if(main::s#2<$20) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@1
[43] *VERA_CTRL = *VERA_CTRL & ~VERA_DCSEL
[44] *VERA_DC_VIDEO = *VERA_DC_VIDEO | VERA_SPRITES_ENABLE
to:main::SEI1
main::SEI1: scope:[main] from main::@3
asm { sei }
to:main::@4
main::@4: scope:[main] from main::SEI1
[46] *KERNEL_IRQ = &irq_vsync
[47] *VERA_IEN = VERA_VSYNC
to:main::CLI1
main::CLI1: scope:[main] from main::@4
asm { cli }
to:main::@return
main::@return: scope:[main] from main::CLI1
[49] return
to:@return
main::@2: scope:[main] from main::@1
[50] *((word*)&SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X) = *((word*)&SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_X) + $a
[51] *((word*)&SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y) = *((word*)&SPRITE_ATTR+OFFSET_STRUCT_VERA_SPRITE_Y) + $a
[52] memcpy_to_vram::vdest#2 = (void*)main::vram_sprite_attr#2
[53] call memcpy_to_vram
to:main::@6
main::@6: scope:[main] from main::@2
[54] main::vram_sprite_attr#1 = main::vram_sprite_attr#2 + SIZEOF_STRUCT_VERA_SPRITE
[55] main::s#1 = ++ main::s#2
to:main::@1
void memcpy_to_vram(byte memcpy_to_vram::vbank , void* memcpy_to_vram::vdest , void* memcpy_to_vram::src , word memcpy_to_vram::num)
memcpy_to_vram: scope:[memcpy_to_vram] from irq_vsync::@6 main main::@2 main::@5
[56] memcpy_to_vram::num#4 = phi( irq_vsync::@6/4, main/(word)$40*$40, main::@2/SIZEOF_STRUCT_VERA_SPRITE, main::@5/$200 )
[56] memcpy_to_vram::src#4 = phi( irq_vsync::@6/(void*)&SPRITE_ATTR+2, main/(void*)SPRITE_PIXELS, main::@2/(void*)&SPRITE_ATTR, main::@5/(void*)SPRITE_PIXELS+(word)$40*$40 )
[56] memcpy_to_vram::vbank#4 = phi( irq_vsync::@6/irq_vsync::vram_sprite_attr_bank, main/0, main::@2/(byte)>VERA_SPRITE_ATTR, main::@5/(byte)>VERA_PALETTE )
[56] memcpy_to_vram::vdest#4 = phi( irq_vsync::@6/memcpy_to_vram::vdest#3, main/(void*)<SPRITE_PIXELS_VRAM, main::@2/memcpy_to_vram::vdest#2, main::@5/(void*)<VERA_PALETTE )
[57] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
[58] memcpy_to_vram::$0 = < memcpy_to_vram::vdest#4
[59] *VERA_ADDRX_L = memcpy_to_vram::$0
[60] memcpy_to_vram::$1 = > memcpy_to_vram::vdest#4
[61] *VERA_ADDRX_M = memcpy_to_vram::$1
[62] memcpy_to_vram::$2 = VERA_INC_1 | memcpy_to_vram::vbank#4
[63] *VERA_ADDRX_H = memcpy_to_vram::$2
[64] memcpy_to_vram::end#0 = (byte*)memcpy_to_vram::src#4 + memcpy_to_vram::num#4
[65] memcpy_to_vram::s#4 = (byte*)memcpy_to_vram::src#4
to:memcpy_to_vram::@1
memcpy_to_vram::@1: scope:[memcpy_to_vram] from memcpy_to_vram memcpy_to_vram::@2
[66] memcpy_to_vram::s#2 = phi( memcpy_to_vram/memcpy_to_vram::s#4, memcpy_to_vram::@2/memcpy_to_vram::s#1 )
[67] if(memcpy_to_vram::s#2!=memcpy_to_vram::end#0) goto memcpy_to_vram::@2
to:memcpy_to_vram::@return
memcpy_to_vram::@return: scope:[memcpy_to_vram] from memcpy_to_vram::@1
[68] return
to:@return
memcpy_to_vram::@2: scope:[memcpy_to_vram] from memcpy_to_vram::@1
[69] *VERA_DATA0 = *memcpy_to_vram::s#2
[70] memcpy_to_vram::s#1 = ++ memcpy_to_vram::s#2
to:memcpy_to_vram::@1

File diff suppressed because it is too large Load Diff

View File

@ -1,136 +0,0 @@
const nomodify void()** KERNEL_IRQ = (void()**) 788
const byte OFFSET_STRUCT_VERA_SPRITE_X = 2
const byte OFFSET_STRUCT_VERA_SPRITE_Y = 4
const word* SINX[SINX_LEN] = kickasm {{ .fillword 256, 288+288*sin(i*2*PI/SINX_LEN)
}}
const nomodify byte SINX_LEN = $f1
const word* SINY[SINY_LEN] = kickasm {{ .fillword 256, 208+208*sin(i*2*PI/SINY_LEN)
}}
const nomodify byte SINY_LEN = $fb
const byte SIZEOF_STRUCT_VERA_SPRITE = 8
struct VERA_SPRITE SPRITE_ATTR loadstore mem[8] = { ADDR: <SPRITE_PIXELS_VRAM/$20|VERA_SPRITE_8BPP, X: $140-$20, Y: (word)$f0-$20, CTRL1: $c, CTRL2: $f0 }
const byte* SPRITE_PIXELS[$40*$40+$200] = kickasm {{ .var pic = LoadPicture("tut.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)
}
// Output pixel as palette index
.byte idx
}
}
.if(nxt_idx>256) .error "Image has too many colours "+nxt_idx
// Output sprite palette (at offset 64*64 bytes)
.for(var i=0;i<256;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
}
}}
const nomodify dword SPRITE_PIXELS_VRAM = $8000
const nomodify byte VERA_ADDRSEL = 1
const nomodify byte* VERA_ADDRX_H = (byte*) 40738
const nomodify byte* VERA_ADDRX_L = (byte*) 40736
const nomodify byte* VERA_ADDRX_M = (byte*) 40737
const nomodify byte* VERA_CTRL = (byte*) 40741
const nomodify byte* VERA_DATA0 = (byte*) 40739
const nomodify byte VERA_DCSEL = 2
const nomodify byte* VERA_DC_VIDEO = (byte*) 40745
const nomodify byte* VERA_IEN = (byte*) 40742
const nomodify byte VERA_INC_1 = $10
const nomodify byte* VERA_ISR = (byte*) 40743
const nomodify dword VERA_PALETTE = $1fa00
const byte VERA_SPRITES_ENABLE = $40
const nomodify word VERA_SPRITE_8BPP = $8000
const nomodify dword VERA_SPRITE_ATTR = $1fc00
const nomodify byte VERA_VSYNC = 1
void __start()
__interrupt(rom_sys_cx16) void irq_vsync()
word~ irq_vsync::$11 zp[2]:22 22.0
word~ irq_vsync::$12 zp[2]:24 22.0
word*~ irq_vsync::$13 zp[2]:22 22.0
word*~ irq_vsync::$14 zp[2]:24 22.0
word irq_vsync::i_x
word irq_vsync::i_x#0 i_x zp[2]:3 2.0
word irq_vsync::i_x#1 i_x zp[2]:3 22.0
word irq_vsync::i_x#2 i_x zp[2]:3 22.0
word irq_vsync::i_x#3 i_x zp[2]:3 3.1818181818181817
word irq_vsync::i_x#7 i_x zp[2]:3 5.5
word irq_vsync::i_y
word irq_vsync::i_y#0 i_y zp[2]:5 4.0
word irq_vsync::i_y#1 i_y zp[2]:5 22.0
word irq_vsync::i_y#2 i_y zp[2]:5 22.0
word irq_vsync::i_y#3 i_y zp[2]:5 2.333333333333333
word irq_vsync::i_y#9 i_y zp[2]:5 16.5
byte irq_vsync::s
byte irq_vsync::s#1 s zp[1]:2 22.0
byte irq_vsync::s#2 s zp[1]:2 1.736842105263158
const nomodify byte irq_vsync::vram_sprite_attr_bank = (byte)>VERA_SPRITE_ATTR
byte* irq_vsync::vram_sprite_pos
byte* irq_vsync::vram_sprite_pos#1 vram_sprite_pos zp[2]:7 2.2
byte* irq_vsync::vram_sprite_pos#2 vram_sprite_pos zp[2]:7 2.2
void main()
byte main::s
byte main::s#1 s zp[1]:9 202.0
byte main::s#2 s zp[1]:9 43.285714285714285
byte* main::vram_sprite_attr
byte* main::vram_sprite_attr#1 vram_sprite_attr zp[2]:10 101.0
byte* main::vram_sprite_attr#2 vram_sprite_attr zp[2]:10 33.666666666666664
void memcpy_to_vram(byte memcpy_to_vram::vbank , void* memcpy_to_vram::vdest , void* memcpy_to_vram::src , word memcpy_to_vram::num)
byte~ memcpy_to_vram::$0 reg byte a 2002.0
byte~ memcpy_to_vram::$1 reg byte a 2002.0
byte~ memcpy_to_vram::$2 reg byte a 2002.0
byte* memcpy_to_vram::end
byte* memcpy_to_vram::end#0 end zp[2]:16 16833.666666666664
word memcpy_to_vram::num
word memcpy_to_vram::num#4 num zp[2]:16 125.125
byte* memcpy_to_vram::s
byte* memcpy_to_vram::s#1 s zp[2]:14 200002.0
byte* memcpy_to_vram::s#2 s zp[2]:14 133668.3333333333
byte* memcpy_to_vram::s#4 s zp[2]:14 2002.0
void* memcpy_to_vram::src
void* memcpy_to_vram::src#4 src zp[2]:14
byte memcpy_to_vram::vbank
byte memcpy_to_vram::vbank#4 reg byte x 166.83333333333334
void* memcpy_to_vram::vdest
void* memcpy_to_vram::vdest#2 vdest zp[2]:12 202.0
void* memcpy_to_vram::vdest#3 vdest zp[2]:12 22.0
void* memcpy_to_vram::vdest#4 vdest zp[2]:12 528.5
volatile word sin_idx_x loadstore zp[2]:18 1.9999999999999998
volatile word sin_idx_y loadstore zp[2]:20 1.714285714285714
zp[1]:2 [ irq_vsync::s#2 irq_vsync::s#1 ]
zp[2]:3 [ irq_vsync::i_x#3 irq_vsync::i_x#0 irq_vsync::i_x#7 irq_vsync::i_x#2 irq_vsync::i_x#1 ]
zp[2]:5 [ irq_vsync::i_y#3 irq_vsync::i_y#0 irq_vsync::i_y#9 irq_vsync::i_y#2 irq_vsync::i_y#1 ]
zp[2]:7 [ irq_vsync::vram_sprite_pos#2 irq_vsync::vram_sprite_pos#1 ]
zp[1]:9 [ main::s#2 main::s#1 ]
zp[2]:10 [ main::vram_sprite_attr#2 main::vram_sprite_attr#1 ]
zp[2]:12 [ memcpy_to_vram::vdest#4 memcpy_to_vram::vdest#3 memcpy_to_vram::vdest#2 ]
reg byte x [ memcpy_to_vram::vbank#4 ]
zp[2]:14 [ memcpy_to_vram::src#4 memcpy_to_vram::s#2 memcpy_to_vram::s#4 memcpy_to_vram::s#1 ]
zp[2]:16 [ memcpy_to_vram::num#4 memcpy_to_vram::end#0 ]
zp[2]:18 [ sin_idx_x ]
zp[2]:20 [ sin_idx_y ]
zp[2]:22 [ irq_vsync::$11 irq_vsync::$13 ]
zp[2]:24 [ irq_vsync::$12 irq_vsync::$14 ]
reg byte a [ memcpy_to_vram::$0 ]
reg byte a [ memcpy_to_vram::$1 ]
reg byte a [ memcpy_to_vram::$2 ]
mem[8] [ SPRITE_ATTR ]