From 3980aa8976ef5f03d030f43b8ce27a6d2251a411 Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Wed, 5 Aug 2026 17:03:19 -0700 Subject: [PATCH] The VMG's 0xC4 is TT_SRPT, not VMGM_C_ADT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The placement code skips that field for the Video Manager, which is right, but said it was skipping it because the field is the menu cell address table. It is the title search pointer table, and it is an offset inside the IFO rather than a pointer to another file — which is the actual reason it constrains nothing. ifo.rs reads the same offset under the correct name, so the two would have drifted. --- src/dirimage/layout.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dirimage/layout.rs b/src/dirimage/layout.rs index a904e65..fcde600 100644 --- a/src/dirimage/layout.rs +++ b/src/dirimage/layout.rs @@ -399,8 +399,12 @@ fn place_video_ts(vts: &mut DirNode, start: u32) -> Result { if menu != 0 { menu_req.insert(c.group, lba.saturating_add(menu)); } - // Only a VTS IFO carries a title VOBS pointer at 0xC4; the VMG's - // 0xC4 is a different field entirely (VMGM_C_ADT). + // Only a VTS IFO carries a title VOBS pointer at 0xC4. In the VMG + // (`VIDEO_TS.IFO`) that offset is TT_SRPT, the title search pointer + // table — a sector offset INSIDE the IFO, not a pointer to another + // file, so treating it as one would place `VIDEO_TS.VOB` at a + // meaningless address. (`ifo.rs::parse_vmg` reads the same field as + // TT_SRPT; the two must not drift.) if c.group > 0 { let title = be_u32(&head, 0xC4).unwrap_or(0); if title != 0 {