Recovered 2026-08-17 from artifacts/walkmanone/WalkmanOne.UPG (v3.5, 2021-09-22, "for A50Series")
vs artifacts/unpacked/stock. Both system images extracted with debugfs -R rdump (no root, no
mount) and diffed file-by-file.
Bottom line: almost all of it is extractable. The headline "sound signature" is a THREE-BYTE patch to a userspace shared library. The device already ships every binary needed to apply it.
A model swap, not a region unlock:
| property | stock | Walkman One |
|---|---|---|
ro.product.device / .board |
BBDMP5_linux |
BBDMP2_linux |
ro.sony.version |
1.02 | 3.02 |
ro.sony.swid |
03.01.E.1.02.00 |
01.20.E.1.02.00 |
BBDMP5 is the A50 series; BBDMP2 is a higher Hagoromo model. The destination letter stays
E in both — so nothing about the EU region is changed at the property level. The gain comes
from the device presenting as a different model, which makes the boot-time audio setup load that
model's tables.
Its installer (0.bin of the UPG) writes 8 partitions raw:
index_2 → mmcblk0p8 (16M) index_6 → p14 AND p15 (5M, written twice = tee1/tee2)
index_3 → mmcblk0p9 (16M) index_7 → p19 (838M) ← android/system
index_4 → mmcblk0p10 (6M) index_8 → p21 (512K)
index_5 → mmcblk0p12 (3M) index_9 → p25 (8M)
System is 528 MB vs stock's 210 MB — it carries a lot of extra payload (see "Tuning packages").
The gate is one line, identical in stock and W1:
PRODDEV=`getprop ro.product.device`
shp=`nvpflag -x shp`; shpfirst=`echo $shp | cut -c1-10`
/system/bin/dacdat auto $PRODDEV $midupper $shpfirst
...
dacdat limiter_500 $shpfirst
dacdat limiter_750 $shpfirst
dacdat limiter_31 $shpfirst$PRODDEVselects which volume-table set is loaded.$shpfirstis the destination code held in NVP, not in build.prop. Values seen in the same script's FM-tuner branch:0x00000001=UC,0x00000306=LA, else J/EE/CEW/CN/E.- The volume limiter is an argument derived from that region code — it is not compiled in.
/system/bin/dacdat is byte-identical between stock and W1 (d3d20f167d8f53d8b643897818a6d38c,
19508 bytes) and is present on the device. The tool that programs the DAC therefore already has
every capability W1 uses.
W1 also swaps the table files in /system/usr/share/audio_dac/:
| file | size | stock | W1 |
|---|---|---|---|
ov_1291.tbl, ov_dsd_1291.tbl, tc_1291.tbl (+_cew) |
84950 / 13076 / 2888 | ✓ | ✗ |
ov_127x.tbl, ov_1280.tbl (+_cew) |
84950 | ✗ | ✓ |
ov_dsd_127x.tbl, ov_dsd_1280.tbl (+_cew) |
13076 | ✗ | ✓ |
tc_127x.tbl, tc_1280.tbl |
2888 | ✗ | ✓ |
ncgain_*.tbl, ambgain*.tbl, ambient480_* |
70 | ✓ | ✗ |
ov = output volume, tc = tone control, _cew = the Europe variant. The trailing number is the
DAC variant: the A50 is 1291, the ZX300 is 1280/127x. W1 drops the A50's noise-cancelling and
ambient tables (the ZX300 has no NC headphone support) and its 1291 tables, and ships 1280/127x in
their place. It also stops insmod-ing cxd3778gf_dnc_core.ko — the only CXD module that differs
between the two images.
CORRECTED 2026-08-17. An earlier pass here claimed stock had NO
ov_*/tc_*tables and that W1 introduced the concept. That was wrong — it came from a directory listing truncated before theov_*entries. Stock shipsov_1291,ov_dsd_1291andtc_1291and loads them at every boot. The mechanism is not new; only the tables differ.This RESOLVES what was flagged as the open question. The stock kernel demonstrably accepts an
ov_*.tblupload, because stock does exactly that on every boot. No kernel change is needed.
/etc/.mod/adler/{normal,normal_nt,pv1,pv2}/libaudiohal-adleralsa.so, all 155068 bytes:
normal c8de2a65cf4f ← BYTE-IDENTICAL to stock's live /vendor/sony/lib/libaudiohal-adleralsa.so
normal_nt c8de2a65cf4f ← same again
pv1 6baf1bf0dcf6 ← 3 bytes differ from normal
pv2 32c9f4359dd1 ← 3 bytes differ from normal
W1's own live HAL is also c8de2a65cf4f, i.e. it ships normal active and the mod swaps in
pv1/pv2 from a settings file at boot.
cmp -l against normal — the changed bytes are ASCII digits inside string literals, not code:
normal pv1 pv2
ALSA out devices hw:0,0 , hw:0,4 hw:0,0 , hw:0,0 hw:0,4 , hw:0,4
scaling_min_freq 1040000 1300000 1300000
So a "sound signature" is exactly two things:
- Which ALSA PCM device the output stream opens. There are two path strings;
pv1forces both tohw:0,0,pv2forces both tohw:0,4. - The CPU clock floor held during playback —
/sys/devices/system/cpu/cpu0/cpufreq/ scaling_min_freqwritten as 1300000 instead of 1040000. The standard "keep the core pinned so the audio thread never stalls" argument. It costs battery; seereference_power_measurement.
Verified present on the device (2026-08-17): card0 sonysoccard exposes PCM devices 0,1,2,3,4,5
— so both hw:0,0 and hw:0,4 exist on A50 hardware and pv1/pv2 are meaningful here.
W1 carries a second directory with the same four variant names as adler — anls/{normal, normal_nt,pv1,pv2} — which at first looks like the signature touching a second library. It is not.
Each holds 48 tiny text files, delay_{dacmode,normal}_{level,spectrum}_<rate>_<bits>.txt: the
analyser/visualiser delay compensation in samples.
Checked file by file:
-
pv2andnormal_ntare byte-identical tonormal. -
Only
pv1differs, and only in thedelay_normal_*set. The big moves are at CD rates:file normal pv1 delay_normal_level_44100_16735 60 delay_normal_level_48000_16730 60 delay_normal_level_88200_16500 420 delay_normal_level_*_32350–475 385
That is exactly what the 3-byte patch predicts. pv1 forces BOTH output path strings to hw:0,0,
where stock uses hw:0,0 and hw:0,4 — and hw:0,4 is the CXD3778GF low-power playback
device. Leaving the low-power path drops ~675 samples (~15 ms at 44.1 kHz) of output latency, so
the delay tables that keep the spectrum display aligned with the sound had to be re-measured.
So it changes when the bars move, not what you hear, and the "sound signature is three bytes"
finding stands. It is also independent evidence for what pv1 actually does: less buffering, lower
latency, which is the same reason it pins the CPU floor to 1.3 GHz.
W1 also carries /etc/.mod/gain/{gain_n,gain_l}/, four .tbl files each, unencrypted and exactly
the sizes stock uses. Cross-checked against wampy's own cross-model md5 map
(artifacts/repos/wampy/tunings/uniq.txt), which settles what they actually are:
| file | md5 | is byte-identical to |
|---|---|---|
gain_n/ov_127x.tbl |
bb5ccae7… |
NW-A50 ov_1291.tbl — your own stock curve |
gain_n/ov_dsd_127x.tbl |
05858758… |
NW-A50 ov_dsd_1291.tbl |
gain_l/ov_127x.tbl |
39a60adc… |
NW-WM1A ov_127x.tbl (= ZX300 ov_1288) |
gain_l/ov_dsd_127x.tbl |
142c8a33… |
NW-WM1A ov_dsd_127x.tbl |
So Walkman One's two "gain modes" are: normal = the A50's own volume curve, renamed to 127x so
it loads under the BBDMP2 model; "L" = the NW-WM1A's curve. That is the whole feature. Both
tables are plain files, both are extracted to artifacts/walkmanone/gain/, and dacdat ovt FILE
is the loader — the same interface already recovered in Layer 1. Reachable without flashing, with
the same headphones-off caution as any volume-table change.
Extracted from /etc/.mod/tunings/ (debugfs -R "rdump /etc/.mod/tunings …" 7.bin). Each is a
Windows installer wrapping a nested NW_WM_FW.UPG: Bright and Neutral/Warm are 196720 bytes,
WM1Z is 192624. SWUpdate.xml targets DMP-Z1 for Bright and NW-WM1Z for the other two
(an earlier note here said NW-WM1Z for all three — wrong).
They cannot be unpacked. In order:
- No known KAS decrypts them.
upgtool -ewas run against all 24 models Rockbox knows, includingnw-wm1zanddmp-z1(which share2b07114f…, the KAS the manifests point at). Every one returnsSignature Mismatch. The Windows updater binaries carry no 64-hex KAS string either — they are Sony's ownWmFwUpdater.dll, and the device does the validating. - The cipher is a stream/CTR, not ECB. All 24064 8-byte blocks of the common region are distinct at entropy 7.999, which structured plaintext under ECB could not produce.
- That makes the two same-size packages a two-time pad, and it still yields nothing. Bright
and Neutral/Warm are byte-identical except for 4000 bytes at 0xd0..0x106f — one contiguous
region, 8-byte aligned, everything after it identical. XOR-ing them cancels the keystream and
gives
plainBright ⊕ plainNeutraldirectly. That XOR is 99% non-zero, entropy-flat, and has no int16/int32 structure at any alignment (0 of 1000 32-bit values below 256 in magnitude). Two plaintext coefficient tables would not XOR to noise; two independently compressed or keyed blobs would.
Conclusion. The entire "external tuning" product is a 4000-byte encrypted blob at a fixed
offset inside a 188 KB common wrapper. Without the KAS it is opaque, and brute-forcing it is not
tractable with upgtool's keysig search (that search assumes a short ASCII key).
So the marketing signature is HALF reachable, and we already have that half. The HAL variant —
which ALSA device the stream opens plus the CPU clock floor — is reproduced byte-for-byte by
cinder-home/deploy/cinder-signature.sh. The paired "external tuning" is not, and no amount of
host-side work will change that. Anyone claiming Cinder can deliver "Bright" or "WM1Z" in full
would be claiming something this analysis shows is false.
/etc/.mod/tunings/{Bright,Neutral_&_Warm,WM1Z}_external_tuning/, ~4.1 MB each. Each is a Windows
installer (FirmwareUpdateTool.exe + WmFwUpdater.dll) wrapping a nested 192 KB
NW_WM_FW.UPG. SWUpdate.xml targets DevicePropertyProductInfo = NW-WM1Z, version 3.02.
Per the bundled Tunings_Info.txt, these are a second step on top of the signature:
- Change the sound signature in the settings file;
- Restart the player…;
- Apply the corresponding external tuning … by launching FirmwareUpdateTool.exe. … you would see the "External tuning not installed!" message if the external tuning would not be applied.
So the marketing names (Warm/Bright/Neutral/WM1Z) are the pair of a HAL variant and a flashed tuning blob. The 192 KB payloads are not yet unpacked — that is the main open question, because it decides whether the full signature is reachable without flashing or only the HAL half is.
-
The CPU clock floor — trivially, today. One sysfs write on play/stop. Cinder already manages the pump cadence and knows the play state. No file swap, fully reversible, and it is one of only two things the paid signature patch actually does. Battery cost is real and measurable.
-
The ALSA device choice — needs the HAL swap. Cinder plays through Sony's PlayerService, so the
hw:0,Nstring lives in the HAL, not in Cinder. Droppingpv1/pv2into/vendor/sony/lib/libaudiohal-adleralsa.sois a plain file replace with the same install discipline ascinder-home(keep a.prev). This is the highest-value / lowest-effort item. -
dacdatre-programming — UNBLOCKED, and the interface is explicit.dacdat's own usage:dacdat ovt FILE --- output volume table (ov_*.tbl) dacdat dgt FILE --- device gain table dacdat tct FILE --- tone control table (tc_*.tbl) dacdat auto MODEL VOL_LIMIT MODEL : BBDMP2_linux / BBDMP3_linux / BBDMP5_linux VOL_LIMIT : 0 / 10The stock binary already accepts
BBDMP2_linux— Walkman One's model — andVOL_LIMITis a bare0or10, which is the region cap expressed as an argument. All it lacks is the 1280/127x tables, which are now staged in/system/usr/share/audio_dac/on the device (inert:load_sony_driverrunsdacdat auto $PRODDEV …withro.product.devicestillBBDMP5_linux, so boot keeps loading the 1291 set).NOT YET RUN. Loading a different output-volume table changes what every volume step does, and
VOL_LIMIT 0removes a cap. That belongs to a deliberate session with headphones OFF, not to a background push. -
The external tuning blobs — CLOSED, negative. A 4000-byte encrypted payload behind an unknown KAS; see Layer 3 above for the three independent lines of evidence. Not reachable.
-
The WM1A volume curve — reachable, and the most interesting thing left.
gain_lis the NW-WM1A's ownov_127x/ov_dsd_127x, loadable withdacdat ovt. See Layer 1b.
The limiter is dacdat limiter_* $shpfirst where shp is an NVP flag, not a property. Changing
it is a different, lower-level operation than anything above, and it raises the actual output
ceiling rather than changing tonality. Treat it as a separate decision with its own testing — the
A50's EU cap exists for hearing-safety reasons, and raising it changes what a given volume step
does to your ears, not just what the DAC reports.
- The prior
analysis/5_stock_vs_w1_diff.txtis a sector-level diff of the packed.bins and is useless for feature work. Use the extracted filesystems. - The UPG entry numbering shifts by one between stock and W1 (W1 inserts a file at index 0), so
N.bindoes not mean the same partition in both. Stock system =6.bin; W1 system =7.bin. - Both system images are ext4 with the same UUID (
57f8f4bc-…), so mounting both at once needs-o nouuidor, better,debugfsas used here.
The ranking above was derived from the extracted filesystems. Checked against the running A55, and it holds — with one finding that makes item 3 considerably better than it reads.
WRONG — corrected 2026-09-13. A stock NW-A50's
/system/usr/share/audio_dac/holds 55 files and only the A50's own set:ov_1291,ov_1291_cew,ov_dsd_1291,ov_dsd_1291_cew,tc_1291. That is the device listing on 2026-09-13, the extracted stock rootfs (artifacts/rootfs_mnt), and the listing in Wampy'sMAKING_OF_VOLUME_TABLES.md. The six extra files below were on the reference device because an earlier session had copied them in from the Walkman One image —ov_127x's md539a60adc…is W1'sgain_l/ov_127x.tbl— and a copy that keeps the source's mtime makes "dated 2019-07-31" prove nothing. By 2026-09-13 they were gone, andcinder-voltable wm1afailed on every boot. The md5 and equality notes below still describe the files themselves; what is wrong is that a stock player has them.
/system/usr/share/audio_dac/ on the stock device, 61 files, all dated 2019-07-31 — Sony's own
build stamp, not anything staged by us:
ov_1291.tbl bb5ccae7b1a147b3507cb787cda522a6 <- the A50 set, what boot loads today
ov_1280.tbl 5bf930c0209cbe4b7ba871e74e6b2b30 <- BBDMP2, i.e. Walkman One's model
ov_127x.tbl 39a60adc7240be8deab95c39becf4419 <- the NW-WM1A's own curve
Three genuinely different files (distinct md5s, same 84950 bytes). Same story for the DSD and tone tables, with a detail worth noting:
ov_dsd_1291 == ov_dsd_1280 but ov_dsd_127x differs -> the WM1A has its own DSD curve
tc_1280 == tc_127x but tc_1291 differs -> the A50 has a DIFFERENT tone-control
table from BOTH higher models
So switching sets changes the volume curve and the tone-control table together. And it needs
nothing from Walkman One at all — the payload is Sony's, sitting inert on every stock A55,
reachable only because load_sony_driver passes ro.product.device = BBDMP5_linux.
$ readelf -d dacdat | grep NEEDED -> libasound
$ strings dacdat -> /proc/icx_audio_cxd3778gf_data
/proc/icx_audio_dnc_data
$ ls /proc/icx_audio_cxd3778gf_data/ -> ovt ovt_dsd dgt tct tct_ng/nh/sg/...
limiter_31/500/750 ainc_* ambgain
b_nc_gain u_ncgain_* c_nw750_nml_0..7 i_data
It is a directory of per-table proc nodes, -rw------- root root, that the codec driver reads. That
means the tables can be loaded at any time, by any root process — and Cinder's launcher already
runs as root, exactly as it already runs cinder-signature.sh. No model swap, no partition write,
no boot-order dependency.
dacdat's usage also lists more than this document recorded: bncgt/uncgt (NC gain tables),
idata (IRAM), per-headphone cnw500n/cnw750n/cnc31n CRAM sets, ambgain, and a third
model in auto — BBDMP2_linux / BBDMP3_linux / BBDMP5_linux.
| layer | status |
|---|---|
| HAL "sound signature" — ALSA device + CPU floor | PORTED. cinder-signature.sh, installed |
| CPU clock floor on its own | FREE, unwired. scaling_min_freq is already 0666 |
Volume / DSD / tone tables (ov_*, tc_*) |
FULLY REACHABLE, and needs no W1 files. All three sets ship in stock; dacdat is byte-identical to W1's and applies at runtime |
dacdat auto BBDMP2_linux (whole model profile) |
Reachable. The stock binary accepts the model |
| External tuning blobs (Bright / Neutral & Warm / WM1Z) | CLOSED, negative. 4000-byte encrypted payload, unknown KAS, and the two-time-pad XOR is noise |
Still NOT RUN, deliberately. Loading a different output-volume table changes what every volume
step does to your ears, and VOL_LIMIT 0 removes the EU cap. That is a session with headphones OFF
and a way back (dacdat ovt ov_1291.tbl restores stock), not a background push.