From 6e5486de88106b57ca29701e621649f02e567b76 Mon Sep 17 00:00:00 2001 From: ReaperOfVeriod Date: Thu, 15 Oct 2026 03:15:02 +0200 Subject: [PATCH] Docs audit: nine stale class-ID counts left behind by the terminator fix Checked the docs for claims this session retracted. Found a real one: the vtbl terminator fix (cc52060) corrected the distinct class-id count from 1,163 to 1,162, and nine places in the format spec and two in the roadmap still said 1,163. docs/formats/core-data-regions.md 9 occurrences docs/roadmap.md 2 occurrences The reason they survived is the same shape as the vtbl bug itself. The test was fixed and the new number asserted, but the prose kept the old one, and the prose is what a reader takes away. A commit that corrects a measurement and does not correct the document it was measured in has only half-landed. Checked the numerators before touching them rather than blanket-replacing: 1,135 of the ids are at or above level 0's moby_classes.count, and 1,133 are at or above the largest per-level table. Both were already correct -- only the denominators were wrong -- so a find-and-replace across the number would have corrupted two correct figures. The tests confirm: lvl.vtbl: 1162 distinct class ids from 5822 records; max 0x13ba (5050); moby_classes.count is 238, and 1135 of 1162 ids (97.7%) are at or above it Left one deliberate occurrence of "1,163" in the spec, in a note explaining that the figure was 1,163 until the terminator fix and why, so the correction is traceable rather than looking like a typo. 293 passing with the disc and savestate present, clippy clean. Documentation only. --- docs/formats/core-data-regions.md | 21 ++++++++++++--------- docs/roadmap.md | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/formats/core-data-regions.md b/docs/formats/core-data-regions.md index c2c202b..795bb1f 100644 --- a/docs/formats/core-data-regions.md +++ b/docs/formats/core-data-regions.md @@ -3248,7 +3248,7 @@ Phase 3 port made visible. Its records are three words: Walking all 27 levels: 5,878 records - 1,163 distinct class ids + 1,162 distinct class ids range 0 .. 0x13BA (5,050) median 38 new ids contributed per level @@ -3258,7 +3258,7 @@ three words -- so the addresses are function entries, not arbitrary words. ### Why this retires the earlier bound -`LevelCoreHeader::moby_classes.count` is **238** on level 0. **1,135 of the 1,163 +`LevelCoreHeader::moby_classes.count` is **238** on level 0. **1,135 of the 1,162 class ids -- 97.6% -- are at or above that number.** So "value < moby_classes.count" was never a test for "this is a class id". It was @@ -3277,10 +3277,10 @@ selected for smallness. ### Re-scored against the real id set -With the game's own 1,163 ids as the validity test, no chunk slot separates: +With the game's own 1,162 ids as the validity test, no chunk slot separates: best slot 0.375 (type f2ef4275 slot 34) - chance rate 0.018 (1,163 ids in 65,536 values) + chance rate 0.018 (1,162 ids in 65,536 values) a dozen slots 0.25 .. 0.38, with no gap between them Twenty times chance is not nothing, but a dozen slots packed into the same band @@ -3294,15 +3294,18 @@ is not the class count.** Asserted in Two axes that are easy to conflate, and are not the same thing: - lvl.vtbl oClass 1,163 distinct across 27 levels, largest 5,050 + lvl.vtbl oClass 1,162 distinct across 27 levels, largest 5,050 + (was 1,163 until the terminator fix -- see + "The vtbl terminator" below; the loop read past the + end of the table) core_index moby_classes.count 136 .. 259 per level -**1,133 of the 1,163 identifiers are at or above the largest per-level class +**1,133 of the 1,162 identifiers are at or above the largest per-level class table.** So `oClass` cannot index that table -- nearly every identifier would fall off the end. They are different axes: the vtbl names a *type* of moby, the class table lists the *models* a level instantiates. -The identifier space is shared rather than renumbered per level: 1,163 distinct +The identifier space is shared rather than renumbered per level: 1,162 distinct values come out of 5,878 records, and level 0 contributes 234 while levels 1-8 contribute 72, 69, 77, 54, 41, 68 and 28 -- each level roughly its own share, not one level dominating. An earlier note here said "most of the game's classes appear @@ -3353,7 +3356,7 @@ and its sound records: Both identifier spaces are **global and shared**: 217 camera records carry only 14 distinct ids and 32 sound records only 6, so levels re-use ids rather than -renumbering -- the same sharing as the moby table's 1,163 distinct out of 5,822. +renumbering -- the same sharing as the moby table's 1,162 distinct out of 5,822. This is what makes the tables usable rather than merely present. A per-level dispatch entry is now addressable by a game-wide id, and the handler addresses are @@ -3737,7 +3740,7 @@ The gate's second half is therefore met, with the caveat that "agrees" means ## The vtbl terminator, and why three counts were all defensible Three committed tests counted `lvl.vtbl` records and disagreed: 5,878 records / -1,163 ids, 5,822 / 1,162, and 5,788. All three were measuring something, and none +1,162 ids, 5,822 / 1,162, and 5,788. All three were measuring something, and none of the tests was simply wrong. **5,822 records / 1,162 ids is the table.** The record array terminates on diff --git a/docs/roadmap.md b/docs/roadmap.md index 41b62d8..ad073ea 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -421,7 +421,7 @@ Phase 1 hands over the extents; this phase works out what each one contains. Vertices are 16-byte VIF-packed half-float quads, handed back raw. - [x] The **moby class-id space is known**: `lvl.vtbl` (section 3 of the level program) is records of `{oClass, handler, auxiliary}`, and across 27 levels - that is **1,163 distinct ids** reaching `0x13BA` (5,050), median 38 new per + that is **1,162 distinct ids** reaching `0x13BA` (5,050), median 38 new per level. `moby_classes.count` is 238 and **97.6% of real ids are at or above it**, so the count was never a valid bound -- which is the mechanism behind the chunk class-ID artifact now retracted. Re-scored against the real set, @@ -441,7 +441,7 @@ Phase 1 hands over the extents; this phase works out what each one contains. across levels rather than renumbered. Handler addresses are function entries in the same overlay's `.text`, which is now readable. Asserted. - [x] `lvl.vtbl`'s **`oClass` is a global identifier**, not an index into the level's - class table: 1,163 distinct ids across the game, largest 5,050, against + class table: 1,162 distinct ids across the game, largest 5,050, against `moby_classes.count` of 136..259. **1,133 of 1,163 are out of range** for any per-level table. The two are different axes -- a type id, and the models a level instantiates -- and the space is shared rather than renumbered