dm2-graphics: image_offset implements only one of DM2_QUERY_GDAT_PICT_OFFSET's three displacement paths; 8-bit header offset bytes discarded #191

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

Problem

Archive::image_offset (crates/dm2-graphics/src/lib.rs ~296) implements only one of the three displacement paths of the engine's DM2_QUERY_GDAT_PICT_OFFSET ([SKPROJECT] v5/skgdtqdb.cpp:188-226):

record kind engine displacement source crate
x_mark == -32 companion cls3 = 0x0C inline record implemented (image_offset)
8-bit (y_mark == 31) header bytes [4], [5] (s84prg5->b_04 / b_05) bytes discarded by the decoder; no API
4-bit / passthrough (x_mark, y_mark) from the header marks marks exposed on Image, but image_offset returns None

So a caller placing sprites via image_offset gets None for every non-sentinel record even though the engine has a real displacement, and for 8-bit records the information isn't recoverable at all — decode_8bit skips bytes [4..6] entirely (crates/dm2-graphics/src/image/decoders.rs ~89).

Fix direction

Surface the 8-bit header bytes [4], [5] on Image (they're currently parsed past), and extend image_offset (or add sprite_offset(rec, image)) to reproduce the full engine dispatch: x_mark == -32 → 0x0C record; 8-bit → (b4, b5); otherwise → (x_mark, y_mark). The engine composes the result as (X << 8) | Y — same packing the 0x0C inline records already use, so the existing unpack helper generalises.

## Problem `Archive::image_offset` (`crates/dm2-graphics/src/lib.rs` ~296) implements only one of the three displacement paths of the engine's `DM2_QUERY_GDAT_PICT_OFFSET` (`[SKPROJECT] v5/skgdtqdb.cpp:188-226`): | record kind | engine displacement source | crate | |---|---|---| | `x_mark == -32` | companion `cls3 = 0x0C` inline record | implemented (`image_offset`) | | 8-bit (`y_mark == 31`) | **header bytes `[4]`, `[5]`** (`s84prg5->b_04` / `b_05`) | bytes discarded by the decoder; no API | | 4-bit / passthrough | `(x_mark, y_mark)` from the header marks | marks exposed on `Image`, but `image_offset` returns `None` | So a caller placing sprites via `image_offset` gets `None` for every non-sentinel record even though the engine has a real displacement, and for 8-bit records the information isn't recoverable at all — `decode_8bit` skips bytes `[4..6]` entirely (`crates/dm2-graphics/src/image/decoders.rs` ~89). ## Fix direction Surface the 8-bit header bytes `[4]`, `[5]` on `Image` (they're currently parsed past), and extend `image_offset` (or add `sprite_offset(rec, image)`) to reproduce the full engine dispatch: `x_mark == -32` → 0x0C record; 8-bit → `(b4, b5)`; otherwise → `(x_mark, y_mark)`. The engine composes the result as `(X << 8) | Y` — same packing the 0x0C inline records already use, so the existing unpack helper generalises.
jqueuniet commented 2026-07-06 06:22:44 +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#191
No description provided.