Skip to content

Configurable floppy drive speed with turbo mode#229

Merged
LinuxJedi merged 3 commits into
mainfrom
feature/floppy-speed
Jul 19, 2026
Merged

Configurable floppy drive speed with turbo mode#229
LinuxJedi merged 3 commits into
mainfrom
feature/floppy-speed

Conversation

@LinuxJedi

@LinuxJedi LinuxJedi commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Adds the FS-UAE-style fast floppy option that keeps getting requested: [floppy] speed / --floppy-speed (alias --fdd-speed) accepting 100 (real speed, default), 200/400/800 percent, or 0 for turbo.

How it stays accurate

  • Percentage modes multiply the elapsed time the data path sees: platter rotation, the MFM read shifter, sync detection, DSKBYTR, and DMA pacing all advance at the whole multiple, so every per-cell decision is bit-identical to a real-speed run, just compressed in time. This is the same shape as FS-UAE/WinUAE's floppy_speed percentage (their 8.8 fixed-point trackspeed divisor), minus their FIFO slot-pacing hacks, which Copperline's rate-based transfer does not need.
  • Turbo mirrors FS-UAE's instant path but runs through the ordinary bit engine instead of a parallel copy loop: once a DMA has been armed for two scanlines (the deferral WinUAE applies so loaders that clear stale INTREQ bits right after writing DSKLEN do not lose the completion), the platter is spun forward in zero emulated time -- first to the next DSKSYNC match, then to the transfer's end. Framing, sync realignment, the write-decode path, and DSKBLK all behave exactly as if the time had really passed. A sync word the track never provides gets one scan and then falls back to normal pacing, like FS-UAE's per-DSKLEN turbo scan.
  • Mechanics are never accelerated: motor spin-up, head stepping, and post-seek settle keep real timing at every speed, so drive-readiness behavior (Gods' spin-up gate, Shadow of the Beast II's DSKLEN-during-spin-up arming) is untouched.
  • The idle fast-forward event horizon (next_completion_cck / next_sync_irq_cck / next_index_pulse_cck) reports the scaled deadlines, so STOP-state batching stays bounded to the accelerated events.
  • The speed is host configuration, not machine state: it is never serialized, adopt_host_resources carries the running session's setting across save-state loads, and the default (100) leaves every timing path byte-identical to before this change.

Hooked up everywhere

  • TOML/CLI: [floppy] speed, --floppy-speed/--fdd-speed, validated to the supported set with a clear error.
  • Desktop menu: a Floppy Speed item (next to Pixel Aspect) cycles 100% -> 200% -> 400% -> 800% -> turbo live, with an OSD flash.
  • Launcher: a Drive speed row on the Floppy tab, round-tripping through the generated TOML only when non-default.
  • Browser: set_floppy_speed(percent) / floppy_speed() on WebEmu, plus a visible speed select on the page itself: a shell-provided #floppy-speed element hosts it, and without one try.js builds a labelled 100%/200%/400%/800%/Turbo select below the canvas (the status strip pattern), so the control is always reachable. ?fdspeed=100..800|0|turbo overrides the initial choice for shareable links; changes apply at boot and live.
  • Docs: configuration.md (option + CLI table), ui.md (menu + launcher), browser.md (JS API + page hooks), and copperline.example.toml.

Testing

  • Seven new unit tests: 800% completes a read DMA exactly eightfold sooner with identical data, turbo bursts read and full-track write DMA after the two-scanline grace, a sync-waiting turbo read delivers the same words as a real-speed run, a missing sync word falls back to normal pacing, turbo waits for motor spin-up, and no speed shortens spin-up. Plus config parse/validation and CLI override tests.
  • cargo test (1665 unit + integration suites), cargo clippy --all-targets, and cargo fmt --check all clean; web crate checked with cargo check/clippy --target wasm32-unknown-unknown and fmt --check.
  • End-to-end headless verification with the Alien Breed trackloader under KS1.3: 13 disk DMA completions in the first 15 emulated seconds at 100%, 22 at 800%, 29 at turbo, all rendering the intro correctly; an AmigaDOS boot behaves identically at all speeds.

Users keep asking for FS-UAE-style fast floppy loading. Add
[floppy] speed / --floppy-speed with the same value set: 100 (real
speed, the default), 200/400/800 percent, and 0 for turbo.

The percentage modes multiply the elapsed time the data path sees --
platter rotation, the MFM read shifter, sync detection, DSKBYTR, and
DMA pacing all advance at the whole multiple -- so every per-cell
decision stays bit-identical to real speed, only compressed in time.
Turbo mirrors FS-UAE's instant path through the ordinary bit engine:
once a DMA has been armed for two scanlines (the same deferral WinUAE
applies, protecting loaders that clear stale INTREQ bits after writing
DSKLEN), the platter is spun forward in zero emulated time, first to
the next DSKSYNC match and then to the transfer's end. A sync word the
track never provides leaves the transfer to normal pacing, and the
event-horizon predictors report the scaled deadlines so idle
fast-forward stays bounded.

Mechanics are never accelerated: motor spin-up, head stepping, and
post-seek settle keep real timing, so drive-readiness state machines
(Gods, Shadow of the Beast II spin-up arming) behave identically. The
speed is host configuration, not machine state -- save states never
carry it, and a loaded state keeps the running session's setting.

The option is live everywhere: a Floppy Speed item in the runtime
menu, a Drive speed row on the launcher's Floppy tab, and in the
browser build a set_floppy_speed/floppy_speed WebEmu API with an
optional #floppy-speed select and ?fdspeed= link parameter.

Verified against the Alien Breed trackloader: 13 disk DMA completions
in the first 15 emulated seconds at 100 percent, 22 at 800, 29 at
turbo, all reaching the intro correctly.
Copilot AI review requested due to automatic review settings July 19, 2026 17:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a configurable “fast floppy” feature (including a turbo mode) to Copperline, wiring the new [floppy] speed / --floppy-speed setting through the core floppy controller and exposing it across the desktop UI/launcher and the web frontend, with accompanying documentation and tests.

Changes:

  • Introduces a floppy speed setting supporting 100/200/400/800% and turbo (0), with timing/prediction support for STOP-state fast-forward.
  • Adds desktop controls (menu + launcher) and web controls (JS API + optional page hooks + URL param) for changing floppy speed live.
  • Updates configuration/CLI parsing plus docs and example config, and adds unit tests covering key timing/behavior cases.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/video/window.rs Plumbs current floppy speed into menu label state and adds a runtime menu action to cycle speeds.
src/video/ui.rs Adds “Floppy Speed” menu item and label formatting; updates menu sizing and tests.
src/video/launcher.rs Adds launcher “Drive speed” control and persists non-default speed into generated TOML.
src/main.rs Adds --floppy-speed / --fdd-speed CLI parsing, help text, and tests for overrides/validation.
src/floppy.rs Implements speed/turbo behavior in the floppy controller, prediction scaling, and extensive unit tests.
src/config.rs Adds [floppy] speed to config model, raw TOML parsing/validation, and override plumbing + tests.
src/bus.rs Preserves host-configured floppy speed across save-state loads via adopt_host_resources.
docs/guide/ui.md Documents the new desktop menu/launcher UI for floppy speed.
docs/guide/configuration.md Documents [floppy] speed and --floppy-speed, including behavior and trade-offs.
docs/guide/browser.md Documents the new WebEmu API + optional #floppy-speed and ?fdspeed= hooks.
crates/copperline-web/www/try.js Implements the optional #floppy-speed select + ?fdspeed= parameter behavior.
crates/copperline-web/src/lib.rs Exposes set_floppy_speed() / floppy_speed() on WebEmu.
copperline.example.toml Adds commented example for [floppy] speed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/floppy.rs
Comment thread src/floppy.rs Outdated
Relying on the page shell to add a #floppy-speed element meant the
browser build had no visible way to change the drive speed until the
site was edited. Follow the status strip's pattern instead: when the
shell provides #floppy-speed the page owns placement and styling, and
without one try.js builds a labelled select (100%/200%/400%/800%/Turbo)
directly below the canvas shell, so the control is always reachable.
The select applies live and at boot, and ?fdspeed= still overrides its
initial choice for shareable links.
Two review findings on PR 229. Entering turbo through
set_speed_percent now arms the same two-scanline grace window and
fresh burst attempt as a DSKLEN arming, so flipping the menu to turbo
with a transfer in flight defers the burst like a new transfer instead
of completing on the next tick, and a spent attempt from an earlier
turbo phase cannot linger. And scale_prediction only reports a 1-cck
event horizon when the burst can actually run: with the grace elapsed
but the drive still spinning up (or settling, or the attempt spent),
predictions fall back to the normal-paced deadline, where previously a
STOP-parked CPU waiting on a DMA armed during spin-up would have been
idle-stepped one cck at a time for the whole quarter-second spin-up.
@LinuxJedi
LinuxJedi merged commit d519fd6 into main Jul 19, 2026
14 checks passed
@LinuxJedi
LinuxJedi deleted the feature/floppy-speed branch July 19, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants