- 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
47 lines
2 KiB
Python
47 lines
2 KiB
Python
"""Expose native helpers in a test-only COFF copy, without patching instructions."""
|
|
from pathlib import Path
|
|
import re
|
|
import struct
|
|
from check_card_exit_build import Coff
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
EXPOSE = {"engineMode", "deltaTime3D", "mouseClick3D", "mouseX3D", "mouseY3D",
|
|
"keys3D", "pressedKeys3D", "tableCos", "tableSin", "screenBuffer",
|
|
"cardExitButton3D", "unavailableText3D", "bankroll", "rngSeed3D"}
|
|
|
|
|
|
def main():
|
|
folder = ROOT / "build/billiards"
|
|
folder.mkdir(exist_ok=True)
|
|
functions = set()
|
|
for name in ("billiards", "pyramid_rules", "eightball", "pyramid_play", "billiards_prediction", "pyramid_render"):
|
|
source = (ROOT / "src_graphics" / (name + ".inc")).read_text(encoding="cp1251")
|
|
functions.update(re.findall(r"^(\w+) PROC", source, re.M))
|
|
for name in ("pyramid_test", "billiards_choice_test", "eightball_regression"):
|
|
source = (ROOT / "tools/tests" / (name + ".inc")).read_text(encoding="cp1251")
|
|
functions.update(re.findall(r"^(\w+) PROC", source, re.M))
|
|
coff = Coff(ROOT / "build/actions/actions-test.obj")
|
|
original = coff.data
|
|
data = bytearray(original)
|
|
start = struct.unpack_from("<I", data, 8)[0]
|
|
found, changes = 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.startswith("_") and name[1:].split("@")[0] in functions and kind == 0x20 and section > 0:
|
|
target = 3
|
|
if target is not None and target != storage:
|
|
data[at+16] = target
|
|
changes.add(at+16)
|
|
assert found == EXPOSE, EXPOSE-found
|
|
assert {i for i, (a, b) in enumerate(zip(original, data)) if a != b} == changes
|
|
(folder / "helpers.obj").write_bytes(data)
|
|
print("Prepared test-only native helpers; only COFF visibility bytes changed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|