The moby class-id space is known: lvl.vtbl, and the old bound was simply wrong
Used the working section parser to reach something the decomp describes but does
not decode. lvl.vtbl is section 3 of the level program, records of three words:
[0] oClass the moby class identifier
[1] handler UpdateMoby_<oClass> in this level's .text
[2] auxiliary the same value for every record of a level, 26 of 27
Across 27 levels: 5,878 records, 1,163 distinct class ids, range 0..0x13BA (5,050),
median 38 new ids per level. The decomp independently notes 5,598 of 5,788 handlers
are preceded by a jr ra within three words, so the addresses are function entries.
WHY THIS RETIRES THE EARLIER BOUND
moby_classes.count is 238 on level 0. 1,135 of the 1,163 real 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 a test for "this is a small number".
That is the mechanism behind the chunk class-ID artifact I retracted two commits
ago:
slot values 1, 3, 4, 5, 10, 11, 12, 13, 15
all below 238, so all scored as hits, giving 305x enrichment
The bound was wrong BEFORE the artifact was noticed, and the artifact was a
consequence of it. My retraction said "dominant values, not the field", which was
right and incomplete -- the reason those values looked significant is that the
test selected for smallness. Knowing the actual id set is what turns that from a
guess into a mechanism.
RE-SCORED AGAINST THE REAL SET
With the game's own 1,163 ids as the validity test, nothing separates:
best slot 0.375 (type f2ef4275 slot 34)
chance rate 0.018 (1,163 ids in 65,536 values)
a dozen slots 0.25 .. 0.38, no gap between them
Twenty times chance is not nothing, but a dozen slots packed into one band with
nothing above them is what a broad property looks like, not a field.
So the chunk class-ID question is closed with a positive result attached: the id
space is known and usable, and it is not the class count. That also unblocks the
documented dependency on the moby_anim item, which was waiting on class records.
Asserted in moby_class_ids_come_from_lvl_vtbl_not_from_the_class_count.
262 tests.
This commit is contained in:
@@ -3065,3 +3065,58 @@ prints `.word` for anything undecodable, and reports the failure count.
|
||||
The undecodable words here are VU1 microcode (`0x0260202d` and friends are COP2
|
||||
opcodes), which is expected and is itself informative: this function interleaves
|
||||
VIF-fed VU1 work with FPU arithmetic, like `tfrag`'s.
|
||||
|
||||
|
||||
## `lvl.vtbl` gives the real class ids, and the old bound was wrong
|
||||
|
||||
`lvl.vtbl` is **section 3** of the level program -- one of the seven sections the
|
||||
Phase 3 port made visible. Its records are three words:
|
||||
|
||||
[0] oClass the moby class identifier
|
||||
[1] handler address of UpdateMoby_<oClass> in this level's .text
|
||||
[2] auxiliary the same value for every record of a level, 26 of 27
|
||||
(level 1 has exactly one record pointing elsewhere, 0x2a5d94)
|
||||
|
||||
Walking all 27 levels:
|
||||
|
||||
5,878 records
|
||||
1,163 distinct class ids
|
||||
range 0 .. 0x13BA (5,050)
|
||||
median 38 new ids contributed per level
|
||||
|
||||
The decomp's `docs/MOBY-DISPATCH-TABLES.md` describes exactly this layout, and
|
||||
independently notes that 5,598 of 5,788 handlers are preceded by a `jr ra` within
|
||||
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
|
||||
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
|
||||
a test for "this is a small number". That is the mechanism behind the chunk
|
||||
class-ID artifact:
|
||||
|
||||
slot values 1, 3, 4, 5, 10, 11, 12, 13, 15
|
||||
every one is below 238
|
||||
so every one scored as a hit
|
||||
65536 / 238 = 275x ... and the largest such score was 305x
|
||||
|
||||
The bound was wrong *before* the artifact was noticed, and the artifact was a
|
||||
consequence of it. Retracting the claim for "small dominant values" was correct
|
||||
but incomplete -- the reason those values looked significant is that the test
|
||||
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:
|
||||
|
||||
best slot 0.375 (type f2ef4275 slot 34)
|
||||
chance rate 0.018 (1,163 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
|
||||
with nothing above them is what a broad property looks like, not a field. The
|
||||
positive finding stands and is now usable: **the class-id space is known, and it
|
||||
is not the class count.** Asserted in
|
||||
`moby_class_ids_come_from_lvl_vtbl_not_from_the_class_count`.
|
||||
|
||||
Reference in New Issue
Block a user