Skip to main content

Python implementation of the defMON C64 tracker's file format and register-level player.

Project description

pydefmon

test PyPI

Read, write and play defMON C64 tracker tunes from Python. The player emits the same per-frame SID register writes as the real defMON binary — verified byte-for-byte by a live-VICE integration test that compares pydefmon's per-frame output against the actual defMON binary running in anarkiwi/headlessvice.

Install

pip install pydefmon          # core
pip install pydefmon[wav]     # adds pyresidfp + numpy for WAV render

Quick start

from pydefmon import DefmonSong, DefmonPlayer, PatternEvent

# Read / edit / write tunes
song = DefmonSong.from_file("tune.prg")
print(song.pattern_events(0)[:4])
print(song.sidtab_row(0))
song.set_step(0, v1=1, v2=2, v3=3)        # arranger row 0 plays patterns 1/2/3
song.to_file("out.prg")

# Render per-frame SID writes
player = DefmonPlayer(song)
for _ in range(600):
    writes = player.play_frame()           # list of (reg, value) for one main-tick NMI
    for reg, value in writes:
        # reg is an absolute SID register address $D400..$D418
        ...

Render to WAV (requires the [wav] extra):

pydefmon-player path/to/tune.prg /tmp/tune.wav

Dump per-frame SID writes as JSONL without rendering audio:

pydefmon-player --dump-writes /tmp/tune.jsonl path/to/tune.prg

What's in the package

  • DefmonSong — the 22887-byte runtime RAM image at $1800..$7166, parsed from a .prg file. Region accessors for arrangers, sidTAB rows + DL bytes, pattern bodies; structured edit API (set_step, set_jump, set_dl, set_jp, set_pattern_events). Round-trips through the $D6C9 LOAD codec.
  • PatternEvent — one 4-byte pattern step (flag, slot_a, slot_b, note) with flag-bit constants and factories (note_on, delay, alt_end).
  • SidtabRow — one 15-byte sidTAB row decoded to named column attributes (WGh / WGl / AD / SR / TR / AF / PW low half; PS / RE / FV / CP / ACID high half) plus its companion jp and dl bytes.
  • SidcallFrame — one frame of a cascade walk via DefmonSong.sidcall_frames(start_row).
  • DefmonPlayer — frame-accurate per-NMI player IRQ model. play_frame() returns the 24 SID register writes that defMON's $1022 body would emit for one main player tick. import_runtime_state() lets you bridge from a live VICE / hardware RAM capture for byte-faithful continuation of a running tune.

See docs/SPEC.md for the canonical reference of the file format, the runtime RAM layout, and what every cell of every region means.

Tests

pip install -e .[dev]
python -m tools.fetch_fixtures        # one-time: populate build/fixtures/
python -m unittest discover -s tests -t .

The unit tests under tests/ pin every subsystem of the player and codec against synthetic .prg fixtures and against the .GLOW WORM fixture (Tomek Grynfelder, in the upstream defMON release). tools/fetch_fixtures.py downloads the upstream csdb.dk archive, extracts the .d64, and writes per-PRG files under build/fixtures/ (override with the PYDEFMON_FIXTURES_DIR env var). Tunes are not redistributed; tests that need a fixture skipTest when it is missing.

The live-VICE integration test under tests/integration/ boots the real defMON binary inside anarkiwi/headlessvice, captures its SID write stream, and asserts pydefmon's DefmonPlayer matches byte-for-byte. Run with:

pip install -e .[dev,integration]
PYDEFMON_INTEGRATION=1 python -m unittest tests.integration.test_player_vs_real

CI runs all three (test, lint, build, integration) on push and PR. Python 3.10 through 3.13.

License

GPL-3.0-or-later. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydefmon-0.2.0.tar.gz (75.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pydefmon-0.2.0-py3-none-any.whl (51.0 kB view details)

Uploaded Python 3

File details

Details for the file pydefmon-0.2.0.tar.gz.

File metadata

  • Download URL: pydefmon-0.2.0.tar.gz
  • Upload date:
  • Size: 75.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pydefmon-0.2.0.tar.gz
Algorithm Hash digest
SHA256 0f280542b24979c6f789f812d729946826a0f2d407e122d369c4f2b283ca8a86
MD5 4224064943426a22f436b368b21757c7
BLAKE2b-256 a841d6736f73f49dc6ba2f61e5e3a531d4370627193a6fd7fae4465c85a2f4ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydefmon-0.2.0.tar.gz:

Publisher: release.yml on anarkiwi/pydefmon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydefmon-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: pydefmon-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 51.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pydefmon-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 09ec9aa6597f409f65e04749099ba5757eab7c4befc39ea909f99c061cd4f525
MD5 8264766000747c7a2bffeb5a94c33bdb
BLAKE2b-256 e6e866b946cce42a350ba8ff98c9fa5a11274c36ef17614fd37da708451a8e0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydefmon-0.2.0-py3-none-any.whl:

Publisher: release.yml on anarkiwi/pydefmon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page