Skip to content

Fix: the configurator's DRAM link takes the ROM units' symbols, as the native builder does (#1312) - #1343

Merged
repeat98 merged 6 commits into
repeat98:mainfrom
Zac-Kyoti:fix-dram-link-rom-symbols
Nov 10, 2026
Merged

repeat98 merged 6 commits into
repeat98:mainfrom
Zac-Kyoti:fix-dram-link-rom-symbols

Conversation

@Zac-Kyoti

Copy link
Copy Markdown
Contributor
  • What was wrong or hard: a card build's DRAM code couldn't name a ROM unit's symbol in the configurator. The configurator links the DRAM runtime before the menus place the ROM units, so their addresses don't exist yet; natively such a reference made ld refuse the build. Mute Modes' answer to the card-build ev_trig_muted (SDK: a card-build counterpart of ev_trig_muted (#777) #1312) has to live in a DRAM unit and read KEYMASK in its ROM unit, so it needs this. As agreed on SDK: a card-build counterpart of ev_trig_muted (#777) #1312, this is the first option, in its own pull request.
  • What this changes:
    • The rule, the same in both builders: a reference a DRAM unit makes that no DRAM unit, platform symbol, DRAM region or declared defsym defines resolves from the ROM units' global symbols. Weak references are included; a weak one with no ROM symbol stays 0. A DRAM unit's own definition and a declared value always win. A build that linked before has no such reference (ld refused it), so nothing else changes.
    • Native: sdk/octabam/tools/build/dram_rom_refs.py, which build_bus.py applies to its DRAM link's --defsym set from _exports (the ROM units' globals, as ROM units already get them). tools/remix/ is untouched, so the reviewed pins over it don't move.
    • Configurator: resolveRomReferences in coldfire-runtime.ts. planStaticOs links the runtime provisionally (an open strong reference held at the base), places the menus (composeModuleMenus now returns romSymbols: CLONE_<key> and the globals of the units it places), then relinks with them only when a DRAM unit left a reference open. It checks the layout didn't move, since only relocated values change, so the menus' writes that name runtime addresses stay valid.
  • How I checked it:
    • Same bytes from both linkers: sdk/tests/test_dram_rom_symbols.py links a ROM unit and two DRAM units natively (a strong ROM byte, a weak ROM routine, a weak absent name, a name another DRAM unit defines, a declared region name) and writes src/engine/test-fixtures/dram-rom-symbols.json. src/engine/dram-rom-symbols.test.ts resolves the same references with the configurator's rule and links GNU's bytes. Both builders resolve exactly KEYMASK and fx_hook. Without the rule, ld refuses the open reference, and so does the configurator.
    • Nothing else changes: 86 selections (every module alone with and without stock FX2, and five large mixed sets) composed on main and on this branch: menu, DSP, platform and startup writes and the DRAM runtime are byte-identical, with only the logger's build-identity text masked.
    • Packages: rebuilt in the isolated toolchain and imported. Only provenance and the source-tree fingerprint change; every package byte is identical. Tape Echo's and Euclid's standalone recipes are re-pinned to the new asset files.
    • Analog BD proofs: re-exported natively (--suite analog-bd --static-stock --vendored-sdk, 8 shards, menus precomputed with defaultChoosers): all 212 proofs identical; only builderSources (build_bus.py) and moduleSourceTreeSha256 move.
    • Builder record: sdk/infrastructure-verification/dram-rom-symbols-builder.json, with its test in test_infrastructure_regressions.py and a chain entry. Two fresh native builds of the ptable2 record's 128 selections, with main's build_bus.py and with this one: every image (98) and every refusal (30) identical.
    • npm run pr:ready: Ready.
  • What the guides lacked or got wrong, and where I fixed it: nothing new for a guide yet. The rule matters once Mute Modes answers ev_trig_muted; sdk/machines/octatrack/card/README.md can then say that an answer unit may read its module's ROM state. I'll add that with the Mute Modes change.

Related to #1312 and #777.

🤖 Generated with Claude Code

Zac-Kyoti and others added 4 commits November 8, 2026 12:21
…e native builder does (repeat98#1312)

A reference a DRAM unit makes that no DRAM unit, platform symbol or region defines resolves from
the ROM units' global symbols. Native: tools/build/dram_rom_refs.py, applied by build_bus.py to its
DRAM link. Configurator: coldfire-runtime.ts resolveRomReferences; planStaticOs links provisionally,
places the menus (composeModuleMenus returns romSymbols), then relinks with them and checks the
layout is unchanged. A build that linked before has no such reference, so nothing else changes.
Same-bytes test: sdk/tests/test_dram_rom_symbols.py writes the fixture from GNU's link,
src/engine/dram-rom-symbols.test.ts links it with the configurator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the source-tree fingerprint only); Tape Echo and Euclid standalone recipes re-pinned

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…only build_bus.py's fingerprint and the source tree move

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ll 128 selections (98 images, 30 refusals) identical

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the bug Something isn't working label Nov 8, 2026
@Zac-Kyoti

Copy link
Copy Markdown
Contributor Author

@repeat98 @timhastie The configurator fix from #1312, as agreed: the DRAM link now takes the ROM units' symbols, the same rule in both builders, with the same-bytes test. Nothing changes for any existing build. Next, after #1195: the joinRuntime extension for an answer unit.

@repeat98

repeat98 commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Thanks Zac, this is careful work, and the same-bytes fixture from both linkers is exactly what I hoped for.

One thing before I merge. In planStaticOs the relink only runs when at least one open reference is in menus.romSymbols. If none of them is (a typo, or the answer unit linked without its ROM unit), the provisional runtime stays, and a strong reference ships pointing at the runtime base instead of being refused. Natively ld still refuses that case, and before this PR the configurator did too. Could you relink whenever runtime.romRefs.length is non-zero, so the final link refuses a missing strong reference as before, and add a test for that through planStaticOs?

A smaller note for the Mute Modes change: romSymbols leaves out the Spectrum SHPE and Tape TIME units' globals. Nothing needs them today, but a native-vs-configurator check with the real answer unit would catch any gap in the set.

Zac-Kyoti and others added 2 commits November 9, 2026 16:05
…no ROM unit defines is refused as before; romSymbols takes the Spectrum SHPE and Tape TIME units' globals too

Review on repeat98#1343: the relink ran only when one open reference was among the ROM symbols, so with none
(a typo, or an answer unit linked without its ROM unit) a strong reference shipped at the provisional
base. src/engine/static-compose-rom.test.ts drives planStaticOs with the fixture's DRAM unit through
the real DRAM link: ROM addresses applied, a missing strong reference refused, none placed refused
(the last fails with the old condition).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Zac-Kyoti

Copy link
Copy Markdown
Contributor Author

@repeat98 Thanks, good catch. Both are pushed (24b7af7a):

  • Relink whenever a reference is open. planStaticOs now relinks whenever runtime.romRefs is non-empty, so the final link refuses a strong reference that no ROM unit defines, as ld does natively and as the configurator did before this PR.
  • Test through planStaticOs. src/engine/static-compose-rom.test.ts drives it with the fixture's DRAM unit in place of Tape Echo's package, through the real DRAM link. The steps that need a stock OS are stubbed, and the menus report the ROM symbols they would place. Three cases:
    • the ROM addresses are applied (KEYMASK and fx_hook, a weak absent name at 0);
    • a missing strong reference is refused;
    • none placed at all is refused.
      With the old condition put back, the last case fails, so the test catches exactly the gap you described.
  • romSymbols now takes the Spectrum SHPE and Tape TIME units' globals too. When Mute Modes' answer lands, I'll run the native-vs-configurator check on the real answer unit, as you suggest.

I also merged main (nothing it changed touches these files, so no regeneration was needed). pr:ready says Ready.

@repeat98
repeat98 merged commit d06c555 into repeat98:main Nov 10, 2026
10 checks passed
repeat98 added a commit to Zac-Kyoti/modwerk that referenced this pull request Nov 10, 2026
…nerated asset JSONs merged row by row, rebuilt next

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
repeat98 added a commit to Zac-Kyoti/modwerk that referenced this pull request Nov 10, 2026
… the source tree fingerprint moves)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
repeat98 added a commit that referenced this pull request Nov 10, 2026
…F0 (#1064) (#1098)

* Octatrack base: the key bus to Y $7E00, Sidechain's MON words to Y $FF0 (#1064)

Frees Y $7F0-$9FF on both cores for a DSP machine's voice. The key bus moves
to the tail of the first internal FX2 slot (+$3E00, past every +$3DFD ring),
Sidechain Compressor's MON words to Y $FF0-$FFF (no stock effect writes
either range: emulator, every stock effect through FX1/FX2 on all tracks,
both cores).

- dsp-sites.json / dsp_ledger.h / resident_dsp: feature 1 owns three regions,
  feature 8 the window and the bus at $7E00. A reset chunk stops at every
  region end from the ledger (MW_DSP_RESET_END); the board's 528 and the
  driver's single split assumed two regions.
- Sidechain Compressor 0.2.1: manifest tokens and declared ranges only
  (source: Zac-Kyoti/octatrack-kyoti-fw 8868867).
- Sidechain Ringmod 0.2.1: the same-core read at $7E00 (npp1993 agreed).
- BBD Delay 0.1.2: buffer_words 0x203A as octabam #783 (JamCones agreed),
  so it stays clear of the bus on T1/T5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Key bus move: 0.2.1 / 0.1.2 evidence, captures and import record

Sidechain Compressor 0.2.1 and BBD Delay 0.1.2: hardware reports from the
author's MKI (30 October 2026), native images fb7c5e31 / c234d13c. Sidechain
Ringmod 0.2.1: screens on its native card image; hardware pending (USB only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Catalog: Sidechain Compressor 0.2.1, Sidechain Ringmod 0.2.1, BBD Delay 0.1.2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Compiled packages and assets from the isolated build of 69e7ee0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Beta base regenerated for the key bus move; USB packages rebound

- octatrack:base --beta --write: base 62ed0ec0 (controller trust rows,
  base binding and base assets); Analog BD's machine recipe recaptured
  (only imageSha256 moved: the base's symbols shifted).
- octatrack:module-packages --stock: Sidechain Compressor 0.2.1
  (fd275bf2), Sidechain Ringmod 0.2.1 (91281f07), BBD Delay 0.1.2
  (58b77069, buffer 8,250); Output Matrix and Analog BD rebound to the new
  base. Earlier versions' files kept as on main.
- Tape Echo's and Euclid's standalone recipes re-pin the rebuilt shared
  assets (as #969).
- Sidechain Compressor's composed image recorded (9b8c9ed3, captures
  pixel-identical to the native image's).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sidechain Compressor 0.2.1: composition proofs regenerated, test pins, import record author pin

Suites sidechain / sidechain-visible / analog-bd: the same selections build and
refuse as with 0.2.0; only selections containing the module changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Key bus move: native comparisons, pair table, test pins, BBD/Ringmod records

- module:verify: Sidechain Compressor, Sidechain Ringmod and BBD Delay, 0
  mismatches of 162 selections each.
- modules:pairs: bbd+sidechain-compressor is no longer refused in card builds
  (BBD's 8,250-word claim stays clear of Sidechain's key window).
- Tests that pinned Sidechain's two-region reset or the old MON address
  (test_owned_transfer, test_resident_boot, sidechain-compressor.test.ts).
- BBD and Ringmod performance records carried to their new versions (same
  instructions); the hooks doc does not grow.

Sidechain Ringmod 0.2.1's qualification stays 0.2.0's until its USB run on
a unit, so modules:generate refuses and module-documents.json is not
regenerated in this branch yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Compiled packages and assets from the isolated build of 1574c62; standalone recipes re-pinned

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* BBD Delay 0.1.2: drop the Sidechain Compressor flag; Sidechain Ringmod's release note names the T1/T5 limit

BBD's conflict with Sidechain Compressor existed only because of the 16K
claim (#731); with 8,250 words the pair builds (review on #1098).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Beta base 672d9ffc regenerated on current main with the key bus move; base-bound packages relinked

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Beta base dd3827f0 regenerated on the merged tree; base-bound packages relinked (only requiredBase moved)

npm run octatrack:base -- --stock OS.bin --beta --write, then
npm run octatrack:module-packages -- --base-only --stock OS.bin.
Drops the Sidechain Compressor 0.2.0 row the merge brought back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Module assets from build-modules-isolated.sh at aaf3e5c (image 1b15c3c0), imported with --development: only sourceCommit and the source tree fingerprint move

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Standalone recipes re-pinned to the rebuilt assets; Analog BD proofs re-exported (212, no refusal flips; against main only selections with Sidechain Compressor move)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: octatrack:module-packages refuses a package list that names a module twice; guide line on merging main into base and package assets

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix: device:qualify finds a chooser name with the package name's words in another order (RINGMOD SC)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sidechain Ringmod 0.2.1: qualification from the owner's MKII run of beta base dd3827f0 (twin 5015d2a7); module documents regenerated; superseded packages removed

DUCK keyed from the same and the other core and RING, measured from the unit's
USB audio, beside BBD Delay on T1/T5 FX2 and a keyed Sidechain Compressor;
self-test, removal in use refused, trial rollback and device:qualify passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Octatrack package list in main's order (the merge had appended Sidechain Ringmod 0.2.1 and BBD Delay 0.1.2)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Module assets from build-modules-isolated.sh at 7ec7903, imported with --development (only sourceCommit and the source fingerprint move)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Tape Echo and Euclid standalone recipes re-pinned to the rebuilt assets

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Analog BD proofs re-exported after #1343 (212 identical; only the source tree fingerprint moves)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jannik Aßfalg <67785539+repeat98@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants