FL Studio projects from v10 through v24 parse cleanly. v25 does not, and this blocks support for the current release.
What we know (see docs/FORMATS.md)
v25-era files appear to add an additive, file-offset-dependent obfuscation keystream over scalar (fixed-size, ID < 192) events:
- Two real autosaves of one project, same size: only 17 of 53,448 bytes differ (0.032%) — FL's writer is otherwise deterministic and positionally stable.
- But when file size changes by 48 bytes, 957 of 973 fixed-size events change, and 88.6% of the changed bytes differ by exactly +48 mod 256 — the file-size delta. All deltas are multiples of 16.
- Event count was identical, so the key is keyed on byte offset, not event index.
- A per-file constant
K was recovered (K=135 for one project, K=136 for another), and byte_real = byte_stored + byte_offset + K (mod 256) correctly decodes IsEnabled/Type/PingPongLoop — but not tempo or time signature, so the key function is not fully solved.
- v25 also breaks the event-width rule at a fixed spot: ID 172 (
0xAC) carries a 3-byte payload, so the stream must resync at 0x34.
The task
Solve the keystream, or prove it cannot be solved and implement the fallback (diff only variable-length events).
The experiment that would settle it — requires FL Studio 2025:
- Open a project, save as A.
- Change one note velocity (no length change) → save as B.
- Change one mixer knob → save as C.
- Add one note (length change) → save as D.
- Rename a channel → save as E.
Then byte-diff A/B/C/D/E. B vs A isolates whether a same-size edit is local under v25 obfuscation. D vs A confirms whether any size change globally rewrites scalars. C vs A measures MixerID.Params blob locality. Repeat on FL 20.9 to confirm the regression.
Start from experiments/flp_parse.py. Please report exact FL version numbers.
FL Studio projects from v10 through v24 parse cleanly. v25 does not, and this blocks support for the current release.
What we know (see
docs/FORMATS.md)v25-era files appear to add an additive, file-offset-dependent obfuscation keystream over scalar (fixed-size, ID < 192) events:
Kwas recovered (K=135 for one project, K=136 for another), andbyte_real = byte_stored + byte_offset + K (mod 256)correctly decodesIsEnabled/Type/PingPongLoop— but not tempo or time signature, so the key function is not fully solved.0xAC) carries a 3-byte payload, so the stream must resync at0x34.The task
Solve the keystream, or prove it cannot be solved and implement the fallback (diff only variable-length events).
The experiment that would settle it — requires FL Studio 2025:
Then byte-diff A/B/C/D/E. B vs A isolates whether a same-size edit is local under v25 obfuscation. D vs A confirms whether any size change globally rewrites scalars. C vs A measures
MixerID.Paramsblob locality. Repeat on FL 20.9 to confirm the regression.Start from
experiments/flp_parse.py. Please report exact FL version numbers.