KAZIK/tools/tests/prepare_scratch_module.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

46 lines
1.9 KiB
Python

"""Link fresh scratch MASM against existing native graphics helpers for fast QA.
Only COFF symbol visibility changes in a test-only COPY. Instructions and
relocations remain untouched; neither shipping binaries nor source are patched.
The full engine is rebuilt/tested separately before publication.
"""
from pathlib import Path
import struct
from check_card_exit_build import Coff
ROOT = Path(__file__).resolve().parents[2]
EXPOSE = {"engineMode","paused3D","bankroll","deltaTime3D","animationClock3D",
"viewWidth3D","viewHeight3D","viewLeft3D","viewTop3D","clpSymbolsPath3D",
"coinExitText3D","coinBankText3D","hudNumBuffer","screenBuffer","rngSeed3D","h3DWnd","lastSoundPath3D"}
def main():
coff = Coff(ROOT/"build/actions/actions-test.obj")
original = coff.data
data = bytearray(original)
symbols = struct.unpack_from("<I",data,8)[0]
touched,exposed = set(),set()
for index,name in coff.symbols.items():
at = symbols+18*index
value,section,kind,storage,aux = struct.unpack_from("<IhHBB",data,at+8)
target = None
if name in EXPOSE:
assert section>0
exposed.add(name)
target = 2
elif ("Scratch" in name or name=="_LoadAnimPack3D@8") and kind==0x20 and storage==2 and section>0:
target = 3
if target is not None and storage!=target:
data[at+16] = target
touched.add(at+16)
assert exposed==EXPOSE,EXPOSE-exposed
assert {i for i,(a,b) in enumerate(zip(original,data)) if a!=b}==touched
(ROOT/"build/scratch/module-base.obj").write_bytes(data)
loader = (ROOT/"src_graphics/scene_animation.inc").read_text(encoding="cp1251")
loader = loader.split("LoadAnimPack3D ENDP",1)[0]+"LoadAnimPack3D ENDP\n"
(ROOT/"build/scratch/module-loader.inc").write_text(loader,encoding="ascii")
print("Prepared test-only native helper object; all code and relocations unchanged")
if __name__=="__main__":
main()