Correction: the camera region is nine matrices, not three

dcd4dd6 said three 4x4 matrices at 64-byte stride and read them as a
view/modelview/lighting family. There are nine. Contiguous from 0x18aa70, breaking
at 0x18acb0 where row norms are 0, 0, 0.97 and w = 0.

All nine are orthonormal to 1e-6, all affine, all translating inside a 0.4-unit
box, all moving smoothly between live frames. Nine different rotations about one
position is not a view/projection/lighting family -- it is a table indexed by
orientation, and the index is what is unknown.

So dcd4dd6 was right that the region holds the camera position and wrong that
three was the extent. It stopped at three because three read as a sensible story.
That is rule 4's failure and I have now committed it twice in this investigation.

What survives unchanged: the translation is the camera position, (247.3, 193.1,
50.5), verified by orthonormality plus the smooth-motion control. The rotation
changes far faster than the translation between frames, which is what identifies
which part is which.

What is now open and larger than it looked: which of the nine is the R that
guard_band step 1 wants. Not "pick m0". Nine orientations about one point is a
table with an index. A plausible reading -- that these are the nine legal camera
orientations on a spherical planet -- would be a real find and is NOT established
by anything measured here.

Two cheap checks, both needing only the live emulator: move the camera and see
whether all nine translations move together or only one; and change pitch to see
whether the nine rotations reindex.

The test now checks all nine rather than three, so a tenth would be noticed.
294 passing with the disc and savestate present, clippy clean.
This commit is contained in:
2026-10-15 03:27:01 +02:00
parent dcd4dd6246
commit d4e81ba977
2 changed files with 51 additions and 10 deletions
+9 -8
View File
@@ -7914,7 +7914,7 @@ fn moby_classes_enrichment_survives_the_correct_mapping() {
}
}
/// The camera transform is three orthonormal matrices with a shared translation.
/// The camera region is nine orthonormal affine matrices sharing a translation.
///
/// Read live over PINE: two EE RAM dumps taken seconds apart, then the region at
/// `0x18aa70` is checked to be a 4x4 matrix whose upper 3x3 is orthonormal and
@@ -7944,11 +7944,12 @@ fn camera_transform_is_orthonormal_with_a_moving_translation() {
]
};
for (name, base) in [
("m1", 0x0018_AA70usize),
("m2", 0x0018_AA_B0),
("m3", 0x0018_AA_F0),
] {
// Nine, contiguous at 64-byte stride from 0x18aa70, ending at 0x18acb0 where
// the structure breaks (row norms 0, 0, 0.97 and w = 0). `dcd4dd6` said three
// and was wrong: it stopped looking after three because the first three
// happened to read as a sensible family.
for name in 0..9usize {
let base = 0x0018_AA70usize + name * 64;
for row in 0..3 {
let r = m(&a, base, row);
let norm = (r[0] * r[0] + r[1] * r[1] + r[2] * r[2]).sqrt();
@@ -7971,8 +7972,8 @@ fn camera_transform_is_orthonormal_with_a_moving_translation() {
assert_eq!(ta[3], 1.0, "{name} fourth row is not affine (w != 1)");
let moved = (ta[0] - tb[0]).hypot(ta[1] - tb[1]).hypot(ta[2] - tb[2]);
eprintln!(
"camera {name} at [{:.3}, {:.3}, {:.3}] moved {:.4} in 1.5s",
ta[0], ta[1], ta[2], moved
"camera m{} at [{:.3}, {:.3}, {:.3}] moved {:.4} in 1.5s",
name, ta[0], ta[1], ta[2], moved
);
assert!(
moved > 0.0,