"""Verification test suite for the Jukebox / Jackbox music system.""" import ctypes from pathlib import Path import re import struct ROOT = Path(__file__).resolve().parents[2] def test_packed_assets(): world_bin = ROOT / "assets/animations/hall/jackbox-v1.bin" ui_bin = ROOT / "assets/animations/hall/jackbox-ui-v1.bin" assert world_bin.is_file(), f"Missing {world_bin}" assert ui_bin.is_file(), f"Missing {ui_bin}" # Check world bin header: ANM1, 256, 512, 3 frames wdata = world_bin.read_bytes() magic, w, h, frames, raw_len = struct.unpack("<4s4I", wdata[:20]) assert magic == b"ANM1", f"Bad magic: {magic}" assert (w, h, frames) == (256, 512, 3), f"Bad dimensions: {w}x{h}, {frames} frames" assert len(wdata) == 20 + raw_len == 20 + 256 * 512 * 4 * 3 print(f"[OK] jackbox-v1.bin verified: {frames} frames ({w}x{h}), {raw_len} bytes") # Check UI bin header: ANM1, 640, 480, 1 frame uidata = ui_bin.read_bytes() magic, w, h, frames, raw_len = struct.unpack("<4s4I", uidata[:20]) assert magic == b"ANM1", f"Bad magic: {magic}" assert (w, h, frames) == (640, 480, 1), f"Bad dimensions: {w}x{h}, {frames} frames" assert len(uidata) == 20 + raw_len == 20 + 640 * 480 * 4 print(f"[OK] jackbox-ui-v1.bin verified: {frames} frame ({w}x{h}), {raw_len} bytes") def test_audio_tracks(): data_inc = (ROOT / "src_graphics/jackbox_data.inc").read_bytes().decode("cp1251") open_cmds = re.findall(r'open\s+"([^"]+)"\s+type\s+(\w+)\s+alias\s+jboxmusic', data_inc) assert len(open_cmds) == 2, f"Expected 2 audio tracks, got {len(open_cmds)}" for rel_path, media_type in open_cmds: assert "assets\\music\\jackbox" in rel_path or "assets/music/jackbox" in rel_path, f"Track must be from jackbox directory: {rel_path}" for rel_path, media_type in open_cmds: full_path = ROOT / rel_path assert full_path.is_file(), f"Audio file missing: {rel_path}" # Test MCI open & close cmd_open = f'open "{full_path}" type {media_type} alias testjbox' err = ctypes.windll.winmm.mciSendStringW(cmd_open, None, 0, None) assert err == 0, f"MCI failed to open {rel_path}: error {err}" try: length_buf = ctypes.create_unicode_buffer(64) err = ctypes.windll.winmm.mciSendStringW("status testjbox length", length_buf, 64, None) assert err == 0, f"MCI failed to query length of {rel_path}" finally: ctypes.windll.winmm.mciSendStringW("close testjbox", None, 0, None) print(f"[OK] MCI verified track: {rel_path} ({media_type})") def test_code_structure(): data_inc = (ROOT / "src_graphics/jackbox_data.inc").read_bytes().decode("cp1251") code_inc = (ROOT / "src_graphics/jackbox.inc").read_bytes().decode("cp1251") casino_inc = (ROOT / "casino3d.inc").read_bytes().decode("cp1251") hall_inc = (ROOT / "src_graphics/hall_scene.inc").read_bytes().decode("cp1251") world_inc = (ROOT / "src_graphics/world_dressing.inc").read_bytes().decode("cp1251") city_inc = (ROOT / "src_graphics/city_bins.inc").read_bytes().decode("cp1251") # Check constants assert "MODE_JACKBOX equ 28" in data_inc assert "INTERACT_JACKBOX equ 48" in data_inc assert "JACKBOX_X equ FP_1*306/10" in data_inc assert "JACKBOX_Y equ FP_1*235/10" in data_inc assert "MATERIAL_JACKBOX_SIDE equ 121" in data_inc assert "MATERIAL_JACKBOX_BACK equ 163" in data_inc # Check procs procs = [ "LoadJackboxArt3D", "FreeJackboxArt3D", "ResolveJackboxSurface3D", "DrawJackboxCabinet3D", "RenderJackboxCabinet3D", "JackboxCanWalk3D", "PlayJukeboxTrack3D", "StopJukeboxTrack3D", "BeginJackbox3D", "HandleJackbox3D", "RenderJackbox3D", "CalculateJukeboxFalloff", "UpdateJukeboxAudio3D", "HandleJukeboxKeys3D", "RenderJukeboxVolumeHUD" ] for p in procs: assert f"{p} PROC" in code_inc, f"Missing proc: {p}" # Check integrations assert "include src_graphics\\jackbox_data.inc" in casino_inc assert "include src_graphics\\jackbox.inc" in casino_inc assert "MODE_JACKBOX" in casino_inc assert "HandleJackbox3D" in casino_inc assert "RenderJackbox3D" in casino_inc assert "call HandleJukeboxKeys3D" in casino_inc assert "call UpdateJukeboxAudio3D" in casino_inc assert "call RenderJukeboxVolumeHUD" in casino_inc assert "jboxUserVolume dd" in data_inc assert "setaudio jboxmusic volume to" in data_inc assert "call LoadJackboxArt3D" in world_inc assert "call FreeJackboxArt3D" in world_inc assert "call RenderJackboxCabinet3D" in world_inc assert "INTERACT_JACKBOX" in hall_inc assert "BeginJackbox3D" in hall_inc assert "JackboxCanWalk3D" in hall_inc assert "ResolveJackboxSurface3D" in city_inc print("[OK] Code structure and all integrations verified.") def test_binary_executable(): exe_path = ROOT / "poker.exe" assert exe_path.is_file() exe_bytes = exe_path.read_bytes() assert b"jackbox-v1.bin" in exe_bytes assert b"jackbox-ui-v1.bin" in exe_bytes assert b"jboxmusic" in exe_bytes print(f"[OK] poker.exe verified with embedded Jackbox strings ({len(exe_bytes)} bytes).") if __name__ == "__main__": test_packed_assets() test_audio_tracks() test_code_structure() test_binary_executable() print("\nALL JACKBOX / JUKEBOX VERIFICATION CHECKS PASSED!")