Repository navigation
Conversation
This was referenced Aug 31, 2026
eynsai
force-pushed
the
virus-ctrldump-pageb-channel
branch
from
September 5, 2026 00:53
cec5d03 to
341b7a7
Compare
eynsai
force-pushed
the
virus-ctrldump-pageb-channel
branch
from
September 13, 2026 02:07
341b7a7 to
43060a7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
REQUEST_CONTROLLER_DUMP(0x37) asks the device to report a part's edit buffer as a burst of individual controller messages rather than as a sysex dump.buildControllerDumpResponse(virusLib/microcontroller.cpp) builds that reply: page A goes out as control change, page B as poly pressure.Page A carries the part number in the status byte's low nibble. Page B does not — it always goes out on nibble 0, whichever part was requested.
The inconsistency
Three places in
microcontroller.cppdecide how a part is addressed in page A/B controller traffic. Two of them agree with each other and the third does not:sendMIDIsingleMode ? SINGLE : channelM_CONTROLCHANGE + channelM_POLYPRESSUREThe device's own receive path treats the page B nibble as a part index. The dump builder honours that convention on the line for page A and drops it on the line directly below. Nothing in the file explains the asymmetry, and no in-plugin consumer appears to depend on it.
The change
channelis the same local the page A line already uses: the requested part, or 0 for theSINGLEslot.Effect
A controller dump requested for part N now delivers both halves of that part's edit buffer to part N. Before this, page A landed on part N and page B landed on part 0, so a dump for any part other than 0 silently wrote half its payload into the wrong part's parameters.
Requesting a dump for part 0, or for the
SINGLEslot in single mode, is unaffected — those already resolve to nibble 0.Testing
Verified in-situ on live Osirus and OsTIrus instances, against builds with and without this change.
The method relies on a raw sysex reaching the device without refreshing the plugin's parameter cache. A
PAGE_Bparameter-change message moves a value on the device only, leaving the cache deliberately stale; the controller dump is then the only thing that can resynchronise it, so watching which part catches up reads the addressing decision directly. All parts are seeded with known values first, so a mis-route shows up as the wrong part moving rather than as an ambiguous no-op, and each test asserts the cache did not move before the dump was requested.PAGE_Bwrite to part 3, dump part 3PAGE_Bwrite to part 0, dump part 0The second row is the control: part 0 was already the correct destination there, so a change would have indicated the fix overshot. The page A phases of the same battery are byte-identical with and without this change, confirming it does not disturb the half that was already correct.
Interaction between three related PRs
I have submitted three PRs affecting Osirus/Ostirus MIDI channel handling, and they are easiest to reason about together:
The table below considers the effects of various combinations of these three PRs on MIDI handling.
Two behaviours are correct in every combination and are left out of the table below: the single-mode controller dump, and the page A half of a multi-mode dump.
Row 1 is current behavior, and no row regresses against it, so any subset may be merged in any order. Row 2 is the only one that can look like a regression, since #291 alone drops a control change that is delivered today, but today it is delivered to the wrong part, so neither matches the device.
#290 is independent: it flips Behavior 4 identically in every row. #285 independently fixes Behavior 1. For Behaviors 2 and 3, however, #285 and #291 are complementary rather than independent, and neither alone produces the correct result.
AI Disclosure: This PR was made with the help of an AI coding assistant.