130 lines
7.0 KiB
Markdown
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 1.0" 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
|
|
```
|