Skip to main content

Shared base for pure-Python C64 SID tracker parsers: PSID/RSID container, loaded-image model, and packed/relocating playroutine detection

Project description

pysidtracker

Shared base for the pure-Python C64 SID tracker parsers (pygoattracker, pysidwizard, pydmcsid, pyfuturecomposer, pymusicassembler, pydefmon, pyjch, pysoundmonitor).

Reads .sid containers (PSID/RSID) and bare .prg images into a 64 KiB C64 memory model, and detects packed/relocating playroutines by running the tune's init in a 6502 emulator — container headers are not trusted. Each format package subclasses BaseSidParser for a consistent read / parse / detect API.

Components

  • parse_sid_header / SidHeader — PSID/RSID container header parsing.
  • SidImage — a loaded 64 KiB C64 memory image with absolute-addressed accessors, from a .sid container or a bare .prg.
  • read_bytes — path / bytes / file-like source dispatch.
  • SidError hierarchy — SidParseError, SidFormatError, EmulatorUnavailable.
  • detect_playroutine / PlayroutineKind — static signature recognition, then an emulated init run to classify DIRECT / RELOCATED / PACKED / UNKNOWN.
  • BaseSidParser — the base class each format subclasses.
  • CodePattern / find_code_all / find_code_first — masked 6502 code-fragment search with operand capture.
  • registers — C64 hardware register map (SID/CIA/VIC, IRQ/NMI and CPU vectors) with predicates and find_register_stores.
  • trace_init / InitTrace — run a tune's init under a write observer to report CIA timer cadence and the IRQ/NMI vectors an IRQ-driven header hides.
  • playroutine_cadence / Cadence / TriggerSource — derive the play-routine cadence (PAL/NTSC video frame vs CIA-timer latch) from what init programs, not the header.
  • native_decrunch — native exomizer unpack (pydexomizer), an init-free alternative depack path; opt-in via detect_playroutine(..., native=True).
  • reglogRegWrite register-log format (read_reglog / write_reglog) and frame_writes, the shared per-frame SID-write framing loop.
  • oracle — per-frame SID register grids: register_grid (py65), the stdlib grid_from_writes framer, read_sidwr (preframr-sidtrace .sidwr.bin), and aligned_match.
  • testing — HVSC tune fetch/resolve for test suites (fetch_tune, resolve_tune, make_tune_fixtures).
  • audiorender_samples / render_wav through an emulated SID (pyresidfp, audio extra), plus resolve_device / seconds_to_frames.
  • Writers — SidHeader.to_bytes / write_psid / SidImage.to_prg (the inverse of the parsers), parse_prg, and encode_cstr / decode_cstr.
  • SidImage absolute-address accessors — byte_at / word_at / contains / poke, relocation-safe and bounds-checked.
  • mos6502 — shared 6502 primitives: OP_LEN, opcode-class sets, s8 / adc / sbc, SidWriteCapturingMemory, walk_until.
  • MemPlayer — per-frame register-diff player scaffold; subclasses implement _init / _frame. register_writes_from_player drives it to a reglog.
  • notefreqNoteFreqTable, computed PAL/NTSC pitch tables, and locate_note_freq (find hi/lo tables from paired absolute-indexed reads).
  • make_package_errors — per-package error hierarchy factory whose *ParseError / *FormatError subclass the base ones, so base except clauses catch them.
  • cli — shared argparse scaffold: run_cli, add_reglog_command, add_wav_command, print_info.
  • registers additions — SID_VOICES, voice/global register indices, and the attack_decay / sustain_release ADSR nibble packers.
  • resolve_entry_points / is_jmp_vector, cadence_from_latch, and the ByteCursor / check / byte_range parse helpers.

Install

pip install pysidtracker          # core (includes py65 for init emulation)
pip install pysidtracker[fast]    # + numpy, to accelerate the image scan
pip install pysidtracker[audio]   # + pyresidfp, for WAV/sample rendering

py65 and pydexomizer are required core dependencies (detection runs a tune's 6502 init, and native_decrunch unpacks exomizer-packed images natively). numpy is optional; a pure-stdlib scan is used when it is absent.

Usage

from pysidtracker import BaseSidParser, PlayroutineKind

class MyParser(BaseSidParser):
    def recognize(self, image):
        return image.find(b"MYSIG")            # truthy anchor when found
    def parse(self, data, **kw):
        image = self.load_image(data)          # .sid or .prg -> SidImage
        ...                                    # decode image.mem into a model

det = MyParser().detect("tune.sid")
if det.kind is PlayroutineKind.PACKED:
    ...                                        # header was not trustworthy

Development

pip install -e ".[dev]"
pytest --cov=pysidtracker

See docs/design.md for the detection model and shared primitives.

License

Apache 2.0 — 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

pysidtracker-0.5.0.tar.gz (74.5 kB view details)

Uploaded Source

Built Distribution

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

pysidtracker-0.5.0-py3-none-any.whl (61.4 kB view details)

Uploaded Python 3

File details

Details for the file pysidtracker-0.5.0.tar.gz.

File metadata

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

File hashes

Hashes for pysidtracker-0.5.0.tar.gz
Algorithm Hash digest
SHA256 fd2bc867cd131348457482e73d33c8401bc9b5fade1deac7b9adf2503473a3b3
MD5 fbccf214f6484d8e15e56eb0e075f0d3
BLAKE2b-256 cd4877ab48e0267d3343f0f11fc80a9d13a2309002a812484d0465b27fbe429a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysidtracker-0.5.0.tar.gz:

Publisher: publish.yml on anarkiwi/pysidtracker

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

File details

Details for the file pysidtracker-0.5.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for pysidtracker-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1e3b1d942ae7125ff609ac5a1eeea7033c23cb36bedcbc9aef73571de7d36653
MD5 7493291329d99ff5d6fc774ac12ab3ce
BLAKE2b-256 c59b8f375bef1fe179807511d5e9dc5009c528440d0725b93600f6fd8a6f4dee

See more details on using hashes here.

Provenance

The following attestation bundles were made for pysidtracker-0.5.0-py3-none-any.whl:

Publisher: publish.yml on anarkiwi/pysidtracker

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