# v2 examples Three interactive demos for the v2 ISA, input RAM and SID-style sound, plus two audio-only ports of Martin Galway's Wizball music (separately GPL-3.0). All load at the default origin `0x1000`, keep variables in the ordinary parts of zero page (`0x10..0x1f`, `0x30..0x3f`, `0x60..0x7f`), and pace themselves with `sleep` instead of busy loops. One host tick = 1,000,000 cycles = 400 samples. Input bits (RAM `0x20`): left 1, right 2, up 4, down 8, A 16, B 32. Pointer x/y at `0x22`/`0x24` (0..255), flags at `0x26` (bit 0 down, bit 1 valid). | Example | Bytes (code + data) | Source instructions | Executed/s | | --- | ---: | ---: | ---: | | gravity-well | 612 (596 + 16) | 203 | ~6.9 M (1,024 particles at ~55 fps) | | elastic-ribbon | 674 (610 + 64) | 212 | ~0.7 M (~60 fps) | | sid-arpeggiator | 1,029 (883 + 146) | 302 | ~0.27 M (1,920 ticks/s) | | wizball-end-of-level | 947 (code + score/tables) | — | low (50 Hz ticks), then HALT | | wizball-title | 3,572 (code + score/tables) | — | low (~200.5 Hz calls), loops forever | Link straight to an example with `?example=`, e.g. [`?example=wizball-title`](./?example=wizball-title). It only preselects a listed example; you still press **Run** to start it and its sound. Unknown names fall back to the first example. ## gravity-well: particles 1,024 particles in 8.8 fixed point; the high byte of each coordinate is the pixel, so 16-bit wraparound gives a torus for free. - **Touch / drag:** a spring well pulls every particle toward the finger (spring constants vary per particle, so the cloud swirls instead of collapsing). - **A (hold):** repel from the pointer, or from the center if nothing is touched. - **Arrows:** tilt gravity. Left/right is wind, up is antigravity, down is heavy. - **B (press):** switch between box walls and the wrap-around torus. - Color shows speed. Each frame erases, moves, then draws all particles. ## elastic-ribbon: springs and drawing A chain of 32 spring nodes chases a cursor and paints a rainbow ribbon that dissolves into black: each frame, a full-period LCG blacks out random pixels. - **Touch / drag:** the head chases the finger. Differences are signed 16-bit values, so the ribbon takes the shortest path across screen edges. - **Arrows:** steer the cursor (3 px per frame). - **A (press):** 4-way kaleidoscope. Mirroring is just `xor 0xffff` per axis. - **B (press):** trail length long / medium / short, plus a hue shift. - With no input, the cursor follows an autopilot Lissajous path. - Every pixel address is `(y & 0xff00) | (x >> 8)`, so all writes stay on screen. ## sid-arpeggiator: music An original four-bar riff in A minor (Am, F, Dm, E), written for this demo and not imitating any existing tune. The guest code is the whole player: it sleeps ~62,000 cycles per tick (~1,920 ticks/s) and writes registers each tick. - Voice 1 is a pulse arpeggio over the chord at 60 notes/s, with a pulse-width sweep. - Voice 2 is a sawtooth bass through a resonant low-pass. Each note kicks a decaying "wah". - Voice 3 is the lead melody. Vibrato starts 100 ms in. Its pulse sweep runs opposite to voice 1. - **Touch:** x sets the key (12 semitones across the screen); y sets the cutoff (top is bright). - **Left / right:** transpose a semitone. **Up / down (hold):** sweep the filter. - **A:** lead tone: pulse / saw / triangle + sine (`0x5b` mask) / saw + pulse. - **B:** tempo: normal / fast / slow. - **Screen:** a piano roll sweeps one column per 16 ticks. Height is pitch. Cyan is the arpeggio, orange the bass, yellow the lead, magenta the filter cutoff. The background tint follows the chord, with brighter beats. Notes are pitch numbers (C0 = 0). `pitch2freq` divides by 12 with repeated subtraction, then shifts the octave-6 table (`round(Hz·2²⁴/985248)`) right. ## ISA friction after the v2 improvements - **Fixed:** `shl/shr/sar/mul` make 8.8 physics, an LCG (`mul r0,25173; add r0,13849`) and frequency scaling short, and variable shift counts help a lot (`256 << 2*TRAIL`, `freq >> (6-octave)`). `neg` replaces `xor -1; inc`. `.equ` turns magic addresses into names. `sleep` makes pacing one instruction and keeps idle CPU near zero. - **Branches:** loops longer than ±127 bytes need explicit `.w`. Without relaxation, you add `.w` after the assembler rejects the short form. That is fine, but slightly tedious. - **Calls:** there is no CALL/RET. The manual form `mov r5, ret; jmp sub` and `mov pc, r5` works (6 + 2 bytes) but uses up a register. - **Zero page:** `[sp+disp8]` reaches only `0x00..0x7f`, and `0x00..0x0f` are registers. A variable at `0x02` silently aliased r1. Use `0x10` and up. - **Expressions:** `.equ` cannot express `KMEM-AX` (symbol minus symbol), so some struct offsets are hand-written numbers. - **Missing pieces:** there is no division or high multiply word. Fixed-point scaling pre-shifts (`(f>>8)*lfo sar 6`) to stay within 16 bits. - **Stores:** there is no store-immediate, so `stb [sp+X], sp` stores zero when `sp = 0`. - **Input timing:** input refreshes once per host tick (~8 ms) and is read once per frame. A press shorter than one frame (~16 ms) can be missed, so this profile does not guarantee delivery of every brief tap. An edge-event latch would be a separate device-design improvement. ## wizball-end-of-level: Martin Galway's jingle (GPL-3.0) A native port of the Wizball "End Of Level" jingle (tune D) by **Martin Galway**, (C) Ocean Software Ltd 1987, from his GPL-3.0 source release (commit `a458a36`, `wizball.asm`). It is the short level-complete jingle; the title music is `wizball-title` below. - **Audio only:** about 2 seconds audible; the screen stays black and input is ignored. Keep **Sound** checked and press **Run**. The program HALTs when the tune ends (about 4.6 s, including the driver's silent tail). - The 6510 driver routines (INITSOUND, TUNE, MUSICn, SOUNDn) were translated by hand into v2 assembly; the score, instrument and PAL frequency table are the original data. SID `$D400+n` is sound RAM `0x40+n`. Each 50.12 Hz PAL tick sleeps ~2.39 M cycles. Unsupported driver commands stop with RAM `0x62` ≠ 0. - Register writes per tick follow a 6510 trace of the original player in order, but are not cycle-exact; the synth is SID-inspired, not a 6581. - **License:** this one file is GPL-3.0, separately from the rest of fanco16. [Source](examples/wizball-end-of-level.asm) · [license text](licenses/wizball/LICENSE) · [attribution and modifications](licenses/wizball/README.md). ## wizball-title: Martin Galway's title music (GPL-3.0) The complete Wizball title music by **Martin Galway**, (C) Ocean Software Ltd 1987, from the same GPL-3.0 source release (commit `a458a36`, `wizball.asm`). It is the full three-voice score, not an excerpt, and it is not a recording. A 3,572-byte native port of the parts of Galway's driver the tune uses plays the original score data. - **Audio only, no controls:** the screen stays black and input is ignored. Keep **Sound** checked and press **Run**; press **Stop** to end it. One pass lasts about 3 min 35 s (43,085 driver calls), then the tune restarts and loops indefinitely. It never HALTs unless the driver meets an unsupported feature (RAM `0x62` ≠ 0). - What you hear: pulse-width sweeps, vibrato and pitch bends, software envelopes and the driver's filter channel sweeping its cutoff. That filter sweep is audible because v2's synth filter was revised for this port: combined low/band/high-pass modes now keep a resonant response instead of cancelling to the dry signal (see [SOUND.md](SOUND.md)). - The original runs from a 200.498 Hz CIA timer (not frame interrupts); the port calls the driver natively at about 200.5 Hz in the HVSC wrapper order. The first pass measures 214.888 s. Register values and their order in each call matched a 6510 trace of the original player over two full passages and the restart. Pacing is a calibrated `sleep` loop, so writes are bunched within each call and timing is approximate (milliseconds), not cycle- or sub-tick-exact. - The synth is SID-inspired, not a 6581: waveforms, envelopes and especially the analog filter sound different from a real C64. - **License:** this one file is GPL-3.0, separately from the rest of fanco16. [Source](examples/wizball-title.asm) · [license text](licenses/wizball/LICENSE) · [attribution and modifications](licenses/wizball/README.md).