6.8 KiB
Lofi-12 XT firmware — cross-version diff (v1.1.156 → v1.2.179 → v1.5.205)
Per-version structural notes: docs/firmware/notes-v{1.1.156,1.2.179,1.5.205}.md
(Sep-26 snapshots; update-entry + checksum notes there are superseded — see
docs/firmware-update.md and tools/README.md).
This file only documents what changed between builds.
Method: cmtd/mmtd/sect headers parsed per build (all verified to tile EOF
exactly); string sets compared as sort -u of strings output with length ≥ 6.
(Raw set lists were scratch files, not shipped.)
Code sects are rebased between builds (different DDR load addresses), so no
byte-level code diff was attempted — deltas below are sizes + string/symbol
evidence.
TL;DR
- v1.1.156 → v1.2.179: small delta (+10,592 B file, +10,080 B code). Only two
user-visible string additions:
TRACK MUTE,AppPad::handleKeyPadOnSliceMode. - v1.2.179 → v1.5.205: big delta (+100,852 B file, +90,912 B code). New subsystems
with fresh class families: audio export, MIDI Note Map, new master FX
(
MIsolator,MRackComp,SlipRoll,HoldDelay), sample tag search, precount/sequencer-transport rework,REVERSEsample mode, step-LED updates. - Callback ABI shift in v1.5: many
std::functionsymbols changeFv(void) →Fvi/Fvii/Fviiisignatures;FileUtilgainsremoveResourceFork+Rbparams; oldRenderBufferIhLi128ELi128Edisplay path symbols disappear.
Image headers
| Field | v1.1.156 | v1.2.179 | v1.5.205 |
|---|---|---|---|
| filesize | 1,595,605 (0x1858D5) |
1,606,197 (0x188235) |
1,707,049 (0x1A0C29) |
| sha256 | 617c3efe…1908ac5 |
30ea9eeb…b616a212 |
a8bffa65…4198026 |
| cmtd cksum | 0xF58AF539 |
0xDFF0D8C2 |
0xB17C0857 |
| mmtd flags | 6e 25 13 20 |
4e b6 e4 04 |
e8 bc f8 4f |
| version triple | (1, 1, 156) | (1, 2, 179) | (1, 5, 205) |
| entry point | 0xC26C4820 |
0xC26CA4C0 |
0xC2CD1AA0 |
| nsect | 7 | 6 (8 B zero slot absent) | 7 (slot back) |
All three entries disassemble (C64x LE) to the same reset prelude
(ZERO b0; mvc b0,ier; mvc b0,csr; mvk/mvklh b15/b14; and -8,…) — only the
stack immediates differ. Container version field stays (1, 3) in all builds.
Checksum is solved: CRC32-IEEE init 0 over the image with bytes [8:12]
replaced by 0xC27C6282 (proven 3/3; tools/ computes it). mmtd flags
semantics unknown, covered as-is, no handling needed.
Section map evolution
| Role | v1.1.156 (addr / len) | v1.2.179 (addr / len) | v1.5.205 (addr / len) |
|---|---|---|---|
| asset/blob | C27753B8 / 85,912 | C277B320 / 83,496 | C2DA7600 / 86,168 |
| float table | C2774C6C / 656 | C277AB18 / 660 | C2DA6DD4 / 688 |
| record table | C2775000 / 512 | C277B000 / 512 | C2DA7400 / 512 |
| code (.text) | C2589800 / 1,389,120 | C258D800 / 1,399,200 | C2B80C00 / 1,490,112 |
| 8 B zero slot | C2589508 / 8 | — absent — | C2B809E8 / 8 |
| strings (.rodata) | C2755488 / 115,561 | C275A7A0 / 117,825 | C2D84DE0 / 125,081 |
| float ramp tail | C27737F8 / 3,668 | C27793E8 / 4,348 | C2DA5680 / 4,312 |
Notes:
- Whole image rebased upward each release (code base
C2589800 → C258D800 → C2B80C00); relative layout (code → data → assets) is unchanged. - Code delta v1.1→v1.2 is +10,080 B; v1.2→v1.5 is +90,912 B.
- Strings-sect cross-refs grow monotonically: code-ptrs 5,854 → 5,909 → 6,362; self-ptrs 2,932 → 2,967 → 3,141.
- Big-sect entropy constant (6.890 / 6.887 / ~6.89, ~12.6% zeros) — same code+data mix, no new packing/encryption introduced.
- The 8 B zero sect comes and goes (present, absent, present) — looks like alignment/patch-slot churn in Sonicware's image generator, not a payload.
v1.1.156 → v1.2.179: +369 / −318 unique strings (≥6)
Essentially a feature-point release; only two user-visible additions:
TRACK MUTE(+PTN MUTEbehavior per changelog)AppPad::handleKeyPadOnSliceMode(+ lambda variant) — slice-mode pad handling (matches v1.2 changelog: EVEN slice mode, PAD hold/ROLL, per-track swing, new LSF/HSF filters — the rest is parameter/data churn, no new class families)
v1.2.179 → v1.5.205: +551 / −427 unique strings (≥6)
Added — new subsystems (each a whole class family, not one-offs)
- Audio export:
18AppAudioExportMenu,21AppAudioExportMixdown,25AppAudioExportMenuPattern,31AppAudioExportIndividualPattern,22AppSongAudioExportMenu,25AppSongAudioExportMixdown,28AppSongAudioExportIndividual(+…::executelambdas),20DialogAudioExporting, UI stringsAUDIO EXPORT,PATTERN/SONG MIXDOWN,MIXDOWN FILE NAME:,INDIVIDUAL TRACKS,CANNOT EXPORT,TO EXPORT. - MIDI Note Map:
14AppMIDINoteMap,MIDI NOTE MAP,NOTE MAP - New master FX (match v1.5 changelog):
SoundEffect::MIsolator,MRackComp,SlipRoll,HoldDelay - Sequencer transport rework:
…AppSequencerTransport…::startPrecount(newEibiEUliE/EibiEUlvEoverloads; oldEbiEUliE/EbiEUlvEremoved) REVERSE(sample reverse mode),18AppAudioFileSelect::playPreview,18AppSampleTagSearch::action,22StepEditPageController::updateAppLED,MixDown~
Added — API/ABI evolution
FileUtil::removeResourceFork(4 refs, previously 0) +Rb(bool) params onconvFsRecursive/searchFileRecursiveetc. — matches the v1.5 "1,024 files per folder / FILE DATABASE" rework. Old(…S1_jjPjS2_…)/(…_PA256_c…Fv…)overloads removed (6convFsRecursiveold-sig symbols gone).- Broad
Fv(void-callback) →Fvi/Fvii/Fviiisignature migration acrossTrackAndModuleController::checkStepLock*,MainDelegate::loadProjectData…, graphicsRenderBufferfunctors, etc.
Removed (meaningful, 35 strings ≥12 chars; rest is relocated code-sect noise)
- Old
FileUtiloverloads (see above), oldstartPrecountoverloads,TrackAndModuleController::checkStepLock{ForUpdateParams,ForSendingMidiCc}old shapes,MainDelegate::loadProjectDataWithProgressBarold shape. - Display pipeline: all
RenderBufferIhLi128ELi128ELi1327Esymbols gone — matches the "enhanced GUI / visual feedback" rework. CONVERTABLE FILES:and?REPITCH TO TEMPOstrings gone.
Continuity (present in all three)
Crash dumper (Legacy NMI Exception, A0–A31/B0–B31, NTSR/ITSR/…),
N3HAL*Driver family, 14AppSongBrowser, Lofi-12XT branding,
TRACK MUTE (added in v1.2, retained in v1.5).
AppPad::handleKeyPadOnSliceMode (added in v1.2) is superseded in v1.5
(symbol absent — slice engine reworked for 16 slices / multi-slice edit).
Open questions (updated 2026-09-30)
Checksum unknown— solved (see above +tools/lofi_image.compute_checksum).- C64x byte-level code diff: now feasible — Ghidra 12.1.3 + ghidra-c6000 lab is
set up (
ghidra/headless/, PyGhidra path) andanalysis/gen_funcmap.pymaps vtable-anchored functions; rebase-aware function-hash diffing still to be run.