From 6dc017cb3d118b202bd30526383b20b2e9abf227 Mon Sep 17 00:00:00 2001 From: Cyd Date: Thu, 16 Jul 2026 22:35:17 -0500 Subject: [PATCH] THE TEST PATTERN: cap7's bench scene recovered exactly (137 triangles) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tri_recover.py parses each payload's stride-0x10 edge groups {scale,A,B,C} (GOODEQNS edgeize output), solves the three edge equations pairwise into true vertices, and fills the triangles. cap7's bench = a triangulated calibration grid + a multi-part test model + triangle strips, in global screen coords -- the image Division's engineers used to validate VelociRender boards, exact to the compiled coefficients. The earlier 9x5 patch was one corner of this scene. Readout gains §06 (test pattern) with trek/klng scenes moving to §07. The demo captures' streak/point payloads use a different layout (parser refinement pending) -- the bench is pure triangles and recovers perfectly. Co-Authored-By: Claude Opus 4.8 --- emulator/firmware-decomp/render-readout.html | 43 ++++++- emulator/firmware-decomp/tri_recover.py | 112 +++++++++++++++++++ 2 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 emulator/firmware-decomp/tri_recover.py diff --git a/emulator/firmware-decomp/render-readout.html b/emulator/firmware-decomp/render-readout.html index 2ba6bbb..129108a 100644 --- a/emulator/firmware-decomp/render-readout.html +++ b/emulator/firmware-decomp/render-readout.html @@ -362,7 +362,27 @@
-

06 The warp field — a Star Trek scene, recovered

+

06 The test pattern — the bench revealed

+

And the scene this page began with — the test bench that every + cap* capture records — turns out to have been hiding in plain + sight. Walking its DMA chains and solving each primitive's three edge equations + (Ax+By+C, pairwise-intersected into vertices) recovers the whole + thing exactly: 137 triangles — a triangulated calibration grid, a multi-part + test model, and triangle strips along the base. This is the image Division's + engineers used to validate VelociRender boards — reconstructed to the pixel from the + compiled coefficients, thirty years on. The 9×5 patch rendered earlier (§03–05) is one + corner of this scene.

+
+ exact recovery · edge equations solved to vertices + +
the VelociRender test bench — every triangle solved from its + compiled edge equations; colors distinguish primitives (true per-primitive colors live + in the payload's colour planes, still being decoded).
+
+
+ +
+

07 The warp field — a Star Trek scene, recovered

The archive's trek capture — unreleased Star Trek material — replays and draws after the dual-instruction-mode fix. Walking the per-region DMA chains in the bin pages enumerated 898 compiled payload programs for @@ -389,7 +409,7 @@

-

07 What it took to get here

+

08 What it took to get here

The i860 core was corrected against the toolchain's own assembler output and MAME's validated i860 model. A selection of the load-bearing fixes:

@@ -726,6 +746,25 @@ dx.putImageData(img,0,0); })(); + /* ---- the test pattern: exact triangles from solved edge equations ---- */ + var BENCH_TRIS=[[[192.3,86.2],[193.1,84.6],[192.4,84.1]],[[191.5,85.8],[192.3,86.2],[192.4,84.1]],[[192.4,84.1],[193.1,84.6],[195.6,84.1]],[[188.0,87.6],[191.2,86.9],[190.4,86.4]],[[187.2,87.2],[188.0,87.6],[190.4,86.4]],[[191.8,80.7],[192.5,81.2],[192.4,80.1]],[[191.2,86.9],[192.3,86.2],[191.5,85.8]],[[190.4,86.4],[191.2,86.9],[191.5,85.8]],[[190.0,78.9],[187.2,79.1],[188.8,82.1]],[[191.6,82.1],[188.8,82.1],[192.4,84.1]],[[195.6,84.1],[191.8,80.7],[191.6,82.1]],[[190.4,86.4],[188.8,82.1],[185.4,82.6]],[[188.8,82.1],[187.2,79.1],[185.4,82.6]],[[187.2,87.2],[185.4,82.6],[183.4,83.2]],[[187.2,79.1],[184.9,78.9],[185.4,82.6]],[[185.4,82.6],[184.9,78.9],[183.4,83.2]],[[184.9,78.9],[183.5,79.3],[183.4,83.2]],[[183.5,79.3],[181.5,80.9],[180.1,85.2]],[[181.5,80.9],[179.8,83.1],[180.1,85.2]],[[181.9,88.4],[180.1,85.2],[179.3,88.1]],[[179.8,83.1],[178.8,86.9],[180.1,85.2]],[[180.1,85.2],[178.8,87.6],[179.3,88.1]],[[183.4,88.6],[180.1,85.2],[181.9,88.4]],[[183.5,79.3],[180.1,85.2],[183.4,83.2]],[[190.4,86.4],[185.4,82.6],[187.2,87.2]],[[191.5,85.8],[188.8,82.1],[190.4,86.4]],[[192.4,84.1],[188.8,82.1],[191.5,85.8]],[[191.8,80.7],[188.8,82.1],[191.6,82.1]],[[190.0,78.9],[188.8,82.1],[191.8,80.7]],[[191.4,79.2],[190.0,78.9],[191.8,80.7]],[[192.4,80.1],[191.4,79.2],[191.8,80.7]],[[195.6,84.1],[191.6,82.1],[192.4,84.1]],[[196.8,82.6],[191.8,80.7],[195.6,84.1]],[[196.9,81.1],[191.8,80.7],[196.8,82.6]],[[195.8,79.1],[191.8,80.7],[196.9,81.1]],[[187.9,87.9],[187.2,87.2],[183.4,88.6]],[[80.8,80.9],[123.5,88.3],[102.2,84.6]],[[62.2,90.4],[123.5,88.3],[80.8,80.9]],[[31.7,113.2],[-8.1,109.6],[-9.9,72.1]],[[30.8,67.2],[31.7,113.2],[-9.9,72.1]],[[-50.0,-4.2],[30.8,67.2],[-9.9,72.1]],[[-26.2,204.9],[-8.1,109.6],[31.7,113.2]],[[345.1,136.1],[336.3,140.1],[397.3,146.3]],[[387.2,137.6],[345.1,136.1],[397.3,146.3]],[[338.6,133.0],[345.1,136.1],[387.2,137.6]],[[326.3,144.6],[397.3,146.3],[336.3,140.1]],[[331.7,162.6],[361.9,180.8],[310.7,186.4]],[[331.7,162.6],[368.9,158.7],[361.9,180.8]],[[368.9,158.8],[406.8,163.1],[361.9,180.8]],[[329.4,154.1],[368.9,158.8],[331.7,162.6]],[[335.3,29.4],[284.2,29.7],[230.9,29.9]],[[293.4,-46.6],[335.3,29.4],[275.0,-38.6]],[[335.3,29.4],[230.9,29.9],[275.0,-38.6]],[[108.1,104.4],[127.6,108.5],[146.8,112.5]],[[107.8,124.4],[108.1,104.4],[146.8,112.5]],[[482.2,153.8],[383.6,170.3],[486.8,176.7]],[[384.7,146.3],[193.2,130.0],[383.6,170.3]],[[208.3,114.2],[31.8,103.5],[193.2,130.0]],[[65.2,88.1],[9.4,91.8],[31.8,103.5]],[[9.4,91.8],[26.1,76.3],[-13.4,88.2]],[[26.1,76.3],[70.9,60.1],[-13.4,88.2]],[[357.7,63.5],[437.2,66.5],[443.8,36.8]],[[357.7,63.5],[384.7,146.3],[437.2,66.5]],[[273.2,64.7],[357.7,63.5],[311.4,13.1]],[[178.6,69.2],[273.2,64.7],[311.4,13.1]],[[208.3,114.2],[384.7,146.3],[273.2,64.7]],[[108.4,63.9],[178.6,69.2],[202.3,22.2]],[[178.6,69.2],[208.3,114.2],[273.2,64.7]],[[108.4,63.9],[208.3,114.2],[178.6,69.2]],[[46.2,74.4],[108.4,63.9],[83.8,49.8]],[[65.2,88.1],[208.3,114.2],[46.2,74.4]],[[26.1,76.3],[46.2,74.4],[83.8,49.8]],[[482.2,153.8],[384.7,146.3],[383.6,170.3]],[[384.7,146.3],[208.3,114.2],[193.2,130.0]],[[208.3,114.2],[65.2,88.1],[31.8,103.5]],[[65.2,88.1],[26.1,76.3],[9.4,91.8]],[[311.4,13.1],[357.7,63.5],[443.8,36.8]],[[273.2,64.7],[384.7,146.3],[357.7,63.5]],[[202.3,22.2],[178.6,69.2],[311.4,13.1]],[[83.8,49.8],[108.4,63.9],[202.3,22.2]],[[46.2,74.4],[208.3,114.2],[108.4,63.9]],[[26.1,76.3],[65.2,88.1],[46.2,74.4]],[[161.5,38.2],[200.8,95.8],[208.1,50.4]],[[154.5,86.4],[200.8,95.8],[161.5,38.2]],[[154.5,86.4],[195.4,139.6],[200.8,95.8]],[[151.0,132.5],[195.4,139.6],[154.5,86.4]],[[151.0,132.5],[199.1,181.4],[195.4,139.6]],[[150.9,177.4],[199.1,181.4],[151.0,132.5]],[[150.9,177.4],[193.6,224.4],[199.1,181.4]],[[142.4,222.9],[193.6,224.4],[150.9,177.4]],[[142.4,222.9],[190.2,266.5],[193.6,224.4]],[[142.3,267.1],[190.2,266.5],[142.4,222.9]],[[142.3,267.1],[188.4,308.2],[190.2,266.5]],[[137.4,310.6],[188.4,308.2],[142.3,267.1]],[[137.4,310.6],[186.6,349.7],[188.4,308.2]],[[142.4,355.3],[186.6,349.7],[137.4,310.6]],[[142.4,355.3],[197.3,394.0],[186.6,349.7]],[[156.1,403.4],[197.3,394.0],[142.4,355.3]],[[100.6,28.8],[154.5,86.4],[161.5,38.2]],[[95.7,78.6],[154.5,86.4],[100.6,28.8]],[[95.7,78.6],[151.0,132.5],[154.5,86.4]],[[97.3,125.4],[151.0,132.5],[95.7,78.6]],[[97.3,125.4],[150.9,177.4],[151.0,132.5]],[[102.2,172.0],[150.9,177.4],[97.3,125.4]],[[102.2,172.0],[142.4,222.9],[150.9,177.4]],[[100.6,220.1],[142.4,222.9],[102.2,172.0]],[[100.6,220.1],[142.3,267.1],[142.4,222.9]],[[105.6,268.1],[142.3,267.1],[100.6,220.1]],[[105.6,268.1],[137.4,310.6],[142.3,267.1]],[[105.6,316.4],[142.4,355.3],[137.4,310.6]],[[104.0,364.4],[142.4,355.3],[105.6,316.4]],[[104.0,364.4],[156.1,403.4],[142.4,355.3]],[[109.0,414.3],[156.1,403.4],[104.0,364.4]],[[38.6,15.8],[95.7,78.6],[100.6,28.8]],[[35.6,67.8],[95.7,78.6],[38.6,15.8]],[[35.6,67.8],[97.3,125.4],[95.7,78.6]],[[40.2,116.4],[97.3,125.4],[35.6,67.8]],[[40.2,116.4],[102.2,172.0],[97.3,125.4]],[[46.4,165.8],[102.2,172.0],[40.2,116.4]],[[46.4,165.8],[100.6,220.1],[102.2,172.0]],[[49.6,217.0],[100.6,220.1],[46.4,165.8]],[[49.6,217.0],[105.6,268.1],[100.6,220.1]],[[57.8,269.2],[105.6,268.1],[49.6,217.0]],[[57.8,269.2],[346.7,554.7],[57.8,269.3]],[[61.1,322.8],[105.6,316.4],[57.8,269.2]],[[61.1,322.8],[104.0,364.4],[105.6,316.4]],[[59.5,375.8],[104.0,364.4],[61.1,322.8]],[[59.5,375.8],[109.0,414.3],[104.0,364.4]],[[57.8,428.3],[109.0,414.3],[59.5,375.8]],[[-30.9,1.2],[35.6,67.8],[38.6,15.8]],[[-26.9,52.4],[35.6,67.8],[-30.9,1.2]],[[-26.9,52.4],[40.2,116.4],[35.6,67.8]],[[-19.9,103.5],[40.2,116.4],[-26.9,52.4]],[[-19.9,103.5],[46.4,165.8],[40.2,116.4]],[[-14.1,157.3],[46.4,165.8],[-19.9,103.5]],[[-14.1,157.3],[49.6,217.0],[46.4,165.8]],[[-12.7,213.5],[49.6,217.0],[-14.1,157.3]],[[-12.7,213.5],[57.8,269.2],[49.6,217.0]],[[-5.1,270.5],[57.8,269.2],[-12.7,213.5]],[[-5.1,270.5],[61.1,322.8],[57.8,269.2]],[[1.2,329.7],[61.1,322.8],[-5.1,270.5]],[[1.2,329.7],[59.5,375.8],[61.1,322.8]],[[-0.4,388.0],[59.5,375.8],[1.2,329.7]],[[-0.4,388.0],[57.8,428.3],[59.5,375.8]],[[57.8,428.3],[57.7,428.3],[57.7,428.3]],[[289.2,-8.3],[242.4,50.6],[251.8,5.1]],[[280.4,39.3],[242.4,50.6],[289.2,-8.3]],[[280.4,39.3],[235.1,99.5],[242.4,50.6]],[[275.8,91.9],[235.1,99.5],[280.4,39.3]],[[275.8,91.9],[240.1,153.9],[235.1,99.5]],[[275.7,147.4],[240.1,153.9],[275.8,91.9]],[[275.7,147.4],[232.6,205.1],[240.1,153.9]],[[263.7,201.1],[232.6,205.1],[275.7,147.4]],[[263.7,201.1],[227.6,258.6],[232.6,205.1]],[[263.6,258.7],[227.6,258.6],[263.7,201.1]],[[263.6,258.7],[224.8,313.0],[227.6,258.6]],[[256.0,317.6],[224.8,313.0],[263.6,258.7]],[[256.0,317.6],[222.1,368.2],[224.8,313.0]],[[263.7,373.8],[222.1,368.2],[256.0,317.6]],[[263.7,373.8],[237.7,416.3],[222.1,368.2]],[[282.6,421.9],[237.7,416.3],[263.7,373.8]],[[320.6,-33.4],[280.4,39.3],[289.2,-8.3]],[[314.1,19.8],[280.4,39.3],[320.6,-33.4]],[[314.1,19.8],[275.8,91.9],[280.4,39.3]],[[316.3,80.9],[275.8,91.9],[314.1,19.8]],[[316.3,80.9],[275.7,147.4],[275.8,91.9]],[[322.6,142.6],[275.7,147.4],[316.3,80.9]],[[322.6,142.6],[263.7,201.1],[275.7,147.4]],[[320.6,200.3],[263.7,201.1],[322.6,142.6]],[[320.6,200.3],[263.6,258.7],[263.7,201.1]],[[320.6,200.3],[252.1,270.4],[339.0,375.4]],[[256.0,317.6],[256.0,317.6],[256.0,317.6]],[[326.8,315.9],[263.7,373.8],[256.0,317.6]],[[324.9,373.9],[263.7,373.8],[326.8,315.9]],[[324.9,373.9],[282.6,421.9],[263.7,373.8]],[[330.8,427.9],[282.6,421.9],[324.9,373.9]],[[364.4,-56.6],[314.1,19.8],[320.6,-33.4]],[[360.6,2.7],[314.1,19.8],[364.4,-56.6]],[[360.6,2.7],[316.3,80.9],[314.1,19.8]],[[366.5,71.2],[316.3,80.9],[360.6,2.7]],[[366.5,71.2],[322.6,142.6],[316.3,80.9]],[[374.0,137.5],[322.6,142.6],[366.5,71.2]],[[374.0,137.5],[320.6,200.3],[322.6,142.6]],[[377.6,199.1],[320.6,200.3],[374.0,137.5]],[[377.6,199.1],[326.8,258.7],[320.6,200.3]],[[377.6,199.1],[394.5,179.2],[386.1,258.7]],[[389.2,315.5],[326.8,315.9],[386.1,258.7]],[[389.2,315.5],[324.9,373.9],[326.8,315.9]],[[387.7,373.1],[324.9,373.9],[389.2,315.5]],[[387.7,373.1],[330.8,427.9],[324.9,373.9]],[[385.9,431.6],[330.8,427.9],[387.7,373.1]],[[416.0,-83.5],[360.6,2.7],[364.4,-56.6]],[[420.9,-8.1],[360.6,2.7],[416.0,-83.5]],[[420.9,-8.1],[366.5,71.2],[360.6,2.7]],[[428.6,66.6],[366.5,71.2],[420.9,-8.1]],[[428.6,66.6],[374.0,137.5],[366.5,71.2]],[[434.4,134.6],[374.0,137.5],[428.6,66.6]],[[434.4,134.6],[377.6,199.1],[374.0,137.5]],[[435.8,197.2],[377.6,199.1],[434.4,134.6]],[[435.8,197.2],[386.1,258.7],[377.6,199.1]]]; + (function(){ + var bc=document.getElementById('benchframe'); if(!bc) return; + var bx=bc.getContext('2d'); + bx.fillStyle='#06090e'; bx.fillRect(0,0,bc.width,bc.height); + var COLS=['#41ff8e','#5fd0ff','#ffb020','#ff5a6a','#eaffef','#a078ff','#c8c85a','#5ac8a0','#ff8c6e','#78b4e6']; + BENCH_TRIS.forEach(function(t,i){ + bx.fillStyle=COLS[i%COLS.length]; + bx.globalAlpha=0.55; + bx.beginPath(); + bx.moveTo(t[0][0],t[0][1]); bx.lineTo(t[1][0],t[1][1]); bx.lineTo(t[2][0],t[2][1]); + bx.closePath(); bx.fill(); + bx.globalAlpha=0.9; bx.strokeStyle='rgba(234,255,239,0.25)'; bx.lineWidth=0.7; + bx.stroke(); + }); + bx.globalAlpha=1; + })(); + /* ---- the warp field: star positions + streaks recovered from trek's compiled per-primitive payload blocks (screen-space floats) ---- */ var WARP_PTS=[[196.5,174.7],[73.5,277.0],[113.9,474.8],[120.3,347.2],[350.8,358.9],[100.0,438.9],[102.7,474.7],[143.5,56.3],[521.1,111.5],[335.1,400.5],[39.3,353.8],[287.8,323.5],[251.4,554.9],[93.4,246.8],[479.9,300.7],[274.7,347.7],[97.6,465.2],[382.6,241.0],[476.5,80.5],[160.7,418.5],[334.4,218.4],[326.4,553.0],[473.7,587.9],[89.8,371.7],[100.0,127.6],[593.2,335.7],[530.1,583.7],[28.3,420.3],[160.3,499.2],[106.8,237.8],[268.7,370.0],[224.2,219.2],[217.4,448.6],[139.3,256.6],[408.1,493.9],[252.3,282.6],[8.2,586.6],[309.7,583.4],[416.5,337.7],[270.2,215.6],[730.9,473.8],[6.6,364.1],[641.3,69.2],[423.6,565.8],[84.0,313.2],[289.9,488.0],[407.1,350.0],[187.8,61.4],[53.3,340.4],[180.7,406.5],[551.6,104.8],[280.6,464.0],[615.6,412.7],[215.4,192.7],[173.6,99.2],[5.2,313.3],[44.7,238.4],[211.9,472.9],[334.4,52.8],[329.5,248.3],[564.8,232.5],[91.9,450.9],[105.0,2.9],[366.1,113.9],[291.5,368.5],[266.1,254.2],[357.0,201.0],[483.0,174.3],[529.5,34.7],[29.2,240.2],[258.7,12.5],[664.8,238.8],[206.6,337.8],[591.0,419.0],[243.1,220.4],[351.8,300.5],[262.0,390.1],[55.0,544.2],[256.1,200.8],[446.6,434.5],[471.1,416.2],[437.2,124.0],[700.2,381.8],[196.6,277.9],[61.1,316.4],[141.9,576.4],[171.4,516.7],[264.4,444.2],[312.7,574.3],[454.3,345.4],[507.3,547.9],[140.8,301.1],[283.3,140.1],[186.6,218.3],[224.1,2.1],[36.1,331.8],[363.8,257.2],[546.4,375.3],[466.2,493.0],[78.2,307.8],[79.7,550.5],[299.3,277.5],[442.7,267.7],[442.7,461.9],[474.9,543.9],[353.3,177.4],[221.3,526.3],[359.7,381.9],[105.0,343.5],[281.6,194.2],[503.9,422.3],[475.1,407.9],[473.7,203.8],[293.6,222.1],[578.8,352.3],[120.9,577.2],[56.9,442.2],[369.5,368.0],[60.2,123.9],[370.9,394.4],[86.3,262.0],[236.9,166.5],[137.0,257.6],[209.9,572.5],[393.1,74.3],[271.4,289.7],[414.7,560.1],[549.8,156.7],[304.6,466.1],[133.0,385.4],[281.6,586.3],[574.1,124.0],[169.6,193.1],[88.4,388.4],[92.3,136.0],[620.2,559.1],[733.7,173.2],[481.8,247.5],[501.2,277.0],[223.4,494.1],[403.7,264.9],[248.9,259.6],[223.6,480.0],[594.2,446.4],[266.3,327.8],[586.8,101.1],[673.0,67.1],[554.5,550.2],[42.7,265.6],[375.2,209.5],[491.0,344.8],[7.8,453.0],[389.1,316.0],[465.7,535.9],[537.6,388.0],[530.8,525.5],[744.7,353.7],[676.1,184.2],[153.8,173.2],[451.5,351.5],[416.8,254.6],[560.5,219.5],[52.6,530.0],[621.6,126.7],[199.3,329.9],[152.3,351.4],[592.3,315.7],[598.4,280.3],[144.0,322.3],[153.5,243.5],[125.4,55.6],[619.1,78.7],[100.4,531.9],[9.1,480.6],[292.8,556.8],[29.5,360.0],[307.4,512.8],[324.5,487.0],[167.5,137.6],[482.1,263.5],[520.6,496.8],[485.1,154.1],[135.6,371.2],[369.8,262.5],[563.6,425.9],[553.7,379.0],[106.3,54.7],[208.8,176.5],[437.1,272.8],[109.5,345.7],[520.9,318.4],[156.9,539.9],[433.7,196.8],[44.5,384.6],[25.4,484.0],[511.8,511.6],[453.1,564.0],[448.3,534.4],[236.8,369.7],[263.6,435.0],[212.2,514.6],[359.4,390.3],[192.0,508.4],[233.2,595.6],[381.4,294.1],[289.1,136.5],[455.7,97.3],[464.1,116.0],[690.2,174.3],[215.9,547.4],[184.3,568.8],[317.7,567.7],[505.4,469.0],[422.1,347.9],[472.6,235.2],[579.0,277.0],[521.7,5.8],[223.3,204.7],[224.5,474.7],[163.8,563.9],[366.0,373.8],[89.1,234.0],[458.4,488.6],[331.7,375.1],[452.8,7.6],[436.2,67.3],[121.1,284.0],[481.7,496.3],[199.2,393.1],[37.8,220.0],[163.6,158.9],[187.1,566.6],[558.4,441.0],[662.0,418.0],[334.4,472.2],[183.4,226.5],[235.5,181.7],[291.3,471.5],[19.2,330.1],[374.6,15.7],[303.1,571.5],[491.8,420.7],[489.5,238.9],[547.0,253.0],[233.0,326.7],[374.7,258.2],[393.3,364.4],[232.5,311.9],[330.4,318.4],[516.5,335.8],[337.1,120.5],[36.7,362.1],[533.1,404.5],[555.4,109.3],[268.1,158.9],[196.5,482.6],[186.1,390.8],[462.0,245.4],[356.6,92.5],[310.3,495.0],[259.6,551.2],[543.3,503.9],[26.7,164.1],[22.3,470.7],[127.2,351.5],[517.7,240.7],[270.8,130.4],[639.1,187.3],[402.4,535.3],[696.5,169.1],[322.6,117.5],[70.3,238.6],[614.4,332.2],[334.4,29.7],[757.0,62.5],[739.8,538.3],[476.6,198.0],[424.5,142.8],[309.5,247.3],[428.5,237.9],[533.4,482.8],[391.7,585.8],[632.0,315.4],[514.7,334.3],[19.6,367.4],[414.1,537.2],[585.7,354.3],[165.6,485.9],[333.1,286.6],[323.6,590.1],[343.1,33.8],[44.8,484.3],[421.3,313.3],[231.5,68.5],[469.3,517.1],[587.8,421.2],[497.0,338.7],[117.1,462.3],[205.4,228.7],[150.4,372.2],[280.2,372.3],[189.1,20.7],[346.9,274.7],[351.4,254.9],[28.5,361.5],[36.0,137.3],[132.3,353.8],[365.2,304.9],[475.0,404.6],[430.1,308.5],[445.6,59.5],[559.0,428.6],[298.9,154.5],[697.9,179.8],[486.3,300.0],[69.1,103.0],[16.2,178.0],[292.3,34.3],[240.7,179.4],[456.2,421.9],[111.8,58.7],[457.9,556.8],[109.3,447.9],[14.0,589.3],[102.7,52.9],[185.0,431.4],[63.4,273.4],[11.7,523.4],[269.2,572.9],[504.6,393.5],[518.1,512.8],[692.4,139.5],[81.2,467.9],[15.6,511.0],[378.5,33.7],[295.6,52.6],[296.2,167.0],[371.0,586.7],[127.0,531.6],[388.1,564.7],[527.6,595.7],[687.9,404.1],[542.7,367.5],[407.9,458.3],[339.1,550.6],[164.6,509.1],[359.8,569.6],[252.2,420.7],[237.8,198.6],[455.9,65.6],[115.0,475.2],[349.6,36.9],[493.5,242.2],[350.0,141.8],[260.0,470.2],[76.3,453.5],[374.1,195.7],[22.4,205.3],[151.0,227.5],[607.0,135.5],[762.1,310.5],[644.8,242.7],[149.8,287.5],[515.3,71.1],[55.6,441.5],[385.7,484.8],[48.8,292.0],[325.5,86.8],[552.2,12.2],[704.6,509.8],[410.5,309.1],[733.1,162.6],[111.1,13.9],[563.9,335.9],[230.1,100.9],[638.4,308.2],[429.5,533.8],[201.9,237.9],[507.9,523.0],[79.3,333.2],[595.8,557.4],[404.5,528.0],[376.4,368.6],[620.3,70.4],[392.4,595.1],[155.0,380.9],[603.5,350.7],[313.1,510.5],[350.9,149.9],[333.4,543.3],[95.4,425.8],[368.0,544.3],[182.6,323.6],[236.0,472.3],[491.6,533.1],[194.7,521.2],[663.2,445.1],[218.3,312.8],[295.6,467.2],[90.8,561.6],[28.9,416.9],[293.2,27.5],[437.1,386.7],[442.3,360.3],[629.0,202.8],[557.0,129.9],[749.3,177.2],[229.6,277.3],[87.9,439.4],[91.2,275.6],[515.0,390.7],[241.4,465.3],[76.6,582.5],[414.4,346.0],[427.8,427.1],[418.7,207.4],[576.2,356.8],[407.4,95.1],[693.1,84.1],[355.8,53.4],[73.7,344.1],[148.1,447.2],[220.6,22.3],[371.4,413.4],[163.2,400.9],[389.6,210.0],[542.1,334.1],[499.3,116.5],[126.7,567.5],[182.1,321.8],[225.3,271.6],[264.2,231.3],[53.7,376.7]]; diff --git a/emulator/firmware-decomp/tri_recover.py b/emulator/firmware-decomp/tri_recover.py new file mode 100644 index 0000000..3ab2c19 --- /dev/null +++ b/emulator/firmware-decomp/tri_recover.py @@ -0,0 +1,112 @@ +"""EXACT scene recovery: payloads = triangles as 3 edge equations {scale,A,B,C} in +stride-0x10 groups. Solve pairwise intersections -> true vertices; auto-detect +tile-local vs global coords; fill triangles. Usage: tri_recover.py """ +import sys, pickle, struct, collections +S = r'C:\Users\cyd\AppData\Local\Temp\claude\c--VWE-TeslaRel410\4e848c76-6e89-4034-8047-d8d491cb32d8\scratchpad' +dump = sys.argv[1]; outb = sys.argv[2] +mem = pickle.load(open(S + '\\' + dump, 'rb'))['mem'] + +def asf(w): + return struct.unpack('> 23) & 0xff + return 1 < e < 254 and 1e-7 < abs(asf(w)) < 1e7 + +# chains with tile ids +regions = [] +for page in sorted(set(a & ~0xfff for a in mem if 0x0801e000 <= a < 0x08030000)): + sends = []; tile = None + a = page + while a < page + 0x800: + w0 = mem.get(a); w1 = mem.get(a + 4) + if w0 is None or w1 is None: + a += 8; continue + c = (w1 >> 28) & 0xf + if c in (1, 9) and w0 >= 0x08030000: + sends.append((w0, w1 & 0x7f)) + elif c == 2: + tile = w0 + a += 8 + if sends: + regions.append((page, tile, sends)) + +def parse_edges(addr, size): + """Find stride-0x10 groups {scale, A, B, C}: scale small (~1e-3..1e-1), A/B/C larger.""" + edges = [] + off = 0 + while off + 0x10 <= size * 4 + 4: + ws = [mem.get(addr + off + k) for k in (0, 4, 8, 12)] + if all(w is not None and isf(w) for w in ws): + s, A, B, C = (asf(w) for w in ws) + if 1e-4 < abs(s) < 0.1 and (abs(A) > 0.5 or abs(B) > 0.5): + edges.append((A, B, C)) + off += 0x10 + continue + off += 4 + return edges + +def isect(e1, e2): + (a1, b1, c1), (a2, b2, c2) = e1, e2 + d = a1 * b2 - a2 * b1 + if abs(d) < 1e-9: return None + return ((-c1 * b2 + c2 * b1) / d, (-a1 * c2 + a2 * c1) / d) + +tris = [] # (tile, [(x,y)x3]) +for page, tile, sends in regions: + for addr, size in sends: + edges = parse_edges(addr, size) + # group consecutive edge triples into triangles + for k in range(0, len(edges) - 2, 3): + e = edges[k:k+3] + pts = [isect(e[0], e[1]), isect(e[1], e[2]), isect(e[2], e[0])] + if all(p is not None for p in pts): + tris.append((tile, pts)) + +xs = [p[0] for _, ps in tris for p in ps] +ys = [p[1] for _, ps in tris for p in ps] +if not xs: + print("no triangles solved"); sys.exit() +print("triangles: %d vertex range x[%.1f..%.1f] y[%.1f..%.1f]" % + (len(tris), min(xs), max(xs), min(ys), max(ys))) +# auto-detect: if 95% of coords within [−16, 160] treat as tile-local +loc = sum(1 for v in xs + ys if -16 <= v <= 160) / len(xs + ys) +tile_local = loc > 0.9 +print("tile-local coords: %s (%.0f%% in range)" % (tile_local, loc * 100)) + +W, H = 832, 512 +img = [[(6, 9, 14) for _ in range(W)] for _ in range(H)] +PAL = [(65,255,142),(95,208,255),(255,176,32),(255,90,106),(234,255,239), + (160,120,255),(200,200,90),(90,200,160),(255,140,110),(120,180,230)] +def fill_tri(pts, col): + xs_ = [p[0] for p in pts]; ys_ = [p[1] for p in pts] + x0, x1 = max(0, int(min(xs_))), min(W - 1, int(max(xs_)) + 1) + y0, y1 = max(0, int(min(ys_))), min(H - 1, int(max(ys_)) + 1) + if x1 - x0 > 500 or y1 - y0 > 500: return # reject degenerate giants + (ax, ay), (bx, by), (cx, cy) = pts + den = (bx - ax) * (cy - ay) - (cx - ax) * (by - ay) + if abs(den) < 1e-9: return + for y in range(y0, y1 + 1): + for x in range(x0, x1 + 1): + w0 = ((bx - x) * (cy - y) - (cx - x) * (by - y)) / den + w1 = ((cx - x) * (ay - y) - (ax - x) * (cy - y)) / den + w2 = 1 - w0 - w1 + if w0 >= -0.02 and w1 >= -0.02 and w2 >= -0.02: + r0, g0, b0 = img[y][x] + img[y][x] = (min(255, r0 + col[0] // 3), min(255, g0 + col[1] // 3), + min(255, b0 + col[2] // 3)) +drawn = 0 +for i, (tile, pts) in enumerate(tris): + if tile_local and tile is not None: + ox = (tile & 0x1f) * 64; oy = ((tile >> 5) & 0x1f) * 128 + pts = [(p[0] + ox, p[1] + oy) for p in pts] + fill_tri(pts, PAL[i % len(PAL)]) + drawn += 1 +print("drawn:", drawn) +buf = bytearray() +for row in img: + for r, g, b in row: + buf += bytes((r, g, b)) +open(S + '\\' + outb + '.ppm', 'wb').write(b'P6\n%d %d\n255\n' % (W, H) + bytes(buf)) +from PIL import Image +Image.open(S + '\\' + outb + '.ppm').save(S + '\\' + outb + '.png') +print("wrote %s.png" % outb)