Scope, legal position, and the documentation and tests behind it - #26
Merged
Merged
Conversation
Tratosca
force-pushed
the
chore/scope-legal-and-docs
branch
from
August 22, 2026 20:17
1c240cb to
a434817
Compare
Tratosca
force-pushed
the
chore/scope-legal-and-docs
branch
2 times, most recently
from
August 22, 2026 21:07
1e9ac8e to
5d218fc
Compare
At -O2 clang rewrites `memcmp(a, b, n) == 0` into a call to bcmp, which rbp's libc does not export. The hook then fails to load: no link error, no warning, because the rewrite happens in the optimiser, after every diagnostic the front end could have produced. The symptom looked nothing like the cause. The emulator painted 17 730 non-black pixels -- exactly the stock figure -- which reads as a startup failure rather than a mod that never loaded. -fno-builtin-memcmp suppresses the rewrite. tests/test_hook_symbols.py reads the .dynsym of both builds with its own small ELF parser, so no external tool is needed, and fails on bcmp, on any import outside the set rbp is known to export, and on the flag being dropped from the Makefile. Second time an unresolved symbol has cost this project a long debugging round. First time a test will catch it.
NS_FONT_ID_ISO8859_w.bin has no header and no offset table. It is a flat array of 189-byte cells: 14x27 pixels at 4 bpp, high nibble first, coverage 0..15. 422 glyphs indexed by `codepoint - 0x20`, covering ASCII, Latin-1, Greek, Cyrillic and the euro sign. The file is 42 bytes short of 422 full cells because the last glyph's all-zero descender rows are not written. The cell height was what earlier attempts missed: 210 leading zero bytes look like a 30-row cell, but they are a 27-row space glyph followed by the first three blank rows of `!`. The typeface is Helvetica Neue LT W1G, named rather than guessed. rekordbox 7 declares font-family="HelveticaNeueLTW1G" in three of its own skin SVGs, and W1G -- Linotype's Latin/Greek/Cyrillic glyph set -- is exactly the repertoire of the firmware's font file. It is licensed and not shipped: scanning all 2144 files in the rekordbox bundle for genuine sfnt table directories finds four, all Chromium's SpiderSymbol icon font. The generator moves to Regular 22 from Light 24, fitted per glyph against nineteen of Pioneer's own capitals segmented out of the BEAT FX captions in imagedata.dat -- 29.3 mean absolute error against 61.3. The earlier fit matched whole-word ink extents, a weaker signal because weight and size trade against each other and still fit a box. The .bin is a condensed cut and is NOT the caption face: 39x19 on FILTER against the artwork's 76x16. It is what rbp draws live for browse lists, while the captions beside the KEY/STEMS controls are pre-rendered artwork. The 87 generated labels are committed because regenerating them needs Helvetica Neue, which is macOS-only; the artwork is ours, not Pioneer's.
UiObjectManager::init() completes and startUp() runs. The blocker every other
limitation hung from was one wrong byte in the shim: common::GpioManager reads
/dev/gpiodrv, and GPIOs 0x7e and 0xcc are the USB over-current inputs, which
are active-low. Our fake node read 0 -- a permanent fault raised during
construction, from which init() never returned. Filling it with 1 is the whole
fix, and it matches what a running RX3 reports over telnet.
rbp now opens 13 devices instead of 8, including both subucom micros and the
touch panel: opens #62-64 of the reference trace captured on hardware.
The window is watchable. With Pillow the framebuffer is unpacked in C and
handed to Tk in memory, 3.5 ms a frame against 220 ms; the stdlib path stays
as the fallback so a clean clone gains no dependency. A measured correction
table keeps the two identical across all 65 536 RGB565 words.
A front panel underneath: the physical keys above the screen, the pad-mode
selectors and the eight pads per deck, injected through rbp's own dispatch
rather than a synthesised device. --duration 0 leaves a session open.
Browse keys now finish the way rbp does. BrowseUiIf::InputKey marks the record
with UiKey_KeyPush and posts an eventflag with set_flg; Ui_EventTask consumes
it and runs BrowseKeyProcessing inside the rest of the transaction, including
the KeyComplete/repaint that the mod's direct call was skipping. The hook posts
the flag, falls back to the pump when the flag id looks uncreated, and
--pump {0,1} forces either route. Whether this moves the screen is not yet
demonstrated; CHANGELOG records exactly what was and was not measured.
Also: 146 key codes and the LED table extracted statically to
docs/rx3-key-codes.md, and the emulator-only rbp patch lives outside
tools/rx3_patcher/ so it cannot reach a device by construction.
… codec The toolkit authors one thing: the autoexec.bin image the player's own maintenance path already looks for. Reading and writing the manufacturer's update container was never on that path -- tools/rx3_runtime/build.py has only ever used load_key, crypt, read_autoexec, write_autoexec and the ISO metadata helpers -- so it goes. Removed: build, split, cmd_encrypt, cmd_decrypt, cmd_verify, their argparse subcommands, the MODEL and TRAILER constants, and the container description in the module docstring. zlib went with them; struct and subprocess stay, both still used by the ISO authoring path. test_firmware_image.py asserts the symbols are gone rather than assuming it, because a future change would most plausibly reintroduce them by copying an older revision back in.
The emulator moves to its own repository. What stays here is the format it consumes and nothing else: `make payload` assembles a directory holding a manifest.toml, the preloaded hook under lib/, and the assets, which is all the toolkit needs to know about how anything runs it. Removed: tools/rx3_emulator/, tools/rx3_system_emulator/, docs/emulator.md, their two test modules, and the emulator-image, emulator-hook, emulate, emulate-system, emulate-system-fast and emulate-system-window targets. No import, no path and no target reaches for either package now. The second hook build keeps its flags and loses its name: librx3_core_emulator becomes librx3_core_payload, since what makes it a variant is the payload it ships in, not who runs it.
The eight scattered documents become one REFERENCES.md, minus the emulation sections, which leave with the code. Every pointer into the old files is retargeted -- the hook's key-code comment, the font note in build_labels.py, both README tables. Three passages said something other than what the work does: - "Cloning, not styling" is now "Reusing the host's typeface at run time", which is the operation: a control wears the face of the model it is drawn from, resolved on the device, at run time. The body is unchanged. - The README's setup step is "Building a root filesystem", because that is the task in front of the reader: building one from the GPL sources Pioneer publishes for this player. It no longer names the file that build leaves. - extract-initramfs.md keeps its body -- it describes running a build script the GPLv2 obliges the manufacturer to provide -- and takes a title matching it. CONTRIBUTING's file table no longer describes a container format nothing in the tree can read. tests/test_docs_hygiene.py fails the build if that description comes back: prose outlives code, and a specification for a format whose codec was deleted is still a specification. The autoexec format stays documented, and a test asserts that too, since it is what the toolkit builds.
… from emulate_image_info_hook.py resolved its input from a hardcoded path whose every component asserted a provenance -- an extraction, of a firmware, of a version. A path is a place on a disk. It is not a provenance record, and it should not read as one. tools/rx3_artifacts.py resolves a role instead: the role's environment variable, then the [artifacts] table of a gitignored artifacts.toml, then local/artifacts/<profile>/<role>. The module has nowhere to write an origin and does not ask for one. A missing file names the role, says what that file has to be, and points at docs/artifacts.md. It does not say where to obtain one -- that is outside what this project does, and a test pins the role vocabulary against the words that would put it back.
Interoperability and study of a device its owner has bought, under directive 2009/24 art. 5(3) and 6 and art. L.122-6-1 CPI; no key, image, manufacturer binary or licensed typeface distributed, here or in the history; the mechanism used is the manufacturer's own maintenance path, which guards a service route rather than a work, and so falls outside L.331-5 CPI; the modification is made in RAM on the owner's device and is undone by removing the medium. Also a contact address and an undertaking to look at any complaint on its merits, whether or not it arrives as a formal notice.
… out The root-password paragraph now carries the date of the finding, 10 August 2026, and says what has been done with it: not reported to the manufacturer, no report planned. Left to inference it reads as an omission; written down it is just the state of things. The hash and the plaintext stay unpublished. The Unreleased section held roughly 290 lines of emulator engineering notes for a tool that is no longer in this repository. They never appeared in a tagged release, so nothing published points at them, and they leave with the code -- the extracted text goes to rx3-emulator's changelog. Two entries were split instead of moved, because the hook they also describe stays here: the performance-row geometry test, and the browse-key eventflag route. What remains is toolkit work, with the three pointers into deleted documents retargeted at REFERENCES.md, plus entries for this cleanup: the codec removal, role-addressed artifacts, and the emulator's departure. The known-issue about the palette now says plainly what the prepared tab bitmaps are still doing in the tree and what would retire them.
…ange it The published source package ships the built initramfs.tar.gz beside the sources it came from, so obtaining the filesystem is archive handling that macOS, Linux and Windows all do natively. make_rootfs, and with it WSL2, moves to its own section and is presented for what it is: the path for changing what goes into the filesystem, or for a source tree that does not carry the archive. The document still stops at an unpacked filesystem. It does not identify what inside it the app is later pointed at, and it states that an archive built by the manufacturer stays on the machine that unpacked it — unpacking it for a device you own is not the act of passing it on. Reported in #23.
Tratosca
force-pushed
the
chore/scope-legal-and-docs
branch
from
August 22, 2026 21:09
5d218fc to
6f25c23
Compare
Tratosca
marked this pull request as ready for review
August 22, 2026 21:25
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.
Summary
Cuts the tree back to what the project actually does, states the legal position in one place, fixes a build problem that could stop the mod working entirely, reworks the root filesystem documentation after #23, and puts the documentation and the tests in order behind it.
Changes
The mod could load and do nothing at all. The compiler was quietly swapping in an instruction the player does not have, so the file on your stick was ignored and the deck behaved exactly as it always had: no error, nothing on screen, nothing to go on. Fixed, and a test now fails the build if it comes back (
-fno-builtin-memcmp,tests/test_hook_symbols.py).Preparing the material no longer needs Linux. Pioneer's published archive already contains the filesystem the app needs, so getting it is unzipping and unpacking, the same steps on Windows, macOS and Linux. WSL2 is now only for someone who wants to rebuild that filesystem rather than read it. Refs Key extraction: make_rootfs is not required to obtain initramfs.tar.gz #23.
The key no longer has to be retyped.
RX3_KEYis read where the key is needed:make autoexectakes it whenKEY=is absent, and the application opens with that path already filled in. Nothing writes the location down.The on-screen lettering is closer to the deck's own. The face the player uses is now identified rather than guessed, from rekordbox's own files, and the labels are refitted against Pioneer's own captions. That face is licensed and is not shipped here, so what the mod draws is the nearest cut available on the machine that builds the stick. How close it looks on a deck is not verified yet.
The mod no longer reaches past the on-screen pad overlay. This is the row on the display that mirrors the eight rubber pads, not the pads themselves. The mod was picking its targets from the deck's window, which a deck shares with its info strip, so AUTO CUE, QUANTIZE and the tempo badges were being intercepted along with it. It now keys on the part of the display that owns that row, and paints it once per pass rather than once per drawing call.
The
PATCHEDbadge is gone. TheKEYandSTEMStabs already tell you the mod is running, so the header is Pioneer's again.What a maintainer sees
The emulator and the scripts that model the player leave. About 1650 lines that no production path imported: the pitch and UI harnesses, the shifter measurement, the image-table model, the Ghidra scripts, and the resolver that fed them. They are kept with the emulator, which is not published.
make payloadreplaces the emulator with a one-way payload directory that nothing here imports back.A quarter of the hook never ran on a deck. The three largest emulator-only blocks move into their own headers, included at the point they used to sit and only under
RX3_EMULATOR_BUILD.rx3_core_hook.cdrops from 2981 lines to 2310. The two teardown paths, which each carried their own copy of the same twenty calls, become one function. Both libraries hash the same before and after every one of these changes, so nothing on a deck can tell the difference.The test suite goes from 143 tests to 64, from 3807 lines to 2424, and from fifteen seconds to six. What stays fails when a deck would misbehave, when a stick or a track would be damaged, when the mod would load and silently do nothing, or when a commitment in LEGAL.md would break. What went was coverage: an estimator for a progress bar, a matrix of accelerator profiles restating a table the code reads, window theming, and interface closures replaying a dependency resolution pinned elsewhere.
Five documents and the app README fold into
REFERENCES.md, which also gains the 146-entryui::KeyInput::KeyCodetable and Pioneer's bitmap font format. Every document carries its licence line, paragraphs are one line each, prose is keyboard characters only, and diagrams are mermaid.Legal
LEGAL.mdsets out what the project is for, what is not distributed, and on what basis. The update-container codec is removed from the code and from the prose, with one test asserting the symbols stay gone and another failing the build if the format is described again.tests/test_names.pyfails the build on any tracked path or Python name that asserts where a file came from.On #23, the last step of the report locates the decryption key inside the unpacked filesystem. That step is not included: LEGAL.md commits this project to not pointing anyone at material of that kind. The document stops at an unpacked filesystem, and states that a manufacturer-built archive stays on the machine that unpacked it.
Testing
make test(64 tests) andmake preflight(202 files) pass.Two things are not verified. Whether
initramfs.tar.gzis present in a copy of the source package, and where: that section is written as a search whose outcome decides which of the two paths the reader takes. And the teardown factorisation changes the generated code, so the acceptance sequence in CONTRIBUTING.md applies to it before this ships. Every other change to the hook produces byte-identical libraries.