diff --git a/emulator/firmware-decomp/igc_array.py b/emulator/firmware-decomp/igc_array.py index 994d6de..a02b01b 100644 --- a/emulator/firmware-decomp/igc_array.py +++ b/emulator/firmware-decomp/igc_array.py @@ -161,6 +161,44 @@ class IGCArray: _wword(pix, G_BIT0, C_BITS, gv) _wword(pix, B_BIT0, C_BITS, bv) + def readout_depth(self, bg=(7, 11, 17)): + """Read the 24-bit z stored in pixel memory back into a depth image (near=bright). + This is the plane the SENDE z-sweep interpolates, straight out of pixel memory.""" + img = bytearray(self.W * self.H * 3) + for y in range(self.H): + o = y * self.W * 3 + for x in range(self.W): + img[o] = bg[0]; img[o + 1] = bg[1]; img[o + 2] = bg[2]; o += 3 + # gather the touched z range for contrast + zmin, zmax = Z_FAR, 0 + for t in self.tiles.values(): + if not t.touched: + continue + for pix in t.mem: + z = _rword(pix, Z_BIT0, Z_BITS) + if z != Z_FAR: + zmin = min(zmin, z); zmax = max(zmax, z) + span = (zmax - zmin) or 1 + for (tx, ty), t in self.tiles.items(): + if not t.touched: + continue + for ly in range(TILE_Y): + gy = t.y0 + ly + if gy >= self.H: + break + base = ly << TILE_X_BITS + for lx in range(TILE_X): + gx = t.x0 + lx + if gx >= self.W: + break + z = _rword(t.mem[base + lx], Z_BIT0, Z_BITS) + if z == Z_FAR: + continue + v = 1.0 - (z - zmin) / span # near = bright + o = (gy * self.W + gx) * 3 + img[o] = int(30 + v * 120); img[o + 1] = int(90 + v * 150); img[o + 2] = int(120 + v * 130) + return img + def readout(self, bg=(7, 11, 17)): """Read pixel memory back out into an RGB framebuffer (row-major, RGB bytes).""" img = bytearray(self.W * self.H * 3) diff --git a/emulator/firmware-decomp/render-readout.html b/emulator/firmware-decomp/render-readout.html index dc200fb..a3c3257 100644 --- a/emulator/firmware-decomp/render-readout.html +++ b/emulator/firmware-decomp/render-readout.html @@ -323,32 +323,37 @@ reference rasteriser to within edge anti-aliasing — the array reproduced faithfully.
What this is not, yet: execution of the compiled - micro-code the DMA actually ships (§02, right) — the form the ground and sky take, since - they carry no stored vertices. That stream is now partly decoded: the per-region command lists - read cleanly, and the SEND payloads turn out to carry the real float coefficients - interleaved with a regular bit-serial sweep — so what remains is pinning the control-word fields - and running that sweep, not reversing an opaque binary. This section is the array's - computational model: the pixels that micro-code produces.
+What this is not, yet: a full from-scratch run of + the compiled micro-code the DMA ships (§02) — the form the ground and sky take, since they + carry no stored vertices. But that stream is now largely decoded: the command lists read cleanly, + the SENDE z-sweep resolves into a regular 4-word instruction, and its + coefficients are the same ones driving this depth buffer — the array's inputs are + cross-validated against the hardware's own compiled stream. What remains is numeric + reconstruction across every region, not reversing an opaque binary.