5.3 KiB
Addresses that moved, and what that means for the older reports
The probe-hardening pass needed room inside the $E6F2-$E732 block, which had only three spare
bytes, so six internal helpers were relocated. Nothing the game, the ABI or the frozen regions name
by address moved - checkAbi.py still passes - and every one of these is reached only by a JSR or
JMP from code that changed in the same pass.
| routine | was | now |
|---|---|---|
aciaSetCommandIdle |
$E72A |
$E408 |
baudEntryTable |
$E6FD |
$E706 |
queueAndKickTx |
$E712 |
$E71B |
silenceCia2 |
$E71E |
$E727 |
countLinkError |
$E403 |
$E73F |
aciaPageLatch |
(new) | $E5BF |
queueByteForTransmit $E73C kept its address and became a tail JMP into queueAndKickTx.
The adopt-mode and re-entrancy-guard pass (2026-08-22)
The NMI re-entrancy guard and the probe that reads the user's own line settings before overwriting
them needed 50-odd bytes inside $E644-$E732, a block that had six spare bytes in it. Three
routines left the block, one routine was deleted, one was folded into another, and the table grew an
eighth entry. Again, nothing the game, the ABI or the frozen regions name by address moved, and
checkAbi.py still passes.
| routine | was | now |
|---|---|---|
aciaResumeReceiver |
$E658 |
$E5B1 |
silenceCia2 |
$E727 |
$E56F |
dropDtrLine |
$E574 |
$E408 |
aciaSetPage |
$E663 |
$E6FA |
aciaProbe |
$E6F2 |
$E655, renamed aciaProbeAdopted - it reads the control register before it writes one |
baudEntryTable |
$E706 |
$E710, and 23 bytes wide: eight entries, not seven (the last entry's spare byte is not needed) |
queueAndKickTx |
$E71B |
$E727 |
| the NMI handler's chain exit | $E679 |
$E67B |
aciaDetectDone |
$E654 (as setBitPeriodFull) |
$E654, unchanged, and now the shared 'nothing to do' RTS of the transmit path as well |
Deleted outright: aciaSetCommandIdle $E408 (the re-entrancy guard makes its second half provably
unnecessary at the one site that called it, so the NMI's disarm is a plain aciaSetCommand again),
clearUartState $E5B6 (its whole inline block was the single byte txCharActive, which
clearTxCharActive $E04F already clears in the same three bytes at the one call site), setBitPeriod
$E657 and the shared transmit-path RTS L_E662 (its callers now branch to aciaDetectDone $E654,
which is the same instruction). aciaRxByte $E5BD became nmiHandlerState, the guard's own byte:
the receive half tests the error bits before it takes the character out of the data register, so it no
longer needs anywhere to park it.
dropDtrLine moving is the only one of these that is visible outside the driver's own block: the
JSR operand at $E38E inside hangUpModem had to follow it, which is why checkAbi.py now lists
$E38E-$E38F as changed.
The dead ignoreLinkError stub that used to sit at $E408-$E40E was deleted to make the space; it
was provably unreachable, and both halves of the error-vector pair at $E3C7/$E3C9 were repointed
at countLinkError so that even the never-selected configuration lands on a real hook.
Why the older reports were not rewritten
realtimeReport.md, strapReport.md, rate1200Report.md, highRateReport.md, hotkeyReport.md,
testReport.md and spec_uart.md cite several of the old addresses - $E403 most often, because
countLinkError is where the error tracepoint was set in every measurement.
Those documents are records of what was observed on the build that existed when the measurement was taken. Editing the addresses inside them would make them describe a run that never happened, so they have been left alone. Read an address in a test report as "the address that routine had at the time of that run", and use the table above to map it onto the current source.
README.md is the exception: it documents the driver as it stands now, and it was updated.
wedgeDiagnosis.md is a second exception in the other direction: it is a record of measurements made
against the build that still had the fault, so its addresses are the ones that build had.
Conclusions that were overturned
The same rule applies to a report's conclusions, and for the same reason. Where a later measurement has overturned one, the older file keeps its numbers and gains a note at the top pointing at the newer result - the way this file points at moved addresses. Three exist so far:
| File | What was overturned | By |
|---|---|---|
highRateReport.md |
"Must not be selected: 38400", and 9600/19200 as degraded modes | wedgeDiagnosis.md found the cause; portCompatReport.md sections 3-4 measured the guarded build |
hardenReport.md |
the 38400 retirement (its hot-key code blanked) | the same, plus testAdopt.py: C= + 8 selects 38400 again |
strapReport.md |
the two probe weaknesses in its section 8 | hardenReport.md (two patterns, and the page latched once per cold start) and portCompatReport.md section 9.1 (the $DF00 fallback now reads that page before writing it) |
spec_uart.md carries a note of the same kind on its hazards checklist: hazard 2's character-time
arithmetic is three times out, and hazard 8's "same 8N1 framing" now describes only the data bits,
since the driver adopts the port's own stop bits and clock source.