Skip to content

Commit

Permalink
c64: updates
Browse files Browse the repository at this point in the history
  • Loading branch information
sehugg committed Oct 26, 2024
1 parent 41952d8 commit e9fc216
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 23 deletions.
5 changes: 4 additions & 1 deletion presets/c64/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,12 @@ typedef enum { false, true } bool; // boolean

// enable ROM and interrupts
#define DISABLE_HIMEM() \
POKE(1, PEEK(1) | 0b111); \
POKE(1, PEEK(1) | 0b110); \
asm("plp");

// are we on a PAL system?
#define IS_PAL() (PEEK(0x2a6) != 0)

///// FUNCTIONS /////

// wait until specific raster line
Expand Down
72 changes: 72 additions & 0 deletions presets/c64/digisound.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <peekpoke.h>
#include <string.h>
#include <c64.h>
#include <cbm_petscii_charmap.h>

#include "sidmacros.h"
#include "common.h"
//#link "common.c"

void digi_setup(void) {
SID.v1.sr = 0xFF; // Voice 1 Sustain/Release
SID.v2.sr = 0xFF; // Voice 2 Sustain/Release
SID.v3.sr = 0xFF; // Voice 3 Sustain/Release
SID.v1.ctrl = 0x49; // Voice 1 Control Register
SID.v2.ctrl = 0x49; // Voice 2 Control Register
SID.v3.ctrl = 0x49; // Voice 3 Control Register
}

void cia2_wait() {
byte timer = CIA2.ta_lo;
while (CIA2.ta_lo < timer) ;
}

void digi_play(const char* snd, unsigned int len) {
unsigned int i; // loop counter
VIC.ctrl1 = 0; // disable video
asm("sei"); // disable interrupts
// setup CIA #2 timer
CIA2.cra = 0x00; // stop timer A
CIA2.ta_lo = IS_PAL() ? 123 : 128; // set lower timer value
CIA2.ta_hi = 0; // set upper timer value
CIA2.cra = 0x11; // start timer, continuous mode
// loop through all samples
for (i = 0; i < len; i++) {
// wait for timer to reset
cia2_wait();
// send upper 4-bit sample
SID.amp = snd[i] >> 4;
// wait for timer to reset
cia2_wait();
// send lower 4-bit sample
SID.amp = snd[i] & 15;
// make a video effect
VIC.bordercolor = i;
}
asm("cli"); // enable interrupts
VIC.ctrl1 = 0x1b; // enable video
CIA2.cra = 0x00; // stop timer A
VIC.bordercolor = COLOR_BLUE;
}

#ifdef __MAIN__

const char digisound[] = {
#embed "springchicken-b4.raw"
};

void main(void) {
clrscr();
digi_setup();
while (1) {
digi_play(digisound, 0xacf8L);
printf("\nPress ENTER to restart digi...\n");
getchar();
}
}

#endif
107 changes: 107 additions & 0 deletions presets/c64/fld.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@

#include "common.h"
//#link "common.c"

#include "rasterirq.h"
//#link "rasterirq.ca65"

#include "bcd.h"
//#link "bcd.c"

extern const unsigned char sinustable[0x100];
//#link "sinustable.c"

///// VARIABLES

byte frame = 0;
byte target_y;

byte fld_offsets[25];

///// FUNCTIONS

void line_crunch() {
// load scroll y
asm("lda %v", target_y);
asm("and #7");
asm("ora #$18");
asm("tax");
// get current raster line
asm("lda $d012");
// wait for next raster line
asm("@loop:");
asm("cmp $d012");
asm("beq @loop");
// set y scroll (ctrl1)
asm("stx $d011");
}

static byte target_line = 0;
static byte row;
static byte offset;

void display_list(void) {

VIC.bgcolor[0] = COLOR_CYAN;
VIC.bordercolor = COLOR_BLUE;

// set initial YSCROLL
SET_SCROLL_Y(fld_offsets[0]);

// set first target scanline
target_line = 48 + (fld_offsets[0] & 7);

// each row has its own FLD gap
for (row=1; row<25; row++) {
// get this row's gap distance
offset = fld_offsets[row];
// fire IRQ 3 lines before target
target_y = target_line - 3;
DLIST_NEXT(target_y);
// change Y scroll to avoid badline
line_crunch();
// set Y scroll for new badline
target_y = target_line + offset;
line_crunch();
// set target line for next IRQ
target_line += 8 + offset;
VIC.bgcolor[0] = row;
// exit loop if integer overflow
if (target_line < 48) break;
}

DLIST_RESTART(30);
}

void main() {
int i;

clrscr();

memset(COLOR_RAM, COLOR_BLUE, 1000);

for (i=0; i<40*25; i++)
POKE(0x400 + i, 205 + (rand() & 1));
for (i=40*25; i<1024; i++)
POKE(0x400 + i, i);
for (i=0; i<1024; i+=40)
POKE(0x400 + i, 122);

SET_VIC_BITMAP(0x1000);

DLIST_SETUP(display_list);

// game loop, repeat forever
while (1) {
// wait for end of frame
waitvsync();

// animate and set scroll_y
frame += 4;

// set FLD offsets via sinus table
for (i=0; i<25; i++) {
fld_offsets[i] = sinustable[frame + i*8] >> 5;
}
}
}
1 change: 0 additions & 1 deletion presets/c64/linecrunch.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ void main() {

SET_VIC_BITMAP(0x1000);

// setup rasterirq library for scoreboard split
DLIST_SETUP(display_list);

// game loop, repeat forever
Expand Down
11 changes: 7 additions & 4 deletions presets/c64/siddemo.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ static int sweep = 0;
#define BITMAP_START 0xe020

// recursive macros to quickly set bitmap memory
#define SID_SIGNAL(index) \
POKE(BITMAP_START + (index), SID.noise)

#define SID_SIGNAL_4(index) \
POKE(BITMAP_START + (index) + 0, SID.noise); \
POKE(BITMAP_START + (index) + 1, SID.noise); \
POKE(BITMAP_START + (index) + 2, SID.noise); \
POKE(BITMAP_START + (index) + 3, SID.noise);
SID_SIGNAL(index); \
SID_SIGNAL(index+1); \
SID_SIGNAL(index+2); \
SID_SIGNAL(index+3);

#define SID_SIGNAL_16(index) \
SID_SIGNAL_4(index); \
Expand Down
12 changes: 4 additions & 8 deletions presets/c64/siegegame.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@ For more information, see "Making Arcade Games in C".

#include "common.h"

// BASL = text address of start of cursor line
byte** BASL = (byte**) 0xD1;

// get the character at a specfic x/y position
byte readcharxy(byte x, byte y) {
gotoxy(x,y); // set BASL
return (*BASL)[x]; // read character at (x,y)
return PEEK(SCRNADR(0x400, x, y));
}

// delay for 'count' frames
Expand All @@ -27,11 +23,11 @@ typedef struct {
byte x; // x coordinate
byte y; // y coordinate
byte dir; // direction (0-3)
word score; // current score
byte score; // current score
char head_attr; // char to draw player
char tail_attr; // char to draw trail
int collided:1; // did we collide? (boolean)
int human:1; // is this player a human? (boolean)
bool collided; // did we collide?
bool human; // is this player a human?
} Player;

Player players[2]; // two player structs
Expand Down
1 change: 1 addition & 0 deletions presets/c64/springchicken-b4.raw

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions presets/c64/test_display_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ word score = 0; // current player score
// display list used by rasterirq.h
// draws scoreboard and sets scroll register
void display_list() {
// set x scroll register to scroll value
SET_SCROLL_X(scroll_x);
// set background color
VIC.bgcolor[0] = COLOR_CYAN;
// set x scroll register to scroll value
SET_SCROLL_X(scroll_x);
// next interrupt is two rows from bottom
DLIST_NEXT(250-16);

Expand Down
14 changes: 10 additions & 4 deletions src/common/wasi/wasishim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,6 @@ export enum WASIErrors {
NOTCAPABLE = 76,
}



export class WASIFileDescriptor {
fdindex: number = -1;
protected data: Uint8Array = new Uint8Array(16);
Expand Down Expand Up @@ -622,9 +620,9 @@ export class WASIRunner {
if (dir == null) return WASIErrors.BADF;
if (dir.type !== FDType.DIRECTORY) return WASIErrors.NOTDIR;
const filename = this.peekUTF8(path_ptr, path_len);
const path = dir.name + '/' + filename;
const path = filename.startsWith('/') ? filename : dir.name + '/' + filename; // TODO?
const fd = this.fs.getFile(path);
console.log("path_filestat_get", dir+"", path, filestat_ptr, '->', fd+"");
console.log("path_filestat_get", dir+"", filename, path, filestat_ptr, '->', fd+"");
if (!fd) return WASIErrors.NOENT;
this.poke64(filestat_ptr, fd.fdindex); // dev
this.poke64(filestat_ptr + 8, 0); // ino
Expand All @@ -637,6 +635,7 @@ export class WASIRunner {
}
path_readlink(dirfd: number, path_ptr: number, path_len: number, buf_ptr: number, buf_len: number, buf_used_ptr: number) {
const dir = this.fds[dirfd];
debug("path_readlink", dirfd, path_ptr, path_len, buf_ptr, buf_len, buf_used_ptr, dir+"");
if (dir == null) return WASIErrors.BADF;
if (dir.type !== FDType.DIRECTORY) return WASIErrors.NOTDIR;
const filename = this.peekUTF8(path_ptr, path_len);
Expand All @@ -651,6 +650,9 @@ export class WASIRunner {
debug("path_readlink", path, '->', target);
return WASIErrors.SUCCESS;
}
path_readlinkat(dirfd: number, path_ptr: number, path_len: number, buf_ptr: number, buf_len: number, buf_used_ptr: number) {
return this.path_readlink(dirfd, path_ptr, path_len, buf_ptr, buf_len, buf_used_ptr);
}
path_unlink_file(dirfd: number, path_ptr: number, path_len: number) {
const dir = this.fds[dirfd];
if (dir == null) return WASIErrors.BADF;
Expand Down Expand Up @@ -697,6 +699,10 @@ export class WASIRunner {
getEnv() {
return {
__syscall_unlinkat() { warning('TODO: unlink'); return WASIErrors.NOTSUP; },
__syscall_faccessat() { warning("TODO: faccessat"); return WASIErrors.NOTSUP; },
__syscall_readlinkat: this.path_readlinkat.bind(this),
__syscall_getcwd() { warning("TODO: getcwd"); return WASIErrors.NOTSUP; },
__syscall_rmdir() { warning("TODO: rmdir"); return WASIErrors.NOTSUP; },
}
}
}
4 changes: 3 additions & 1 deletion src/platform/c64.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { BaseMAME6502Platform } from "../common/mameplatform";

const C64_PRESETS : Preset[] = [
{id:'helloc.c', name:'Hello World', category:'C'},
{id:'siegegame.c', name:'Siege Game'},
{id:'screen_ram.c', name:'Screen RAM'},
{id:'siegegame.c', name:'Siege Game'},
{id:'joymove.c', name:'Sprite Movement'},
{id:'sprite_collision.c', name:'Sprite Collision'},
{id:'scroll1.c', name:'Scrolling (Single Buffer)'},
Expand All @@ -29,10 +29,12 @@ const C64_PRESETS : Preset[] = [
{id:'musicplayer.c', name:'Music Player'},
//{id:'sidtune.dasm', name:'Tiny SID Tune (ASM)'},
{id:'siddemo.c', name:'SID Player Demo'},
{id:'digisound.c', name:'Digi Sound Player'},
{id:'climber.c', name:'Climber Game'},
{id:'test_border_sprites.c', name:'Sprites in the Borders'},
{id:'sprite_stretch.c', name:'Sprite Stretching'},
{id:'linecrunch.c', name:'Linecrunch'},
{id:'fld.c', name:'Flexible Line Distance'},
{id:'plasma.c', name:'Plasma Demo'},
{id:'23matches.c', name:'23 Matches'},
{id:'tgidemo.c', name:'TGI Graphics Demo'},
Expand Down
4 changes: 2 additions & 2 deletions src/test/testwasishim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ describe('test WASI oscar64', function () {
let shim = await loadOscar64();
const zipdata = fs.readFileSync(`./src/worker/fs/oscar64-fs.zip`);
shim.fs = await unzipWASIFilesystem(zipdata, "/root/");
shim.addPreopenDirectory("/root");
shim.fs.putSymbolicLink("/proc/self/exe", "/root/bin/oscar64");
shim.fs.putFile("/root/main.c", "#include <stdio.h>\nint main() { return 0; }");
shim.addPreopenDirectory("");
shim.setArgs(["oscar64", '-v', '-o=foo.prg', '/root/main.c']);
shim.setArgs(["oscar64", '-v', '-o=foo.prg', 'main.c']);
let errno = shim.run();
const stdout = shim.fds[1].getBytesAsString();
console.log(stdout);
Expand Down

0 comments on commit e9fc216

Please sign in to comment.