c64 0.1.0-alpha.1

Driver for the Commodore 64 platform
Documentation
#include <stdint.h>

// https://www.c64-wiki.com/wiki/POLY1
// https://www.the-dreams.de/aay64/ROME043.HTM
void kernal_poly1(uint8_t* addr) {
    uint8_t a = (uint8_t) ((uint16_t) addr);
    uint8_t y = (uint8_t) ((uint16_t) addr >> 8);
    asm volatile(
        "jsr $E043"
        :: "a" (a), "y" (y)
    );
}

// https://www.c64-wiki.com/wiki/POLY1
// https://www.the-dreams.de/aay64/ROME043.HTM
void kernal_poly2(uint8_t* addr) {
    uint8_t a = (uint8_t) ((uint16_t) addr);
    uint8_t y = (uint8_t) ((uint16_t) addr >> 8);
    asm volatile(
        "jsr $E059"
        :: "a" (a), "y" (y)
    );
}

// https://www.c64-wiki.com/wiki/COS_(ROM_Routine)
// https://www.the-dreams.de/aay64/ROME264.HTM
void kernal_cos() {
    asm volatile("jsr $E264");
}

// https://www.the-dreams.de/aay64/ROME26B.HTM
void kernal_sin() {
    asm volatile("jsr $E26B");
}

// https://www.the-dreams.de/aay64/ROME2B4.HTM
void kernal_tan() {
    asm volatile("jsr $E2B4");
}

// https://www.c64-wiki.com/wiki/ATN_(ROM_Routine)
// https://www.the-dreams.de/aay64/ROME30E.HTM
void kernal_atn() {
    asm volatile("jsr $E30E");
}

// https://www.c64-wiki.com/wiki/CHROUT
// https://www.the-dreams.de/aay64/ROMFFD2.HTM
void kernal_chrout(uint8_t c) {
    asm volatile(
        "jsr $FFD2"
        :: "a" (c)
    );
}

// SETTIM expects A = LSB, X = middle byte, Y = MSB (the routine at $F6E4
// stores them with `STA $A2 / STX $A1 / STY $A0`, and the jiffy clock at
// $A0..$A2 is big-endian: $A0 = MSB, $A2 = LSB).
//
// https://www.the-dreams.de/aay64/ROMFFDB.HTM
void kernal_settim(uint32_t time) {
    uint8_t a = (uint8_t) time;
    uint8_t x = (uint8_t) (time >> 8);
    uint8_t y = (uint8_t) (time >> 16);
    asm volatile(
        "jsr $FFDB"
        :: "a" (a), "x" (x), "y" (y)
    );
}

// RDTIM returns A = LSB, X = middle byte, Y = MSB (mirror of SETTIM's
// convention; the routine at $F6DD does `LDA $A2 / LDX $A1 / LDY $A0`).
//
// https://www.the-dreams.de/aay64/ROMFFDE.HTM
uint32_t kernal_rdtim() {
    uint8_t a, x, y;
    asm volatile(
        "jsr $FFDE"
        : "=a" (a), "=x" (x), "=y" (y)
    );
    return ((uint32_t) y << 16) | ((uint32_t) x << 8) | ((uint32_t) a);
}

// https://www.the-dreams.de/aay64/ROMFFED.HTM
uint16_t kernal_screen() {
    uint8_t cols, rows;
    asm volatile(
        "jsr $FFED"
        : "=x" (cols), "=y" (rows)
    );
    return ((uint16_t) cols << 8) | (uint16_t) rows;
}

// https://www.c64-wiki.com/wiki/PLOT_(KERNAL)
// https://www.the-dreams.de/aay64/ROMFFF0.HTM
uint16_t kernal_plot_get() {
    uint8_t row, col;
    asm volatile(
        "sec\n\t"
        "jsr $FFF0"
        : "=x" (row), "=y" (col)
    );
    return ((uint16_t) row << 8) | (uint16_t) col;
}

// https://www.c64-wiki.com/wiki/PLOT_(KERNAL)
// https://www.the-dreams.de/aay64/ROMFFF0.HTM
void kernal_plot_set(uint8_t row, uint8_t col) {
    asm volatile(
        "clc\n\t"
        "jsr $FFF0"
        :: "x" (row), "y" (col)
        : "a"
    );
}