Files
lintunes/scripts/kaleidostrobe/golden.py
T
trav e38c751e39 v0.53.0: Kaleidostrobe, the 2002 iTunes visualizer, as the fourth style
Reverse-engineered from its PowerPC binary and checked against the original
running under emulation: textures byte for byte and every triangle, over
3,600 frames. 25 fps like the plugin; its colour maps and wave images are
extracted from its own code; tests/kaleidostrobe_golden.npz was recorded
from the original.
2026-10-14 12:02:22 -07:00

64 lines
2.6 KiB
Python

"""Golden data for tests/test_round84.py, produced by the ORIGINAL plugin
running under emulation (see compare.py / coverage.py)."""
import sys, hashlib, random
sys.path.insert(0, __file__.rsplit('/', 1)[0]); sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parents[2]))
import numpy as np
from plugin import Plugin
import compare
from lintunes.kaleidostrobe import engine as E
def digest(a): return hashlib.sha256(np.ascontiguousarray(a).tobytes()).hexdigest()[:16]
def pattern(seed):
y, x = np.mgrid[0:128, 0:128]
return ((x * (7 + seed) + y * (13 + 2 * seed)) ^ (x * y + seed)).astype(np.uint8)
out = {}
# 1. end to end: 120 frames at 640x480, seed ticks 1000
p = Plugin(rect=(0, 0, 480, 640), ticks=1000)
rnd = random.Random(11)
F = 120
spectra = np.zeros((F, 2, 512), np.uint8); ticks = np.zeros(F, np.int64)
tex_d = []; geo = []; counts = []
t0 = p.k.micro
for f in range(F):
spec = compare.spectra(f, rnd); spectra[f] = spec
start = len(p.k.gl)
p.k.micro += 40001
tk = 1000 + (p.k.micro - t0) * 60 // 1_000_000; ticks[f] = tk
calls = p.frame(None, spec, dt_us=0, dticks=tk - p.k.ticks)
idx = [i for i in range(start, len(p.k.gl)) if p.k.gl[i][0] == '_glTexImage2D']
tex_d.append([digest(np.frombuffer(p.k.textures[i], np.uint8)) for i in idx])
tris = compare.gl_triangles(calls)
counts.append(len(tris))
geo.append(np.array([[(*v[0], *v[1]) for v in t[2]] for t in tris], np.float32))
out['spectra'] = spectra; out['ticks'] = ticks
out['tex_digest'] = np.array(tex_d)
out['tri_counts'] = np.array(counts)
out['tris'] = np.concatenate(geo) # (sum, 3, 5): s, t, x, y, z (eye space)
# 2. every warp, 3 iterations from zeroed counters, layer 1
TEXIDX, CURTEX, CURFRAME = 0x457f8, 0x13dbc, 0x13dc0
k = p.k
dd = []
for n in E.DELTA_TABLE:
k.u.mem_write(0x13b2c, b'\0' * (0x13be4 - 0x13b2c))
row = []
for it in range(3):
src = pattern(n * 3 + it)
k.u.mem_write(TEXIDX + 0x8000, src.tobytes())
k.w32(CURTEX, 1); k.w32(CURFRAME + 4, 1)
k.call(f'_calcDelta{n:03d}')
row.append(digest(np.frombuffer(k.mem(TEXIDX + 0x8000 + 0x4000, 0x4000), np.uint8)))
dd.append(row)
out['delta_digest'] = np.array(dd)
# 3. every wave-table entry, rand seeded 4321
wd = []
for idx in range(len(E.WAVE_TABLE)):
k.rng.srand(4321)
k.w32(CURTEX, 0); k.w32(CURFRAME, 0)
k.call(f'_initWaveShape{E.WAVE_TABLE[idx]:03d}')
wd.append(digest(np.frombuffer(k.mem(TEXIDX, 0x4000), np.uint8)))
out['wave_digest'] = np.array(wd)
np.savez_compressed(sys.argv[1], **out)
print('frames', F, 'triangles', sum(counts), 'beats seen', None)