#!/usr/bin/env python3 # traceRun.py - run the game under VICE (NTSC) to $0800, then enable an exec tracepoint over the # whole RAM range and collect every executed PC for a wall-clock budget; write a coverage file. import socket, subprocess, sys, time, os, re sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from viceDriver import pickFreePort, recvUntilPrompt, SCRATCH def main(): disk = os.path.abspath(sys.argv[1]) budget = int(sys.argv[2]) outName = sys.argv[3] port = pickFreePort() cmd = ["xvfb-run", "-a", "x64sc", "-remotemonitor", "-remotemonitoraddress", f"127.0.0.1:{port}", "-drive8truedrive", "-drive8type", "1541", "-sounddev", "dummy", "-warp", "-jamaction", "2", "-autostart-warp", "-model", "ntsc", "-chdir", SCRATCH, "-autostart", disk] proc = subprocess.Popen(cmd, stdout=open(f"{SCRATCH}/trace_stdout.txt", "w"), stderr=subprocess.STDOUT) sock = None for _ in range(100): try: sock = socket.create_connection(("127.0.0.1", port), timeout=1); break except OSError: time.sleep(0.3) print(recvUntilPrompt(sock, 10)) sock.sendall(b"break 0800\n"); print(recvUntilPrompt(sock, 10)) sock.sendall(b"x\n"); print(recvUntilPrompt(sock, 300)) sock.sendall(b"del\n"); print(recvUntilPrompt(sock, 10)) sock.sendall(b"tr exec 0000 ffff\n"); print(recvUntilPrompt(sock, 10)) sock.sendall(b"x\n") pcs = {} buf = b"" deadline = time.time() + budget sock.settimeout(1.0) total = 0 rx = re.compile(rb"\.C:([0-9a-f]{4})") while time.time() < deadline: try: chunk = sock.recv(1 << 20) if not chunk: break total += len(chunk) buf += chunk lines = buf.split(b"\n") buf = lines[-1] for ln in lines[:-1]: m = rx.search(ln) if m: pc = int(m.group(1), 16) pcs[pc] = pcs.get(pc, 0) + 1 except socket.timeout: pass with open(f"{SCRATCH}/{outName}", "w") as f: for pc in sorted(pcs): f.write(f"{pc:04X} {pcs[pc]}\n") print(f"bytes received {total}, distinct PCs {len(pcs)}") try: sock.sendall(b"\n") time.sleep(0.5) sock.sendall(b"quit\n") except OSError: pass time.sleep(1) proc.kill(); proc.wait() main()