Files
CDJ900NXS-Patcher/README.md
T

130 lines
7.0 KiB
Markdown

# CDJ-900NXS firmware patcher
Builds a new `C900NXS.UPD` from the official CDJ-900NXS firmware 1.31 with
the mods you choose, for the player's own USB update.
```sh
python cdj900nxs_patcher.py C900NXS.UPD # choose in a list
python cdj900nxs_patcher.py C900NXS.UPD --mods cuecolours,hotcuekeys
python cdj900nxs_patcher.py C900NXS.UPD --stock # the original, to go back
python cdj900nxs_patcher.py --list
```
In the list: **arrow keys** move, **space** ticks or unticks, **a** ticks all
or none, **enter** builds, **q** quits. Ticking a mod ticks what it needs;
unticking one unticks what needs it (`hotcuekeys` needs `cuecolours`,
`beatjump` needs `hotcuekeys`). A mod with known faults starts unticked.
Before anything is built the patcher shows a disclaimer that must be
accepted by typing `yes` (or with `--accept`, where no one can type): the
mods and the patcher were developed with Claude Code, Anthropic's AI coding
assistant, and are used at your own risk. Terminals that cannot pass single
keys (Git Bash's mintty, a pipe) get a numbered list instead. The result goes
to `out/<date>-<mods>/C900NXS.UPD` with a `report.txt` of every check.
## What it guarantees
- **Only the original file is accepted**: SHA-256
`e96bca7d1ac983985992a8e5fa7813e1ebf04bef514e0c6cfd0a8375f667f7f9`, and the
1.31 application inside it is checked too.
- **Only the main application is replaced.** The boot loader and recovery
loader (MAIN's records below flash 0x40000), MAIN's S0 header and S7 entry
records, and the DRIV and PANL sections are copied from the original byte
for byte. Before anything is written the finished file is read back and
checked: every section CRC and S-record checksum; DRIV and PANL equal to the
original; MAIN's header equal but for its version label, application-only
mode kept; every boot loader and recovery record and byte equal; no record
past 0x7E0000; the packed application's checksum; and the application,
unpacked the way the boot loader does it, equal to the patched one.
- **Labelled 1.32**, so that the player's updater does not skip the update as
the version it already has. The application still reports 1.31 (as
arnoldasr's builds do). `--stock` gives the original firmware with only that
label changed: three bytes differ from the official file (the digit and the
section CRC), exactly as arnoldasr's back-to-stock file, which installed on
his test player.
Checked in the emulator: both the `--stock` file and one with every mod were
written into an emulated flash and booted through Pioneer's own boot loader,
which unpacked and started them.
## Mods
From the emulator checkout `../CDJ900NXSVirtual` (`--repo` for another place):
`mods/patch_cdj900nxs.py` and the mods next to it.
| mod | what it does |
|---|---|
| `extended_bpm` | arnoldasr: BPM with two decimals (tenths as a small digit above) |
| `phasemeter` | arnoldasr: two-line phase meter, chosen in UTILITY > PHASE METER (was SLIP FLASHING) |
| `rgb_waveform` | arnoldasr: big waveform in RGB colours, overview as a red-to-white gradient |
| `beatjump` | TRACK SEARCH jumps 1/2/4/8 beats, UTILITY > BEAT JUMP (needs `hotcuekeys`), see below |
| `cuecolours` | memory cues in their rekordbox colours, hot cues shown |
| `hotcuekeys` | hot cues A-C on the BEAT DIVIDE keys (needs `cuecolours`), see below |
| `ledsaver` | UTILITY > LED ANIMATION: while the screen saver dims the display, the button LEDs and the jog's rings play a loop |
| `credit` | the boot screen says "Pionaarr Mods by Givou" where it said "Ver 1.31" (ticked at the start, can be unticked) |
`hotcuekeys`: UTILITY > HOT CUE KEYS ON; then QUANTIZE pressed briefly
switches the hot key mode (HOT KEYS box beside QUANTIZE), held it is
QUANTIZE. In the mode the BEAT DIVIDE keys 3/4, 1/3, 1/2 are hot cues A-C
(1/4 and 1/8 do nothing and stay dark: the player has three hot cue buffers,
one for each):
- press: jump to the hot cue and play (from pause too);
- hold 0.5 s or longer, then let go: back to the hot cue, standing (gate);
- an empty key held 0.8 s while paused: a hot cue there;
- DELETE held, a key pressed: its hot cue deleted (DELETE alone is DELETE);
- LEDs: off without a hot cue, dim with one, two bright blinks when pressed.
Hot cues set or deleted are written to the USB stick (the track's rekordbox
analysis files, as MEMORY and DELETE keep memory cues), so they are there
after the next load too. As with MEMORY, the player takes this only once the
track has settled (a few seconds after loading). Hot cues A-C start at once: once a track is loaded and the
deck stands at its CUE point for a second (in hot key mode), they are loaded
into the player's three hot cue buffers, silently, and the deck goes back to
its CUE point. PLAY or CUE pressed meanwhile wait for it (PLAY is played
after). A hot cue set later loads into
its own buffer on its first press (about a second). A hot cue played from a buffer
leaves the CUE point where it is; one recalled without a buffer moves it, as
CALL does.
`ledsaver`: UTILITY > LED ANIMATION, ON from the first start (set it to OFF
to switch it off; the player keeps the choice). When the
player's own screen saver dims the display (5 minutes without a track, or
100 minutes paused), the BEAT DIVIDE keys fade in a wave down and back up,
SYNC / MASTER and MASTER TEMPO / DISC EJECT fade in and out, CUE, PLAY, REV,
SLIP, the SLIP LOOP bar and RELOOP/EXIT light one after another, and the
jog's three rings light in turn from the inside out and back in. Any key ends
it, as it ends the screen saver.
`beatjump`: UTILITY > BEAT JUMP (where SCREEN SAVER was) sets 1, 2, 4 or 8
beats (OFF: TRACK SEARCH as before); TRACK SEARCH back and forward then jump
that many beats along the track's beat grid, keeping the position within the
beat. While playing, the jump is loaded into a buffer of the player's own
that only beat jumps use (A-C keep theirs): there is a short silence while it loads, but the
deck comes back in phase, as if it had played on through it (the load time is
measured on every jump and allowed for), and the CUE point stays. Paused, it
is a CALL (the CUE point moves with it). A press while a jump or hot cue is
still loading is ignored.
arnoldasr's mods need his repository checked out in
`../CDJ900NXSVirtual/mods/cdj900nxs/upstream` (it has no licence, so it is
not copied here); without it they are greyed out.
## Risk
Nothing here talks to a player; you copy the file to a FAT32 USB stick and run
the update yourself. Our mods were developed with Claude Code in an emulator.
An earlier `beatjump` jumped off the grid on a player and, after a few quick
jumps, reported a corrupted file and needed a restart; it has been rebuilt on
the hot cue engine (no overlapping loads), which has not run on a player yet,
nor has the hot cue engine. A jump while a loop plays ends the loop. `cuecolours` and earlier versions of `hotcuekeys`
ran on a player. Recovery from an
application that crashes at start-up has not been tested by anyone. Keep the
`--stock` file at hand.
## Tests
```sh
CDJ900NXS_UPD=/path/to/C900NXS.UPD python -m pytest test_patcher.py
```