mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-31 12:05:05 +02:00
The 1987 DOS toolchain (GSPA/GSPLNK/GSPROM) runs under DOSBox and reassembles 32 KB of the v2.2 ROM byte-for-byte after five documented fixups to smart34010 output. The 1990 r5.01 tools are OS/2 NE and do not run in DOS. Adds the converter, round-trip script, and the DOSBox/dosemu benchmark.
104 lines
3.7 KiB
Python
104 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""DOSBox vs dosemu on the real workload: GSPA assembling TMS34010 source.
|
|
|
|
Workload A: gspa t1 t1.obj t1.lst -l (4 KB region, listing)
|
|
Workload B: gspa -q rt16 rt16.obj (16 KB region, no listing)
|
|
|
|
Both headless: DOSBox with SDL dummy drivers and core=dynamic/cycles=max;
|
|
dosemu in -t (terminal/S-Lang) mode. Three measured runs each, plus one
|
|
warm-up. Raw COFF md5 differs only in the 4-byte time stamp, so a
|
|
timestamp-normalised md5 is also reported.
|
|
"""
|
|
import hashlib
|
|
import os
|
|
import statistics
|
|
import subprocess
|
|
import time
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent
|
|
BENCH = ROOT / "bench"
|
|
DHOME = ROOT / "dosemu-home"
|
|
DBENCH = DHOME / ".dosemu" / "drive_c" / "bench"
|
|
RUNS = 3
|
|
|
|
|
|
def norm_md5(p):
|
|
if not p.exists():
|
|
return "-"
|
|
b = bytearray(p.read_bytes())
|
|
if len(b) >= 8:
|
|
b[4:8] = b"\0\0\0\0"
|
|
return hashlib.md5(bytes(b)).hexdigest()
|
|
|
|
|
|
def raw_md5(p):
|
|
return hashlib.md5(p.read_bytes()).hexdigest() if p.exists() else "-"
|
|
|
|
|
|
def clean(d, base):
|
|
for name in (base + ".OBJ", base + ".LST", "MACLIB.$$$",
|
|
base.lower() + ".obj", base.lower() + ".lst", "maclib.$$$"):
|
|
f = d / name
|
|
if f.exists():
|
|
f.unlink()
|
|
|
|
|
|
def run_dosbox(base, args):
|
|
clean(BENCH, base)
|
|
cmds = []
|
|
for _ in range(1):
|
|
cmds += ["-c", "gspa " + args]
|
|
env = dict(os.environ, SDL_VIDEODRIVER="dummy", SDL_AUDIODRIVER="dummy")
|
|
t0 = time.perf_counter()
|
|
rc = subprocess.run(
|
|
["timeout", "120", "dosbox", "-conf", str(ROOT / "dosbox-bench.conf"),
|
|
"-noprimaryconf", "-nolocalconf",
|
|
"-c", "mount c " + str(BENCH), "-c", "c:"] + cmds +
|
|
["-c", "exit", "-exit"],
|
|
env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode
|
|
dt = time.perf_counter() - t0
|
|
# DOSBox uppercases 8.3 names
|
|
obj = BENCH / (base.upper() + ".OBJ")
|
|
return dt, rc, raw_md5(obj), norm_md5(obj), obj.stat().st_size if obj.exists() else 0
|
|
|
|
|
|
def run_dosemu(base, args, bat):
|
|
clean(DBENCH, base)
|
|
script = "@echo off\r\nc:\r\ncd \\bench\r\ngspa %s\r\nexitemu\r\n" % args
|
|
(DBENCH / bat).write_bytes(script.encode())
|
|
env = dict(os.environ, HOME=str(DHOME))
|
|
t0 = time.perf_counter()
|
|
rc = subprocess.run(
|
|
["timeout", "120", "dosemu", "-t", "-quiet", "-E", r"c:\bench" + "\\" + bat],
|
|
env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode
|
|
dt = time.perf_counter() - t0
|
|
# dosemu/lredir keeps the lowercase names written by FreeCom
|
|
obj = DBENCH / (base.lower() + ".obj")
|
|
if not obj.exists():
|
|
obj = DBENCH / (base.upper() + ".OBJ")
|
|
return dt, rc, raw_md5(obj), norm_md5(obj), obj.stat().st_size if obj.exists() else 0
|
|
|
|
|
|
def bench(name, base, args, bat):
|
|
print("\n== %s == gspa %s" % (name, args))
|
|
run_dosbox(base, args) # warm-up
|
|
run_dosemu(base, args, bat)
|
|
results = {}
|
|
for label, fn in (("dosbox", lambda: run_dosbox(base, args)),
|
|
("dosemu", lambda: run_dosemu(base, args, bat))):
|
|
rows = [fn() for _ in range(RUNS)]
|
|
results[label] = rows
|
|
for dt, rc, raw, norm, size in rows:
|
|
print(" %-7s %6.2fs rc=%d size=%d raw=%s norm=%s" %
|
|
(label, dt, rc, size, raw[:8], norm[:8]))
|
|
print(" %-7s median %.2fs" % (label, statistics.median(r[0] for r in rows)))
|
|
n0 = {r[3] for r in results["dosbox"]}
|
|
n1 = {r[3] for r in results["dosemu"]}
|
|
print(" normalised object identical: %s (%s)" % (n0 == n1 and len(n0) == 1, n0))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
bench("A: 4 KB with listing", "t1", "t1 t1.obj t1.lst -l", "bench.bat")
|
|
bench("B: 16 KB, no listing", "rt16", "-q rt16 rt16.obj", "bench16.bat")
|