- 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
46 lines
1.9 KiB
Python
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()
|