Map instance records carry their own length

They are not a fixed 76 bytes. The first int of each record is its length,
and while most placements are 76, every track also has eight of 140, two
of 80 and one of 336 - 560 on Paingod's. Striding a fixed 76 landed
mid-record on those, and hunting forward for the next plausible
quaternion then locked onto arbitrary bytes: that is where the impossible
class ids came from, and the "resource id" 1065353216, which is
0x3F800000 - float 1.0.

Reading the length instead, all eighteen tracks parse to exactly their
declared instance count with no bytes left over. That is the check that
was missing before.

It does not change what gets drawn, because the extra records were never
drawable anyway. It does mean the parse is no longer guessing.
This commit is contained in:
Cyd
2026-08-07 13:23:37 -05:00
parent 4979193528
commit 86bf6a934b
3 changed files with 36 additions and 25 deletions
+13 -13
View File
@@ -312,7 +312,7 @@ h1 em { font-style: normal; color: var(--sys); }
<div><dt>Extent</dt><dd>231 &times; 5708</dd></div>
<div><dt>Relief</dt><dd>90</dd></div>
</dl>
<p class="twin">Same footprint and instance count as -- Wiserguy's --</p><p class="twin">118 of 133 placements are drawn; the rest carry no map art or stand alone off the course</p>
<p class="twin">118 of 133 placements are drawn; the rest carry no map art or stand alone off the course</p>
</div>
</article>
<article class="trk" data-tags="arcade race football" data-search="burnt burnt cookies">
@@ -406,9 +406,9 @@ h1 em { font-style: normal; color: var(--sys); }
<div><dt>Cameras</dt><dd>20</dd></div>
<div><dt>Start boxes</dt><dd>20</dd></div>
<div><dt>Extent</dt><dd>1187 &times; 23298</dd></div>
<div><dt>Relief</dt><dd>415</dd></div>
<div><dt>Relief</dt><dd>627</dd></div>
</dl>
<p class="twin">594 of 607 placements are drawn; the rest carry no map art or stand alone off the course</p>
<p class="twin">595 of 607 placements are drawn; the rest carry no map art or stand alone off the course</p>
</div>
</article>
<article class="trk" data-tags="later race" data-search="donut -- donut --">
@@ -428,7 +428,7 @@ h1 em { font-style: normal; color: var(--sys); }
</div>
</article>
<article class="trk" data-tags="later race" data-search="trough -- ares&#x27; armpits --">
<figure class="plan"><span class="plan__img" role="img" aria-label="-- Ares&#x27; Armpits -- plan view" style="--art:url(data:image/png;base64,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);--ar:41/520"></span><figcaption class="plan__src">Course traced from the gates</figcaption></figure>
<figure class="plan"><span class="plan__img" role="img" aria-label="-- Ares&#x27; Armpits -- plan view" style="--art:url(data:image/png;base64,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);--ar:41/520"></span><figcaption class="plan__src">Course traced from the gates</figcaption></figure>
<div class="trk__body">
<h3>-- Ares&#x27; Armpits --</h3>
<p class="trk__key">trough</p>
@@ -440,7 +440,7 @@ h1 em { font-style: normal; color: var(--sys); }
<div><dt>Extent</dt><dd>322 &times; 9217</dd></div>
<div><dt>Relief</dt><dd>530</dd></div>
</dl>
<p class="twin">580 of 633 placements are drawn; the rest carry no map art or stand alone off the course</p>
<p class="twin">619 of 633 placements are drawn; the rest carry no map art or stand alone off the course</p>
</div>
</article>
<article class="trk" data-tags="later race" data-search="rpweekend2014 -- zaxxis --">
@@ -456,11 +456,11 @@ h1 em { font-style: normal; color: var(--sys); }
<div><dt>Extent</dt><dd>3389 &times; 5959</dd></div>
<div><dt>Relief</dt><dd>266</dd></div>
</dl>
<p class="twin">678 of 695 placements are drawn; the rest carry no map art or stand alone off the course</p>
<p class="twin">683 of 695 placements are drawn; the rest carry no map art or stand alone off the course</p>
</div>
</article>
<article class="trk" data-tags="later race" data-search="wiserguys -- wiserguy&#x27;s --">
<figure class="plan"><span class="plan__img" role="img" aria-label="-- Wiserguy&#x27;s -- plan view" style="--art:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAIICAYAAAAPGuyGAAACIklEQVR42u3dUZKDIAwA0Kbj/a/MXmA7IyImwvOzs1PfmhiBCkRr7ZN5fD/JBwAAQDrg6Pjb3ooVS4WgZYcg/kFEdhK2pwExA/GdkdmzQxB3XoXXVsLIBngYAQAAAJQAxB1PRCEAAHg9YLgWCAEAwBKAoVogBAAAywAu1wIhAAAAAAAAAAAAWBIQGYAyw/WRAWjbJ6EhGp1TAAAAAAAAAAAAAIChvsGr5pj09o7bme7663OgncyJaYD48Vk8mYRDEx6WHB9QipViOQCQCui+E5a7AqmD1eVebE6d9hvqwHaAdrV1JAQzfrjcr1ke27cJ28it6A2KJV5gKHMbpjfJ9n4ce4EBAAAAAKAEwFBtqTEiQzQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7Afae/F5u0ezHJzxGhStgTSoAAAAAAAAAAAAAAAAAgMs95eU2VksDWJNKEpYapJKEKiEAwJ6FyO8F5QApC6NFpSuQsi5ZmZXZ0h/HCpEWEYDesRwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOg6jhu/K4QAAAAAAAAAAAAAAAAAAAAAAADgynFM+t7TW88KAQAAgI1UvpP/+3gS0H3yOwHl1i1/dPuAdvXkdwCGTn4HICrchjGCsZEKAADAH1bvPh9VyhfnAAAAAElFTkSuQmCC);--ar:32/520"></span><figcaption class="plan__src">Course traced from the gates</figcaption></figure>
<figure class="plan"><span class="plan__img" role="img" aria-label="-- Wiserguy&#x27;s -- plan view" style="--art:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAIICAYAAAAPGuyGAAACNklEQVR42u3d2WrEIBQA0NyS//9l+1QohcKo0Wv05HEY4okat7hEKeXKvL6u5AsAAGA7QHWpdg+4+c//4hVJcDc+fTyVFJ/GQFQGEDMyYZn9FsQIRG0MxArlQDwZC68tCSMboDICAAAAAPhbIRVJAACQBYiVYqDIAwAAWYCualkSAABsA2guCyQBAAAAAAAAAADANoCzB6trp3fsnQkjA2CIRu9YEgAAAAAAAAAAAAB0Nc1fs8Kipnv++/fYPg+U3q76iJlUcU1aY/If4szOaWQDFMXvLYoBAEaOFZcjYyB1sHq5ecWpy35DOQAwG1Bam2dbfjk9r1kePU3zUTFQMvKARS5NldGdFbC6YNQAhQkMaQATGAAAAAAAmuuDrWJgqWa5IRoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIDzANaeL5UHpq83jBViwJ5UAAAAAAAAAAAAAAAAAADNPeVtTnZbanygyANHvoa2BVMSegsAANJrQ98LlgOkbIwWLXliy43R0mtD5cCVnQRnHzmtY6J3LBMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvA9wP3ivkAQAAAAAAAAAAAAAAAAAAAAAAAAt1z3ovh9vHSsJAAAAbBf8NfjpYyagOvAnAcsdpDL1+IDSGvgTgK7AnwDECq9h9GCcXwAAAPAN+PtBHnhf+l8AAAAASUVORK5CYII=);--ar:32/520"></span><figcaption class="plan__src">Course traced from the gates</figcaption></figure>
<div class="trk__body">
<h3>-- Wiserguy&#x27;s --</h3>
<p class="trk__key">wiserguys</p>
@@ -469,14 +469,14 @@ h1 em { font-style: normal; color: var(--sys); }
<div><dt>Instances</dt><dd>133</dd></div>
<div><dt>Cameras</dt><dd>16</dd></div>
<div><dt>Start boxes</dt><dd>9</dd></div>
<div><dt>Extent</dt><dd>231 &times; 5708</dd></div>
<div><dt>Relief</dt><dd>138</dd></div>
<div><dt>Extent</dt><dd>1513 &times; 5708</dd></div>
<div><dt>Relief</dt><dd>150</dd></div>
</dl>
<p class="twin">Same footprint and instance count as Wiseguy's Wake</p><p class="twin">117 of 133 placements are drawn; the rest carry no map art or stand alone off the course</p>
<p class="twin">118 of 133 placements are drawn; the rest carry no map art or stand alone off the course</p>
</div>
</article>
<article class="trk" data-tags="later race" data-search="demoderb -- arena (large) --">
<figure class="plan"><span class="plan__img" role="img" aria-label="-- Arena (Large) -- plan view" style="--art:url(data:image/png;base64,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);--ar:520/518"></span><figcaption class="plan__src">Wall blocks &mdash; no single course to trace</figcaption></figure>
<figure class="plan"><span class="plan__img" role="img" aria-label="-- Arena (Large) -- plan view" style="--art:url(data:image/png;base64,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);--ar:520/518"></span><figcaption class="plan__src">Wall blocks &mdash; no single course to trace</figcaption></figure>
<div class="trk__body">
<h3>-- Arena (Large) --</h3>
<p class="trk__key">demoderb</p>
@@ -488,7 +488,7 @@ h1 em { font-style: normal; color: var(--sys); }
<div><dt>Extent</dt><dd>2000 &times; 1995</dd></div>
<div><dt>Relief</dt><dd>0</dd></div>
</dl>
<p class="twin">437 of 455 placements are drawn; the rest carry no map art or stand alone off the course</p>
<p class="twin">443 of 455 placements are drawn; the rest carry no map art or stand alone off the course</p>
</div>
</article>
<article class="trk" data-tags="later race" data-search="arena -- arena (small) --">
@@ -504,7 +504,7 @@ h1 em { font-style: normal; color: var(--sys); }
<div><dt>Extent</dt><dd>1844 &times; 1850</dd></div>
<div><dt>Relief</dt><dd>55</dd></div>
</dl>
<p class="twin">678 of 695 placements are drawn; the rest carry no map art or stand alone off the course</p>
<p class="twin">683 of 695 placements are drawn; the rest carry no map art or stand alone off the course</p>
</div>
</article></div>
<p class="empty-state" id="nomatch" hidden>No track matches that.</p>
File diff suppressed because one or more lines are too long
+22 -11
View File
@@ -83,20 +83,31 @@ def read_gauge_image(res, addr, size):
def instances(res, addr, size, count, gauge_ids):
"""Map instance records: 76 bytes, model gauge-image id at +44,
position at +48, unit quaternion at +60. The quaternion validates the
record; a record whose +44 is not a gauge image is simply not drawn,
exactly as DrawStatic skips it."""
"""Map instance records are variable length and say so: the first int
of a record is its own length in bytes. Resource id at +44, position
at +48, quaternion at +60.
Most records are 76 bytes - a scenery placement - but every track also
carries eight of 140, two of 80 and one of 336 (560 on Paingod's).
Striding a fixed 76 lands mid-record on those, and hunting forward for
the next plausible quaternion then locks onto arbitrary bytes: that is
where the impossible class ids and the "resource id" of 1065353216
came from, which is 0x3F800000, float 1.0. Reading the length instead
makes all eighteen tracks parse to exactly their declared count with
no bytes left over.
A record whose +44 is not a gauge image is not drawn, exactly as
DrawStatic skips an entity with no gauge image."""
out, o, end = [], addr + 4, addr + size
while len(out) < count and o + 76 <= end:
while len(out) < count and o + 8 <= end:
length = struct.unpack_from('<i', res, o)[0]
if not (40 <= length <= 1024) or o + length > end:
break
gid = struct.unpack_from('<i', res, o + 44)[0]
pos = struct.unpack_from('<3f', res, o + 48)
q = struct.unpack_from('<4f', res, o + 60)
if abs(sum(v * v for v in q) - 1.0) < 0.02 and all(abs(v) < 1e5 for v in pos):
gid = struct.unpack_from('<i', res, o + 44)[0]
out.append((gid if gid in gauge_ids else None, pos, q))
o += 76
else:
o += 4
out.append((gid if gid in gauge_ids else None, pos, q))
o += length
return out