210 lines
9.1 KiB
Markdown
210 lines
9.1 KiB
Markdown
# PT2 Continuation Command Trace
|
|
|
|
This note enumerates the command paths that are active after the ROM sees `FAA2 != 0`.
|
|
|
|
## Dispatcher Shape
|
|
|
|
RX command dispatch starts after six-byte frame validation at `H'BBD6-H'BC67`.
|
|
|
|
Important gates:
|
|
|
|
- `F9C3 == 6`.
|
|
- SCI/RX physical error latch `FAA4.7 == 0`.
|
|
- Checksum matches `0x5A ^ F860 ^ F861 ^ F862 ^ F863 ^ F864 == F865`.
|
|
- Command number is `F860 & 0x07`.
|
|
- `F861.7` rejects normal command handling.
|
|
- `FAA2 == 0` enters the initial dispatcher.
|
|
- `FAA2 != 0` enters the continuation dispatcher.
|
|
|
|
Continuation split:
|
|
|
|
| Incoming command bits | Path | Meaning |
|
|
| --- | --- | --- |
|
|
| `command & 0x04 != 0` | `H'BC3A-H'BC56` | explicit continuation commands `4/5/6/7` |
|
|
| `command & 0x04 == 0`, `FAA2.3 == 0` | `H'BC5C -> H'BE6F` | ignored/returns |
|
|
| `command & 0x04 == 0`, `FAA2.3 == 1` | `H'BC5C-H'BC67 -> H'BC15` | clears queued-report continuation bit and re-enters initial command handling |
|
|
|
|
That last row is easy to miss: command `0/1/2/3` can consume the report-continuation latch when `FAA2.3` was set by an autonomous report, then command `0/1/2` can run as an initial command. Command `3` still has no recognized initial handler and falls to the clear/return path.
|
|
|
|
Selector bytes are packed from `F861:F862`, mapped by `loc_622B`, then doubled into `R4 = selector * 2` before the command handlers use the selector as a word-table offset.
|
|
|
|
## Explicit Continuation Commands
|
|
|
|
| Command | Handler | Table writes | Queue/report behavior | Cleanup |
|
|
| --- | --- | --- | --- | --- |
|
|
| `4` | `H'BD0E` | writes `E000`; selector zero also writes `E800`; sets `EC00.7` | calls `BE70` to append selector to `F970`; if `FAA2.3` set, advances `F9B5` | clears `FAA3`, clears `FAA2` |
|
|
| `5` | `H'BD80` | none | special selectors may append to `F970` or clear latches; if `FAA2.3` set, advances `F9B5` | clears `FAA3`, clears `FAA2` |
|
|
| `6` | `H'BDDB` | writes `E400`; sets `EC00.6` | does not append to `F970`; if `FAA2.3` set, advances `F9B5` | clears `FAA3`, clears `FAA2` |
|
|
| `7` | `H'BE05` | none | copies previous finalized TX frame from `F858-F85C` to `F850-F854` and retransmits | does not clear `FAA2/FAA3` in this handler |
|
|
|
|
## `BE70`: Selector Processing Queue Append
|
|
|
|
`BE70` is the shared helper used by command `0`, command `4`, and selected command-`5` cases.
|
|
|
|
Path `H'BE70-H'BE9D`:
|
|
|
|
- Scans the `F970` word ring from consumer cursor `F9B9` to producer cursor `F9B4`.
|
|
- If the selector is already present, returns without appending a duplicate.
|
|
- If absent, writes the selector to `F970 + 2*F9B4`.
|
|
- Increments `F9B4` and clears bit 5, making the queue a 32-entry ring.
|
|
|
|
Practical meaning:
|
|
|
|
- `F970` means "process this selector internally".
|
|
- It is separate from the serial-visible report queue at `F870`.
|
|
- Re-sending the same selector may refresh table values without creating another queued selector entry if the old entry has not been consumed yet.
|
|
|
|
## Command 4: Continuation Primary Write
|
|
|
|
Selector zero branch:
|
|
|
|
- `H'BD12-H'BD18`: builds value from `F863` and forces low byte `0x80`.
|
|
- `H'BD1A`: writes `E000[0]`.
|
|
- `H'BD1E`: writes `E800[0]`.
|
|
- `H'BD22`: sets `EC00[0].7`.
|
|
- `H'BD26`: calls `BE70`, appending selector zero to `F970`.
|
|
|
|
Nonzero selector branch:
|
|
|
|
- `H'BD2B-H'BD35`: builds value from `F863/F864` and writes `E000[selector]`.
|
|
- `H'BD39`: sets `EC00[selector].7`.
|
|
- `H'BD3D-H'BD45`: if the selector has a mapped shadow slot, writes the value into the `F400` shadow area.
|
|
- `H'BD49-H'BD5F`: if `F76E.7` is set, uses the mapped shadow offset plus the `F76E` page nibble and calls `BFE0`, the EEPROM/persistent-write path.
|
|
- `H'BD64`: calls `BE70`, appending the selector to `F970`.
|
|
|
|
Persistent-write detail:
|
|
|
|
- If the selector-to-shadow map entry is zero, the mirror/persist path is skipped.
|
|
- `BFE0` seeds retry timer `F840=0x0A`, writes via the P9/X24164 helper path, reads back for verification, and sets `F841.7` on timeout/failure.
|
|
|
|
Report consumption:
|
|
|
|
- `H'BD67-H'BD71`: if `FAA2.3` was set by a queued report, increments `F9B5` and clears `F9B5.7`.
|
|
- `H'BD75-H'BD79`: clears `FAA3` and `FAA2`.
|
|
|
|
Practical meaning:
|
|
|
|
- Command `4` is a continuation write/update, not a generic always-live command.
|
|
- Command `4` selector zero can refresh both the primary/current table and queue the CONNECT selector.
|
|
- Nonzero command `4` does not directly refresh `E800`; autonomous report values still come from the older/current `E800` value unless another path updates it.
|
|
|
|
## Command 5: ACK-Like / Special Selector Command
|
|
|
|
Command `5` reaches `H'BD80` only from the continuation dispatcher:
|
|
|
|
- `FAA2 != 0`.
|
|
- `command & 0x04 != 0`.
|
|
- `F861.7 == 0`.
|
|
- `F860 & 0x07 == 5`.
|
|
|
|
Special enqueue selectors:
|
|
|
|
| Selector | Branch | Later selector dispatch | Current meaning |
|
|
| --- | --- | --- | --- |
|
|
| `0x006C` | `H'BD80 -> H'BDBF` | `H'2FAF` | COPY completion/exit sibling when copy flags are live |
|
|
| `0x006D` | `H'BD85 -> H'BDBF` | `H'3015` | COPY in-progress/start refresh |
|
|
| `0x006E` | `H'BD8A/H'BD8F -> H'BDBF` | `H'2CA6` | special-accepted but selector dispatch is currently no-op |
|
|
|
|
The duplicate `0x006E` compare at `H'BD8A` and `H'BD8F` appears redundant in the current decode.
|
|
|
|
Selector-table math for the special group:
|
|
|
|
- Table base is `H'28A6`.
|
|
- `0x006C` indexes `H'297E`, whose pointer is `H'2FAF`.
|
|
- `0x006D` indexes `H'2980`, whose pointer is `H'3015`.
|
|
- `0x006E` indexes `H'2982`, whose pointer is `H'2CA6`.
|
|
- `H'2CA6` clears `F769.7` and returns.
|
|
|
|
Latch-clear selectors:
|
|
|
|
| Selector | Gate | Effect |
|
|
| --- | --- | --- |
|
|
| `0x006B` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
|
| `0x0096` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
|
| `0x0097` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
|
| `0x00C6` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
|
| `0x00F8` | only if `F731.7` set | clears `F731.7` and `F790.7` |
|
|
|
|
Report consumption and cleanup:
|
|
|
|
- `H'BDC2-H'BDCC`: if `FAA2.3` was set by a queued report, increments `F9B5` and clears `F9B5.7`.
|
|
- `H'BDD0-H'BDD4`: clears `FAA3` and `FAA2`.
|
|
|
|
Practical meaning:
|
|
|
|
- Command `5` is the closest thing to an ACK, but only inside the continuation side.
|
|
- Most command-5 selectors do not have selector-specific meaning; they just consume/clear the continuation state if one is live.
|
|
- `0x006C/0x006D/0x006E` are command-5 special cases because they enter the `F970` selector-processing queue.
|
|
- `0x006E` is accepted as special by the command handler, but its current selector-table target is `2CA6`, the no-op return path.
|
|
|
|
## Command 6: Continuation Secondary Write
|
|
|
|
Path `H'BDDB-H'BE03`:
|
|
|
|
- `H'BDDB-H'BDE5`: builds value from `F863/F864` and writes `E400[selector]`.
|
|
- `H'BDE9`: sets `EC00[selector].6`.
|
|
- `H'BDED-H'BDF7`: if `FAA2.3` was set by a queued report, increments `F9B5` and clears `F9B5.7`.
|
|
- `H'BDFB-H'BDFF`: clears `FAA3` and `FAA2`.
|
|
|
|
Practical meaning:
|
|
|
|
- Command `6` is the secondary feature/status table write used by menu visibility and gate code.
|
|
- It does not append the selector to `F970`, so it changes later decisions but does not itself force immediate selector dispatch.
|
|
|
|
## Command 7: Retransmit
|
|
|
|
Path `H'BE05-H'BE25`:
|
|
|
|
- Copies previous finalized TX bytes `F858-F85C` into staging bytes `F850-F854`.
|
|
- Loads `F9C0=0x1F`.
|
|
- Calls `BA26` to finalize/send again.
|
|
- `BA26` then waits for `F9C0 == 0`, reloads `F9C0=0x64`, reloads `F9C4=0x07`, copies staging bytes back to `F858-F85C`, recomputes the checksum into `F85D`, and starts SCI1 TX.
|
|
|
|
Practical meaning:
|
|
|
|
- Command `7` repeats the previous finalized TX frame.
|
|
- It is valid from both initial and continuation dispatch.
|
|
- It does not acknowledge/consume `F870` report queue entries by itself and does not clear `FAA2/FAA3` in this handler.
|
|
- The copied old checksum byte is not trusted; `BA26` recomputes the checksum.
|
|
|
|
## Distinct `07` Error Echo Path
|
|
|
|
The ROM also emits `07...` frames from an error/retry path that is separate from explicit command `7`.
|
|
|
|
Triggers:
|
|
|
|
- SCI/RX physical error latched in `FAA4.7`.
|
|
- Checksum mismatch at `H'BBF0`.
|
|
|
|
Path `H'BE29-H'BE6A`:
|
|
|
|
- Clears `FAA4.7`.
|
|
- Requires `FAA5.7`; if the session gate is absent, no echo is sent.
|
|
- Increments retry counter `FAA6`.
|
|
- For the first two retry attempts, stages:
|
|
|
|
```text
|
|
byte0 = 0x07
|
|
byte1 = RX[1]
|
|
byte2 = RX[2]
|
|
byte3 = RX[3]
|
|
byte4 = RX[4]
|
|
```
|
|
|
|
- Calls `BA26` to send the error echo.
|
|
- After too many retries, loads `F9C0=0x1F` and clears `FAA3/FAA2` instead of sending another echo.
|
|
|
|
Practical meaning:
|
|
|
|
- A `07 ...` frame is not automatically a normal command-7 retransmit.
|
|
- Old captures made with the wrong serial parity can easily be retry/error echoes.
|
|
- Valid frames clear `FAA6` at `H'BBF3`.
|
|
|
|
## Bench Implications
|
|
|
|
- To update active selector state during a report window, use command `4` or `6` while `FAA2 != 0`.
|
|
- To consume a queued report without changing tables, command `5` is the cleanest continuation ACK shape.
|
|
- To trigger COPY side effects, command `5` with `0x006D` starts/refreshes `COPY IN PROGRESS`, and command `5` with `0x006C` completes/exits only while the copy flags are live.
|
|
- Do not treat command `7` as an ACK. It is a repeat probe.
|
|
- A low command `0/1/2` sent while `FAA2.3` is live may clear the report continuation and then run as an initial command, which can make timing-sensitive bench traces look like an ACK plus a new command in one frame.
|