import sys; 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 from lintunes.kaleidostrobe import engine as E TEXIDX, CURTEX, CURFRAME, WAVEINC = 0x457f8, 0x13dbc, 0x13dc0, 0x257f0 p = Plugin(seed=1); k = p.k rng = np.random.default_rng(3) bad = 0 for n in E.DELTA_TABLE: for tex in (0, 1): state = {} # the emulator's static counters may already have moved during # Plugin(); sync by reading them is fiddly, so zero them first k.u.mem_write(0x13b2c, b'\0' * (0x13be4 - 0x13b2c)) for it in range(4): src = rng.integers(0, 256, (128, 128), dtype=np.uint8) base = TEXIDX + tex * 0x8000 k.u.mem_write(base, src.tobytes()) k.w32(CURTEX, tex); k.w32(CURFRAME + 4 * tex, 1) k.call(f'_calcDelta{n:03d}') theirs = np.frombuffer(k.mem(base + 0x4000, 0x4000), np.uint8).reshape(128, 128) ours = E.delta(n, src, state) d = int((theirs != ours).sum()) if d: bad += 1; print(f'delta {n:03d} tex {tex} iter {it}: {d} differ') print('deltas checked') for seed in (5, 99, 31337): for idx in range(len(E.WAVE_TABLE)): k.rng.srand(seed); r = E.ParkMiller(seed) tex = idx % 2 k.w32(CURTEX, tex); k.w32(CURFRAME + 4 * tex, 0) n = E.WAVE_TABLE[idx] k.call(f'_initWaveShape{n:03d}') theirs = np.frombuffer(k.mem(TEXIDX + tex * 0x8000, 0x4000), np.uint8).reshape(128, 128) eng = E.Kaleidostrobe.__new__(E.Kaleidostrobe) t = E.tables(); eng.waves, eng.wave_inc = t['waves'], t['wave_inc'] eng.rng = r; eng.buffers = np.zeros((2, 2, 128, 128), np.uint8) eng.wave_scale = [0.0, 0.0]; eng.cur_wave = [idx, idx] eng._init_wave(tex) d = int((theirs != eng.buffers[tex, 0]).sum()) inc = k.rf(WAVEINC + 4 * tex) if d or abs(inc - eng.wave_scale[tex]) > 1e-7 or k.rng.x != r.x: bad += 1; print(f'wave {n:03d} seed {seed}: {d} differ, inc {inc} vs {eng.wave_scale[tex]}, rng {k.rng.x == r.x}') print('waves checked; failures:', bad)