c64: .wiz

This commit is contained in:
Steven Hugg 2023-11-02 08:17:15 -05:00
parent 483675fded
commit fc432a3bbf
5 changed files with 343 additions and 23 deletions

127
presets/c64/c64.wiz Normal file
View File

@ -0,0 +1,127 @@
struct CoordXY {
x : u8,
y : u8
}
struct SIDVoice {
freq : u16, /* Frequency */
pw : u16, /* Pulse width */
ctrl : u16, /* Control register */
ad : u16, /* Attack/decay */
sr : u16 /* Sustain/release */
}
typealias SpriteData : [u8; 64];
union VICBank {
spritedata : [SpriteData; 256],
data : [u8; 0x4000]
}
namespace c64 {
extern var colorram @ 0xD800 : [u8; 0x400];
namespace color {
let BLACK = 0x00;
let WHITE = 0x01;
let RED = 0x02;
let CYAN = 0x03;
let PURPLE = 0x04;
let GREEN = 0x05;
let BLUE = 0x06;
let YELLOW = 0x07;
let ORANGE = 0x08;
let BROWN = 0x09;
let LIGHTRED = 0x0A;
let GRAY1 = 0x0B;
let GRAY2 = 0x0C;
let LIGHTGREEN = 0x0D;
let LIGHTBLUE = 0x0E;
let GRAY3 = 0x0F;
}
namespace vic {
namespace sprite {
extern var pos @ 0xD000 : [CoordXY; 8];
extern var coord @ 0xD000 : [u8; 16];
extern var hi_x @ 0xD010 : u8;
extern var enable @ 0xD015 : u8;
extern var expand_y @ 0xD017 : u8;
extern var priority @ 0xD01B : u8;
extern var multicolor @ 0xD01C : u8;
extern var expand_x @ 0xD01D : u8;
extern var coll @ 0xD01E : u8;
extern var coll_bg @ 0xD01F : u8;
extern var mcolor @ 0xD025 : [u8; 2];
extern var color @ 0xD027 : [u8; 8];
}
extern var control1 @ 0xD011 : u8;
extern var rasterline @ 0xD012 : u8;
extern var lightpen @ 0xD013 : CoordXY;
extern var control2 @ 0xD016 : u8;
extern var mem @ 0xD018 : u8;
extern var irr @ 0xD019 : u8;
extern var imr @ 0xD01A : u8;
extern var bordercolor @ 0xD020 : u8;
extern var bgcolor @ 0xD021 : [u8; 4];
}
namespace sid {
extern writeonly v1 @ 0xd400 : [SIDVoice; 3];
extern writeonly flt_freq @ 0xd415 : u16;/* Filter frequency */
extern writeonly flt_ctrl @ 0xd417 : u8; /* Filter control register */
extern writeonly amp @ 0xd418 : u8; /* Amplitude */
extern writeonly ad1 @ 0xd419 : u8; /* A/D converter 1 */
extern writeonly ad2 @ 0xd41a : u8; /* A/D converter 2 */
extern writeonly noise @ 0xd41b : u8; /* Noise generator */
extern const read3 @ 0xd41c : u8; /* Value of voice 3 */
}
namespace cia1 {
// CIA1 Registers
extern writeonly port_a @ 0xDC00 : u8;
extern const port_b @ 0xDC01 : u8;
extern writeonly data_direction_a @ 0xDC02 : u8;
extern writeonly data_direction_b @ 0xDC03 : u8;
extern const timer_a_lo @ 0xDC04 : u8;
extern const timer_a_hi @ 0xDC05 : u8;
extern const timer_b_lo @ 0xDC06 : u8;
extern const timer_b_hi @ 0xDC07 : u8;
extern const sdr @ 0xDC0C : u8;
extern const icr @ 0xDC0D : u8;
extern const cra @ 0xDC0E : u8;
extern const crb @ 0xDC0F : u8;
}
namespace cia2 {
// CIA2 Registers
extern writeonly port_a @ 0xDD00 : u8;
extern const port_b @ 0xDD01 : u8;
extern writeonly data_direction_a @ 0xDD02 : u8;
extern writeonly data_direction_b @ 0xDD03 : u8;
extern const timer_a_lo @ 0xDD04 : u8;
extern const timer_a_hi @ 0xDD05 : u8;
extern const timer_b_lo @ 0xDD06 : u8;
extern const timer_b_hi @ 0xDD07 : u8;
extern const sdr @ 0xDD0C : u8;
extern const icr @ 0xDD0D : u8;
extern const cra @ 0xDD0E : u8;
extern const crb @ 0xDD0F : u8;
}
namespace kernal {
let ioinit = 0xFDA3 as func;
let rantam = 0xFD50 as func;
let restor = 0xFD15 as func;
let cint = 0xFF5B as func;
let scnkey = 0xEA87 as func;
let chrin = 0xF157 as func : u8 in a;
let chrout = 0xF1CA as func(char : u8 in a);
let screen = 0xE505 as func : u16 in xy;
let plot_save = 0xE50A as func(save : bool in carry) : u16 in xy;
let plot_restore = 0xE50A as func(x : u8 in x, y : u8 in y, save : bool in carry);
}
}

181
presets/c64/hello.wiz Normal file
View File

@ -0,0 +1,181 @@
import "c64.wiz";
bank zeropage @ 0x02 : [vardata; 254];
bank stackpage @ 0x100 : [vardata; 256];
bank textscrn @ 0x400 : [vardata; 0x400];
bank ram @ 0x2000 : [vardata; 0x7800];
bank prghdr @ 0x7ff : [prgdata; 0x2];
bank prg @ 0x801 : [varinitdata; 0x7000];
in textscrn {
var scrn: [u8; 40*25];
var _unused: [u8; 16];
var spriteptr: [u8; 8];
}
extern var vicbank @ 0x0000 : VICBank;
// PRG file header
in prghdr {
const prgstart : u16 = 0x801;
}
// BASIC header
in prg {
namespace prgheader {
const nextline = &BASIC_END;
const linenum : u16 = 10;
const sysstmt = "\x9e 2062\0";
BASIC_END:
const hdrend : u16 = 0;
}
PRG_START:
/*
c64.kernal.ioinit();
c64.kernal.rantam();
c64.kernal.restor();
c64.kernal.cint();
*/
c64.vic.bordercolor = a = c64.color.ORANGE;
c64.kernal.chrout('A');
for x in 0..250 {
// scrn[x] = a = x;
// (&scrn[40*8])[x] = a = x;
// (0x600 as *u8)[x] = a = x;
(&scrn[40*12])[x] = a = message[x] + 0xc0;
}
for x in 0..255 {
a = message[x];
break if zero;
a += 0xc0;
(&scrn[40*20])[x] = a;
}
upandaway();
return;
const message = "HELLO WORLD!\0";
const SPRITE : [u8; 3*21] = [
/*{w:24,h:21,bpp:1,brev:1}*/
0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xE0,
0x03,0xE7,0xE0,0x07,0xD9,0xF0,0x07,0xDF,0xF0,
0x07,0xD9,0xF0,0x03,0xE7,0xE0,0x03,0xFF,0xE0,
0x03,0xFF,0xE0,0x02,0xFF,0xA0,0x01,0x7F,0x40,
0x01,0x3E,0x40,0x00,0x9C,0x80,0x00,0x9C,0x80,
0x00,0x49,0x00,0x00,0x49,0x00,0x00,0x3E,0x00,
0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00
];
const yValues : [u8] = [
32, 35, 38, 41, 44, 47, 49, 52,
54, 56, 58, 60, 61, 62, 63, 63,
64, 63, 63, 62, 61, 60, 58, 56,
54, 52, 49, 47, 44, 41, 38, 35,
32, 28, 25, 22, 19, 16, 14, 11,
9, 7, 5, 3, 2, 1, 0, 0,
0, 0, 0, 1, 2, 3, 5, 7,
9, 11, 14, 16, 19, 22, 25, 28
];
const pwr2 : [u8] = [
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
];
in zeropage {
var b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 : u8;
var w0 @ &b0, w2 @ &b2, w4 @ &b4, w6 @ &b6, w8 @ &b8, w10 @ &b10 : u16;
var ptr0 @ &b0, ptr2 @ &b2, ptr4 @ &b4, ptr6 @ &b6, ptr8 @ &b8, ptr10 @ &b10 : *u8;
}
inline func rasterWait(line : u8 in a) {
while (c64.vic.rasterline < line) { }
}
func upandaway() {
//unsigned char n, t;
//int rx, x;
//char sx, msb;
var xp : u16 in w0;
var rx : u16 in w2;
var msb : u8 in b4;
let sprdata = &vicbank.spritedata[13] as *u8;
c64.vic.bgcolor[0] = a = 3;
nointerrupt = true; // clear interrupts to avoid glitching
for y in 0..(sizeof(typeof(SPRITE)) - 1) {
sprdata[y] = a = SPRITE[y];
//POKE(832 + n, sprite[n]);
}
c64.vic.sprite.enable = a = 255;
for x in 0..7 {
spriteptr[x] = a = 13;
y = a = x<<1;
c64.vic.sprite.coord[y] = a = 50;
y ++;
c64.vic.sprite.coord[y] = a = 50;
//POKE(2040 + t, 13); // Set sprite x data from 13th block for all sprites
}
do {
<:xp = a = 0;
>:xp = a = 0;
//while (xp < 550) {
while (true) {
<:xp = a = <:xp + 1;
>:xp = a = >:xp +# 0;
msb = a = 0; // MSB of X coordinates
// Wait until raster hits position 250 before drawing upper sprites
rasterWait(250);
// Set border color, which indicates the raster position
c64.vic.bordercolor = a = 1;
<:rx = a = <:xp;
>:rx = a = >:xp;
for x in 0..7 {
<:rx = a = <:rx - 24;
>:rx = a = >:rx -# 0;
//if (rx >= 0 && rx < 366)
if (true) {
// if (rx > 255)
a = >:rx;
if (!zero) {
// Set MSB of x coordinate for sprite if x position > 255
a = msb;
a |= pwr2[x];
msb = a;
}
y = a = x<<1;
c64.vic.sprite.coord[y] = a = <:rx;
// Y position is an indirect Sinus function of X, using array
// index for retrieving the Y value
y = a = <:rx & 63;
a = yValues[y] + 40;
push(a);
y = a = (x<<1) + 1;
a = pop();
c64.vic.sprite.coord[y] = a;
} else {
c64.vic.sprite.pos[y].x = 0;
}
}
c64.vic.sprite.hi_x = a = msb; // Set MSB of x coordinate
// Wait until raster hits position 135 before drawing lower sprites
rasterWait(135);
c64.vic.bordercolor = a = 2; // Set border color
for x in 0..7 {
// Add 128 to current sprite Y position
y = a = (x<<1) + 1;
c64.vic.sprite.coord[y] = a = c64.vic.sprite.coord[y]+128;
}
cmp(a = >:xp, >:550);
if (zero) {
cmp(a = <:xp, <:550);
break if zero;
}
}
} while (true);
return;
}
}

View File

@ -1,7 +1,10 @@
// ported from
// https://odensskjegg.home.blog/2018/12/29/recreating-the-commodore-64-user-guide-code-samples-in-cc65-part-three-sprites/
#include "common.h"
//#include "common.h"
#include <peekpoke.h>
#include <c64.h>
/*{w:24,h:21,bpp:1,brev:1}*/
const char sprite[3*21] = {
@ -15,7 +18,7 @@ const char sprite[3*21] = {
};
// Pre-calculated sinus values
const char yValues[] = {
const char yValues[64] = {
32, 35, 38, 41, 44, 47, 49, 52,
54, 56, 58, 60, 61, 62, 63, 63,
64, 63, 63, 62, 61, 60, 58, 56,
@ -31,58 +34,66 @@ void rasterWait(unsigned char line) {
while (VIC.rasterline < line) ;
}
const char LUT[8] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
int main (void)
{
unsigned char n, t;
int rx, x;
char sx, msb;
unsigned char msb;
VIC.bgcolor0 = 3;
VIC.bgcolor0 = COLOR_CYAN; // set background color
__asm__("SEI"); // clear interrupts to avoid glitching
// Set 13th sprite bitmap
for (n = 0 ; n < sizeof(sprite) ; n++) {
POKE(832 + n, sprite[n]);
}
// enable all sprites
VIC.spr_ena = 255;
// Set all sprite pointers to 13th sprite
for (t = 0 ; t < 8 ; t++) {
POKE(2040 + t, 13); // Set sprite x data from 13th block for all sprites
POKE(2040 + t, 13);
}
do {
// loop forever
while(1) {
for (x = 0 ; x < 550; x++) {
msb = 0; // MSB of X coordinates
// MSB of each sprite's X coordinate (i.e. if X >= 256)
msb = 0;
// Wait until raster hits position 250 before drawing upper sprites
rasterWait(250);
// Set border color, which indicates the raster position
VIC.bordercolor = 1;
VIC.bordercolor = COLOR_RED;
rx = x;
// iterate over all 8 sprites
for (t = 0 ; t < 8 ; t++) {
VIC.bordercolor = t;
rx -= 24;
if (rx >= 0 && rx < 366) {
// Usually I would calculate the sprite X coordinate using
// the expression sx = rx % 256, but bitwise operation is
// significant faster
sx = rx & 255;
if (rx > 255) {
// Set MSB of x coordinate for sprite if x position > 255
msb |= 1 << t;
// Set MSB of x coordinate for sprite if x position > 255
if (x >= 256) {
msb |= LUT[t]; // look up 1 << t
}
VIC.spr_pos[t].x = sx;
VIC.spr_pos[t].x = x;
// Y position is an indirect Sinus function of X, using array
// index for retrieving the Y value
VIC.spr_pos[t].y = yValues[sx & 63] + 40;
VIC.spr_pos[t].y = yValues[x & 63] + 40;
} else {
VIC.spr_pos[t].x = 0;
}
}
VIC.spr_hi_x = msb; // Set MSB of x coordinate
// Set MSB of x coordinate
VIC.spr_hi_x = msb;
// Wait until raster hits position 135 before drawing lower sprites
VIC.bordercolor = COLOR_BLUE;
rasterWait(135);
VIC.bordercolor = 2; // Set border color
VIC.bordercolor = COLOR_RED;
// Add 128 to current sprite Y positions
for (t = 0 ; t < 8 ; t++) {
// Add 128 to current sprite Y position
VIC.spr_pos[t].y += 128;
}
}
} while (1);
return EXIT_SUCCESS;
}
return 0;
}

View File

@ -13,4 +13,4 @@ class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
if __name__ == '__main__':
http.server.test(HandlerClass=MyHTTPRequestHandler)
http.server.test(HandlerClass=MyHTTPRequestHandler, port=8000)

View File

@ -28,6 +28,7 @@ const C64_PRESETS = [
//{id:'sidtune.dasm', name:'Tiny SID Tune (ASM)'},
{id:'siddemo.c', name:'SID Player Demo'},
{id:'climber.c', name:'Climber Game'},
{id:'hello.wiz', name:'Hello Wiz (Wiz)'},
];
const C64_MEMORY_MAP = { main:[