Login

Commodore 64

The Commodore 64 is the classic 8-bit home computer. Our C64 projects are written in 6502 assembly, built with the ACME cross-assembler into a .prg program file, and tested in the VICE emulator (x64sc).

ACME: https://sourceforge.net/projects/acme-crossass/ VICE: https://vice-emu.sourceforge.io Tools repository: https://git.teletype.hu/tools/c64-tools


Makefile

This Makefile provides a simple, reproducible workflow for building C64 assembly projects with ACME and running them in VICE. It is designed for small projects where all .asm files live in the project root and are assembled from a single entry point.

Overview

The workflow is based on four core ideas:

  • All .asm sources are assembled through a single entry file (main.asm) that !src-includes the rest
  • ACME produces one .prg file that loads and runs on a real C64 or in VICE
  • Version management is handled from metadata.json
  • CI/CD targets enable automated build, versioning, and deployment

Project Structure

TEXT
project-root/
├── main.asm
├── defs.asm
├── common.asm
├── ...
├── metadata.json
├── Makefile
└── README.md
  • main.asm is the assembler entry point; it includes the other .asm files
  • metadata.json holds the catalog metadata and the version
  • <project>.prg is generated by ACME

Configuration Variables

Variable Description Default
PROJECT Project name (used in artifact filenames and the catalog)
ASM Assembler binary acme
EMU Emulator binary x64sc
SRC Assembler entry point main.asm
TARGET Output program file $(PROJECT).prg
METADATA Metadata file metadata.json

The metadata.json File

JSON
{
  "name": "example",
  "title": "Example C64 Game",
  "author": "Teletype Games",
  "desc": "Short description of the game.",
  "site": "https://git.teletype.hu/games/example",
  "license": "MIT",
  "version": "1.0.0"
}
  • name must match the PROJECT variable in the Makefile
  • version drives ci-version
  • The rest (title, author, desc, site, license) is what the update server writes into the game catalog

Usage

Install Dependencies (macOS)

SH
make deps
  • Installs acme and vice via Homebrew (macOS only; on other systems install them manually).

Build (default)

SH
make build
  • Assembles main.asm (and everything it includes) with ACME
  • Produces <project>.prg
  • Only rebuilds when an .asm file changed

Run

SH
make run
  • Builds the project, then launches it in VICE (x64sc)

Clear / Rebuild

SH
make clear       # remove the .prg and CI artifacts
make rebuild     # clear + build
make rebuildrun  # clear + build + run

VS Code Tasks

The tools repository also contains an example-tasks.json that can be copied to .vscode/tasks.json. It wraps the local make targets (deps, build, run, clear, rebuild, rebuildrun), with build set as the default build task (Cmd+Shift+B).

CI/CD Targets

These targets are designed for automated continuous integration (Woodpecker CI). Each target reads the version from the .version file created by ci-version.

make ci-version

  • Extracts the version string from metadata.json
  • Appends the branch name (if not main/master) for development builds (e.g., dev-1.0.0-feature-foo)
  • Writes the version to a .version file for subsequent steps

make ci-build

  • Runs the normal build, then creates the versioned artifacts:
    • <project>-<version>.prg
    • <project>-<version>.metadata.json

make ci-artifact

  • Uploads the versioned .prg and .metadata.json to the droparea using scp
  • Uses sshpass for SSH authentication
  • Connection details are configured via environment variables (DROPAREA_HOST, DROPAREA_PORT, DROPAREA_USER, DROPAREA_TARGET_PATH)

make ci-update

  • Triggers the update server via curl with platform=c64
  • Uses a secret key (UPDATE_SECRET) to authorize the request
  • The server-side updater reads the metadata, creates/updates the catalog entry, and registers the .prg as the release cartridge

Generated Artifacts

File Description
<project>.prg The assembled C64 program
<project>-<version>.prg Versioned copy for release
<project>-<version>.metadata.json Versioned metadata for the update server

Requirements

  • make
  • acme (assembler)
  • x64sc from VICE (only for run)
  • sshpass and curl (for CI/CD targets)

Example file

https://git.teletype.hu/tools/c64-tools/src/branch/master/example-makefile.make


Pipeline

This document describes the Woodpecker CI pipeline used to build, upload, and publish a C64 game project.

Overview

The pipeline logic is almost entirely encapsulated within a Makefile, which is called by each pipeline step. This approach simplifies the CI configuration and keeps the build logic centralized.

The pipeline performs the following steps:

  1. Version Extraction: Extracts the game version from metadata.json.
  2. Build: Assembles the .prg with ACME and creates versioned artifacts.
  3. Upload Artifacts: Uploads the .prg and metadata to a remote server.
  4. Notify Update Server: Triggers a remote service to publish the new version.

Each step corresponds to a make ci-* target.

Step 1: Version Extraction

YAML
- name: version
  image: alpine
  commands:
    - 'apk add --no-cache make'
    - 'make ci-version'

What it does:

  • Uses a minimal Alpine Linux image.
  • Installs make.
  • Runs make ci-version, which reads the version from metadata.json, appends the branch name on development branches, and saves it to a .version file for subsequent steps to use.

Step 2: Build

YAML
- name: build
  image: debian:stable-slim
  commands:
    - 'apt-get update && apt-get install -y --no-install-recommends make acme'
    - 'make ci-build'

What it does:

  • Uses a Debian image, because the ACME cross-assembler is packaged in Debian (apt install acme) — no custom builder image is needed.
  • Runs make ci-build, which assembles the .prg and creates the versioned artifacts:
    • <project>-<version>.prg
    • <project>-<version>.metadata.json

Step 3: Artifact Upload

YAML
- name: artifact
  image: alpine
  environment:
    DROPAREA_HOST: vps.teletype.hu
    DROPAREA_PORT: 2223
    DROPAREA_TARGET_PATH: /home/drop
    DROPAREA_USER: drop
    DROPAREA_SSH_PASSWORD:
      from_secret: droparea_ssh_password
  commands:
    - 'apk add --no-cache make openssh-client sshpass'
    - 'make ci-artifact'

What it does:

  • Installs make and SSH tooling (openssh-client, sshpass).
  • Runs make ci-artifact, which uploads the versioned .prg and .metadata.json files to the droparea using scp.
  • Uses secrets for SSH authentication. The Makefile target reads the necessary environment variables.

Step 4: Update Notification

YAML
- name: update
  image: alpine
  environment:
    UPDATE_SERVER: https://games.vps.teletype.hu
    UPDATE_SECRET:
      from_secret: update_secret_key
  commands:
    - 'apk add --no-cache make curl'
    - 'make ci-update'

What it does:

  • Installs make and curl.
  • Runs make ci-update, which sends an HTTP request to the update server with query parameters:
    • secret - Authorization token
    • name - Project name
    • platform - Platform identifier (c64)
    • version - Version from .version file
  • The server reads <name>-<version>.metadata.json, creates or updates the catalog entry, and registers <name>-<version>.prg as the downloadable cartridge of the release.

Example request:

TXT
https://games.vps.teletype.hu/update?secret=<SECRET>&name=example&platform=c64&version=1.0.0

Result

After a successful run:

  • The game is assembled into a versioned .prg program file.
  • The .prg and its metadata are uploaded to the distribution server.
  • The public game index is updated automatically, with the .prg available for download.

This pipeline enables fully automated C64 releases where the entire build and release logic is managed by the project's Makefile.

Example file

https://git.teletype.hu/tools/c64-tools/src/branch/master/example-woodpecker.yaml