dm2-graphics: docs: ENT1 type headers are (field letter, byte width) descriptors, not per-type record counts #192

Closed
opened 2026-07-05 07:48:27 +02:00 by jqueuniet · 1 comment
jqueuniet commented 2026-07-05 07:48:27 +02:00 (Migrated from codeberg.org)

Problem

Both crates/dm2-graphics/src/ent1.rs (TypeHeader { letter, count }, "ASCII letter code … plus the count of entries of that type") and docs/formats/graphics-dat.md ("type-header records: (type_letter_code, count) pairs") mislabel the ENT1 type headers.

The engine reads them as field descriptors: (field letter, byte width) pairs that define the layout of every entry record. DM2_LOAD_ENT1 matches each header letter against the canonical field list T I D S P F G, records the field's byte width (v1e09c0) and running offset (v1e09b2), and sums the widths into the record stride (v1e09ae) — [SKPROJECT] v5/bgdat.cpp:909-926; DM2_QUERY_GDAT_ENTRY_VALUE (bgdat.cpp:516-527) then reads each field at its declared offset/width.

All 16 fixture archives declare T,I,D,S,F,G,P with widths 1,1,1,1,1,1,2 — which is exactly why the crate's hardcoded 8-byte GraphicFileEntry (cls1..cls6 + u16 data) works. The "count" reading is self-evidently wrong from the data: ('P', 2) would mean "2 records of type P" in a table with thousands.

Two consequences beyond the doc fix:

  • Ent1::parse never validates the declared layout. An archive with reordered or re-sized fields (the engine would handle it) would be silently misparsed. Cheap guard: error (or warn) unless the headers match the canonical T1 I1 D1 S1 F1 G1 P2 shape.
  • The letters map onto the field roles (T=cls1 type?, I=cls2 id, D=cls3 data-kind, S=cls4 slot, F/G = cls5/cls6, P = the 2-byte payload/data word) — worth recording in graphics-dat.md while correcting the label.
## Problem Both `crates/dm2-graphics/src/ent1.rs` (`TypeHeader { letter, count }`, "ASCII letter code … plus the count of entries of that type") and `docs/formats/graphics-dat.md` ("type-header records: (type_letter_code, count) pairs") mislabel the ENT1 type headers. The engine reads them as **field descriptors**: (field letter, **byte width**) pairs that define the layout of every entry record. `DM2_LOAD_ENT1` matches each header letter against the canonical field list `T I D S P F G`, records the field's byte width (`v1e09c0`) and running offset (`v1e09b2`), and sums the widths into the record stride (`v1e09ae`) — `[SKPROJECT] v5/bgdat.cpp:909-926`; `DM2_QUERY_GDAT_ENTRY_VALUE` (`bgdat.cpp:516-527`) then reads each field at its declared offset/width. All 16 fixture archives declare `T,I,D,S,F,G,P` with widths `1,1,1,1,1,1,2` — which is exactly why the crate's hardcoded 8-byte `GraphicFileEntry` (cls1..cls6 + u16 data) works. The "count" reading is self-evidently wrong from the data: `('P', 2)` would mean "2 records of type P" in a table with thousands. Two consequences beyond the doc fix: - `Ent1::parse` never validates the declared layout. An archive with reordered or re-sized fields (the engine would handle it) would be silently misparsed. Cheap guard: error (or warn) unless the headers match the canonical `T1 I1 D1 S1 F1 G1 P2` shape. - The letters map onto the field roles (T=cls1 type?, I=cls2 id, D=cls3 data-kind, S=cls4 slot, F/G = cls5/cls6, P = the 2-byte payload/data word) — worth recording in graphics-dat.md while correcting the label.
jqueuniet commented 2026-07-06 06:22:45 +02:00 (Migrated from codeberg.org)

Fixed by #208 (merged into main).

Fixed by #208 (merged into `main`).
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jqueuniet/dm2-tools#192
No description provided.