KAZIK/tools/tests/prepare_world_dressing_probe.py
Игорь Федосеев ca62db53e9 feat: implement native billiards, scratch tickets, first-person dice, and city wake scene
- Billiards: add native Russian Pyramid & American Eight-Ball pool with physics prediction, controls, and regression tests
- Scratch Tickets: add dedicated counter, mat presentation, elliptical coin scraping, 4 ticket types, and payout effects
- First-Person Dice: add native dice scene, hand anchor frames, throwing animation, and table perspective
- City Wake & Weather: add arrival cutscene, alley geometry, weather/rain effects, and lighter/rocker animation
- World Dressing: add hall paintings, furniture packs, hall lighting, and scene regression tests
- Build & Tooling: update build.bat for modern MSVC toolchain, update launcher hash, and refresh shipping binaries
2026-10-16 12:37:40 +03:00

51 lines
2.3 KiB
Python

"""Expose native state in a test-only COFF copy; never patch instructions."""
from pathlib import Path
import struct
from check_card_exit_build import Coff
ROOT = Path(__file__).resolve().parents[2]
EXPOSE = {"casinoMap","hallLevel3D","outdoorRender3D","hallLights3D","hallLoungeDecor3D",
"hallRopeFurniture3D","hallLampFurniture3D","cityObjects3D","hallStreetLife3D","cityDecorPack3D",
"playerX","playerY","playerAngle","viewEye3D","viewCeiling3D","viewHorizon3D",
"worldMap3D","floorTexture3D","cityMap3D","cityPhase3D","cityTime3D","cityClock3D","arrivalState3D",
"screenBuffer","cityDepthBuffer3D","cityRayX3D","cityRayY3D","zBuffer","cityBackdrop3D",
"playerPlaneX","playerPlaneY"}
def main():
out = ROOT/"build/world"
out.mkdir(parents=True,exist_ok=True)
baseline = out/"prior-release.obj"
if not baseline.exists():
baseline.write_bytes((ROOT/"build/actions/actions-test.obj").read_bytes())
coff = Coff(baseline)
original = coff.data
data = bytearray(original)
start = struct.unpack_from("<I",data,8)[0]
changed,found = set(),set()
for index,name in coff.symbols.items():
at = start+index*18
_,section,kind,storage,_ = struct.unpack_from("<IhHBB",data,at+8)
target = None
if name in EXPOSE:
found.add(name)
target = 2
elif name in {"_ResolveCitySurface3D@4","_DrawCityVertical3D@28","_DrawCityHorizontal3D@24"} and kind==0x20 and storage==2 and section>0:
target = 3
if target is not None and target!=storage:
data[at+16] = target
changed.add(at+16)
assert found==EXPOSE,EXPOSE-found
assert {i for i,(a,b) in enumerate(zip(data,original)) if a!=b}==changed
(out/"base.obj").write_bytes(data)
source = (ROOT/"src_graphics/city_bins.inc").read_text(encoding="cp1251")
bodies = []
for name in ("ResolveCitySurface3D","DrawCityVertical3D","DrawCityHorizontal3D"):
body = source.split(name+" PROC",1)[1].split(name+" ENDP",1)[0]
bodies.append(name+" PROC"+body+name+" ENDP\n")
(out/"surfaces.inc").write_text("\n".join(bodies),encoding="ascii")
print("Prepared native renderer probe: storage visibility only, no modified code or relocations")
if __name__=="__main__":
main()