docs/program-format: document Remarks-table layout + resolution path

The previous "What we don't yet know" entry for RemarkID -> RemarkText
is now closed. Replaced the placeholder note with the actual format
(clsPrograms.ReadRemarks layout) and a Python usage example showing
how to resolve a Program's remark_id against PcaAccount.remarks.

Removed the "RemarkID -> RemarkText lookup" line from the
"what we don't yet know" list.
This commit is contained in:
Ryan Malloy 2026-05-11 21:34:02 -06:00
parent f45e9fd014
commit e4dbcf0429

View File

@ -45,8 +45,35 @@ When `prog_type == REMARK` (4) the bytes at offsets 1-4 hold a single
| 1-4 | `remark_id` | BE u32 |
| 5-13 | (unused, typically zero) | bytes |
The lookup from `remark_id` to the user-visible remark string lives in a
separate table on disk that we have not yet reverse-engineered.
The lookup from `remark_id` to the user-visible remark text lives in a
separate **Remarks table** further down the `.pca` body. Layout
(`clsPrograms.ReadRemarks`, clsPrograms.cs:148-168):
```
[u32 LE _RemarksNextID]
[u32 LE count]
[ for each entry:
[u32 LE remark_id]
[u16 LE text_length][text_length bytes UTF-8]
]
```
To reach the Remarks table from end-of-Connection, the walker skips
nine fixed-shape Description blocks (one per object family, each
`[u32 count] + count × 33 bytes`); see
`clsHAC.cs:8055-8079`. The Python parser puts the resolved dict on
`PcaAccount.remarks`:
```python
from omni_pca.pca_file import parse_pca_file, KEY_EXPORT
from omni_pca.programs import ProgramType, iter_defined
acct = parse_pca_file("Account.pca", key=KEY_EXPORT)
for p in iter_defined(acct.programs):
if p.prog_type == ProgramType.REMARK:
text = acct.remarks.get(p.remark_id, "<unresolved>")
print(f"slot {p.slot}: remark {p.remark_id} = {text!r}")
```
## Enums
@ -208,9 +235,6 @@ pass. So is the multi-record clausal encoding hinted at by the
the `WHEN / AT / EVERY / AND / OR / THEN` ProgType values — so we
can't yet say whether they reference adjacent slots, use extra bytes
within a single slot, or live in some separate clause table.
- **RemarkID → RemarkText lookup.** The remark-text table on disk has
not been located; `RemarkID` decoded fine, but we can't resolve it
to a string today.
- **`DoubleProgramConditional` capability flag.** We hardcode 14-byte
records for the Omni Pro II. Other models may use the 12-byte form.
Locating where the panel advertises the flag (and which non-OPII