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.

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

CDJ900NXS_UPD=/path/to/C900NXS.UPD python -m pytest test_patcher.py
S
Description
No description provided
Readme
124 KiB
0 Stars 1 Watchers 0 Forks
Languages
Python 100%