defmon-driver
defmon-driver is a Python automation framework for driving
defMON — the Commodore 64 cross-platform
music editor by Ilkke / defcom — running inside
asid-vice, an extension of the VICE
C64 emulator that exposes a binary monitor with key-matrix tap and screen-
scrape opcodes.
It is designed for the case where you want to programmatically:
- boot defMON in an emulator,
- load a tune from disk,
- press keys (chords, super-commands, modal switches),
- read the screen back as text or screencode bytes,
- edit pattern / sidTAB / seqLIST fields,
- and snapshot CPU state, RAM, or per-instruction code coverage.
The driver's defMON-specific layer is pure-Python and depends only on
vice-driver (which itself has
no runtime dependencies beyond the standard library). vice-driver
provides the binary-monitor wire client, key matrix, screen scrape,
container management, coverage harness, and state-assertion helpers;
defmon-driver provides everything specific to defMON (mode handlers,
field setters, sidTAB calibration, tune navigation, etc.).
defMON is a property of its authors; this project is an independent automation harness and is not affiliated with the defMON project.
Requirements
- Python ≥ 3.10
- Docker, with the published
anarkiwi/asid-vice:latestimage (pulled automatically on first run, ordocker pull anarkiwi/asid-vice:latest) — seeanarkiwi/asid-vicefor the Dockerfile and build instructions. - A defMON-formatted
.d64disk image (e.g.defmon-20201008.d64ordefmon-withtunes.d64, both available from csdb.dk).
The package itself does not bundle defMON or any disk image — the user provides their own copy in line with the original distribution terms.
Installation
pip install defmon-driver
Or, for development:
git clone https://github.com/anarkiwi/defmon-driver
cd defmon-driver
pip install -e ".[dev]"
pytest tests/unit
Quick start
import logging
from vice_driver import BinMon, DiskMount, ViceContainer
from defmon_driver import Defmon
logging.basicConfig(level=logging.INFO)
# Spin up an asid-vice container that autostarts the defMON disk image.
container = ViceContainer(
autostart="/work/defmon.d64",
mounts=[DiskMount("/host/path/to/defmon.d64", "/work/defmon.d64", read_only=True)],
)
with container:
bm = BinMon("127.0.0.1", 6502)
bm.connect(timeout=10.0, attempts=80, retry_delay=0.25)
# Drain the initial halt and resume the CPU.
bm.exit()
d = Defmon(bm)
d.wait_for_defmon_loaded(timeout=90.0)
# Press F1 to start playback from cursor.
d.play_from_cursor()
# Scrape the screen back as 25 lines of ASCII.
print(d.screen().text())
d.stop_playback()
bm.close()
For higher-level workflows there are dedicated sub-modules. The
transport / emulator-control layer lives in
vice-driver; everything below
is defMON-specific.
| Module | Purpose |
|---|---|
vice_driver.binmon |
Binary-monitor wire client + checkpoint / cpuhistory wrappers |
vice_driver.keys |
C64 key-matrix names + ASCII → chord conversion |
vice_driver.screen |
SCREEN_GET parsing, screencode → ASCII, find_text() |
vice_driver.vice_docker |
One-shot Docker container management |
vice_driver.coverage |
Per-action code-coverage harness using CHECK_EXEC + cpuhistory |
vice_driver.expect |
Expect predicate + verify polling helper for post-action state assertions |
defmon_driver.defmon |
Every documented defMON keyboard shortcut as a Python method |
defmon_driver.keyhandler |
Direct-call keyboard injection (bypasses matrix scan / debounce) |
defmon_driver.field_setter |
High-level "set any UI field" API on top of keyhandler |
defmon_driver.sidtab |
sidTAB cell-level editing API driven by a calibration JSON |
defmon_driver.keycode_table |
name → $0E44 keycode resolver built from defMON's $0F90 LUT |
defmon_driver.calibrate_sidtab |
Auto-discover the sidTAB column → screen layout for a tune |
defmon_driver.tune_manifest |
Static manifest of example tunes shipped with the defMON d64s |
defmon_driver.tune_navigation |
Cursor-walk a tune off the disk menu by dir_index |
CLI smoke tests
Several modules expose a python -m … entry point that drives a real
asid-vice container end-to-end. They are not part of the CI unit-test
suite (CI is offline-only); they exist for manual validation against a
local Docker setup:
# End-to-end driver smoke: every documented chord + disk-menu round-trip.
python -m defmon_driver.smoke /path/to/defmon-20201008.d64
# Coverage harness smoke: install 176 page checkpoints, fire F1, verify the
# $80-$9F player band lights up.
python -m defmon_driver.smoke_coverage /path/to/defmon-20201008.d64
# Checkpoint + cpuhistory smoke.
python -m defmon_driver.smoke_checkpoint_cpuhistory /path/to/defmon-20201008.d64
# sidTAB calibration: discover the column → screen-cell mapping for a tune.
python -m defmon_driver.calibrate_sidtab \
--d64 /path/to/defmon-withtunes.d64 \
--tune ".GLOW WORM" \
--out sidtab_calibration.json
# sidTAB driving smoke: load .GLOW WORM, write JP/AD/SR/ACID cells.
python -m defmon_driver.smoke_sidtab \
--d64 /path/to/defmon-withtunes.d64 \
--tune ".GLOW WORM" \
--cal sidtab_calibration.json
# Chord-driven note write smoke: write_note_chord for Z..M, verify the
# expected note byte ($30..$3B) actually lands in pattern memory.
python -m defmon_driver.smoke_note_chord /path/to/defmon-20201008.d64
# Chord-driven sidcall1 smoke: cross-product V0/V1/V2 × {step 0,3,7} ×
# {0x00, 0x57, 0xAB, 0xFF}, verify each chord-driven write lands at the
# runtime cell address (catches the BUGS.md #2 regression class).
python -m defmon_driver.smoke_sidcall /path/to/defmon-20201008.d64
Known limitations
See BUGS.md for outstanding issues,
FUTURE.md for features that another contributor could pick
up, and CHANGELOG.md for behavioural changes —
including any breaking renames or fixes whose impact downstream callers
should review.
License
Apache 2.0 — see LICENSE.
Metadata
Release files for defmon-driver 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| defmon_driver-0.4.0.tar.gz | 77.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| defmon_driver-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 160.5 kB
Release files / defmon_driver-0.4.0.tar.gz
| Download URL | defmon_driver-0.4.0.tar.gz |
|---|---|
| Size | 77.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c8310d145c5eb7373e0133b9a81e42e0190002ecc0294181f07a8be327631973
|
|
BLAKE2b-256 checksum How to use checksums |
6b3f9bb05e87f2ef9158e5c53148f61760b4071f90cc3f471671d20c0cf7bdfb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.
Transparency logRelease files / defmon_driver-0.4.0-py3-none-any.whl
| Download URL | defmon_driver-0.4.0-py3-none-any.whl |
|---|---|
| Size | 83.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
359a2f76ac6bbbdba41cd0640971d3fa0bca199bb5b6575885eed80ade1e9732
|
|
BLAKE2b-256 checksum How to use checksums |
daa196474d50a3eff0055f2350a281c837a3d5f9d0e1838ba4affee8e605fd3c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.
Transparency log