Back to Supersonic RC Revive
SOURCE / PINNED RELEASE

Made of little things.

Supersonic RC Revive

Release
1ba42f1ca1d6…
Author-recorded commit
baecad10b1cd…
License
LICENSE
Author’s source reference
nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.napplet.soy%2F/n-143146b0d6f

Archive hash verified: 90d22b206672eba4…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

tools/sim/make_logger_wrapper.py
#!/usr/bin/env python3
"""Build an instrumented copy of the original wrapper movie (dev-only).

The wrapper compiles member("closeScript").text into a movie script inside
game.dcr at startup. This replaces that text with the original closeRequest
handler plus an idle-time logger that records the car's Havok state each new
simTime and flushes it with setPref() (ssrc0.txt, ssrc1.txt, ... in the
projector's Prefs folder). Writes to the given output path only; ref/ is never
modified.

    python3 tools/sim/make_logger_wrapper.py <wine-copy>/wrapper_SupersonicRC.dir
"""
import os
import struct
import sys

ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
SRC = os.path.join(ROOT, "ref", "SuperSonicRC", "wrapper_SupersonicRC.dir")

LINGO = r'''on closeRequest me
  if keyPressed(53) = 0 then
    quit()
  end if
end

on idle
  ssrcTick()
end

on ssrcTick
  global gMainManager, gSSRCBuf, gSSRCPart, gSSRCFlush, gSSRCSim
  if voidp(gSSRCPart) then
    gSSRCPart = 0
    gSSRCBuf = ""
    gSSRCFlush = the milliSeconds
    gSSRCSim = -1
    the floatPrecision = 6
  end if
  if ilk(gMainManager) = #instance then
    tDM = gMainManager.getDrivingManager()
    if ilk(tDM) = #instance then
      tCar = tDM.getCar()
      if ilk(tCar) = #instance then
        tRB = tCar.getRB()
        tSim = tDM.getHavokManager().getSimTime()
        if tSim <> gSSRCSim then
          gSSRCSim = tSim
          ssrcExperiment(tDM, tRB, tSim)
          tP = tRB.position
          tR = tRB.rotation
          tV = tRB.linearVelocity
          tA = tRB.angularVelocity
          tL = the milliSeconds && tSim && tP.x && tP.y && tP.z && tR[1].x && tR[1].y && tR[1].z && tR[2] && tV.x && tV.y && tV.z && tA.x && tA.y && tA.z
          repeat with tW in tCar.getWheels()
            tL = tL && tW.pOnGround && tW.pSpringLength && tW.pRotation
          end repeat
          tL = tL && keyPressed(126) && keyPressed(125) && keyPressed(123) && keyPressed(124) && keyPressed(" ") && tCar.pSkidding
          tC = tRB.centerOfMass
          tL = tL && tC.x && tC.y && tC.z && tRB.mass
          repeat with tW in tCar.getWheels()
            tS = tW.pSpeed
            if ilk(tS) = #vector then
              tL = tL && tW.pLoad && tS.x && tS.y && tS.z
            else
              tL = tL && 0 && 0 && 0 && 0
            end if
          end repeat
          gSSRCBuf = gSSRCBuf & tL & RETURN
        end if
      end if
    end if
  end if
  if the milliSeconds - gSSRCFlush > 1000 then
    if gSSRCBuf <> "" then
      setPref("ssrc" & gSSRCPart, gSSRCBuf)
      gSSRCPart = gSSRCPart + 1
      gSSRCBuf = ""
    end if
    gSSRCFlush = the milliSeconds
  end if
end

-- SSRC_EXPERIMENTS: scripted drop tests. Each sets the car's state between
-- frames, drops the forces already queued for the next step, and logs a marker.
on ssrcExperiment tDM, tRB, tSim
  global gSSRCBuf, gSSRCExp
  if voidp(gSSRCExp) then gSSRCExp = 0
  tList = @@EXPERIMENTS@@
  if gSSRCExp >= tList.count then exit
  tE = tList[gSSRCExp + 1]
  if tSim < tE[1] then exit
  gSSRCExp = gSSRCExp + 1
  tHM = tDM.getHavokManager()
  tHM.pForcesOnPoint.deleteAll()
  tHM.pForces.deleteAll()
  tRB.position = tE[2]
  tRB.rotation = [tE[3], tE[4]]
  tRB.linearVelocity = tE[5]
  tRB.angularVelocity = vector(0, 0, 0)
  tH = member("havok")
  gSSRCBuf = gSSRCBuf & "EXP" && gSSRCExp && tSim && tH.tolerance && tH.scale && tRB.friction && tRB.restitution && tRB.mass & RETURN
end
'''


def main():
    out = sys.argv[1]
    data = bytearray(open(SRC, "rb").read())
    assert data[:4] == b"XFIR"
    # mmap entry 14 is the closeScript STXT (see ProjectorRays mmap dump).
    mmap_entries = 44 + 8 + 24
    entry = mmap_entries + 14 * 20
    assert data[entry:entry + 4] == b"TXTS"
    old_len, old_off = struct.unpack_from("<II", data, entry + 4)
    old = bytes(data[old_off + 8:old_off + 8 + old_len])
    hdr, tlen, flen = struct.unpack_from(">III", old, 0)
    fmt = old[hdr + tlen:hdr + tlen + flen]
    lingo = LINGO.replace("@@EXPERIMENTS@@", os.environ.get("SSRC_EXPERIMENTS", "[]"))
    text = lingo.replace("\n", "\r").encode("latin1")
    payload = struct.pack(">III", 12, len(text), len(fmt)) + text + fmt
    while len(data) % 2 or len(data) < struct.unpack_from("<I", data, 4)[0] + 8:
        data += b"\0"  # the shipped file is one byte short of its RIFX length
    new_off = len(data)
    data += b"TXTS" + struct.pack("<I", len(payload)) + payload
    if len(payload) % 2:
        data += b"\0"
    struct.pack_into("<II", data, entry + 4, len(payload), new_off)
    struct.pack_into("<I", data, 4, len(data) - 8)
    struct.pack_into("<I", data, mmap_entries + 4, len(data) - 8)
    open(out, "wb").write(data)
    print(f"wrote {out}: closeScript {old_len} -> {len(payload)} bytes at {new_off}")


if __name__ == "__main__":
    main()