From e38c751e3981900a2d8863854d678dbdeddee438 Mon Sep 17 00:00:00 2001 From: trav Date: Wed, 14 Oct 2026 12:02:22 -0700 Subject: [PATCH] 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. --- CLAUDE.md | 28 ++ lintunes/__init__.py | 2 +- lintunes/gui/preferences_dialog.py | 12 + lintunes/gui/visualizer.py | 3 + lintunes/gui/visualizer_kaleido.py | 198 ++++++++ lintunes/gui/visualizer_styles.py | 8 +- lintunes/kaleidostrobe/__init__.py | 2 + lintunes/kaleidostrobe/engine.py | 706 +++++++++++++++++++++++++++++ lintunes/kaleidostrobe/tables.npz | Bin 0 -> 112292 bytes lintunes/preferences.py | 2 +- scripts/kaleidostrobe/README.md | 21 + scripts/kaleidostrobe/compare.py | 107 +++++ scripts/kaleidostrobe/coverage.py | 45 ++ scripts/kaleidostrobe/emu.py | 253 +++++++++++ scripts/kaleidostrobe/extract.py | 85 ++++ scripts/kaleidostrobe/golden.py | 63 +++ scripts/kaleidostrobe/macho.py | 188 ++++++++ scripts/kaleidostrobe/plugin.py | 68 +++ setup.py | 1 + tests/kaleidostrobe_golden.npz | Bin 0 -> 92947 bytes tests/test_round84.py | 320 +++++++++++++ 21 files changed, 2109 insertions(+), 3 deletions(-) create mode 100644 lintunes/gui/visualizer_kaleido.py create mode 100644 lintunes/kaleidostrobe/__init__.py create mode 100644 lintunes/kaleidostrobe/engine.py create mode 100644 lintunes/kaleidostrobe/tables.npz create mode 100644 scripts/kaleidostrobe/README.md create mode 100644 scripts/kaleidostrobe/compare.py create mode 100644 scripts/kaleidostrobe/coverage.py create mode 100644 scripts/kaleidostrobe/emu.py create mode 100644 scripts/kaleidostrobe/extract.py create mode 100644 scripts/kaleidostrobe/golden.py create mode 100644 scripts/kaleidostrobe/macho.py create mode 100644 scripts/kaleidostrobe/plugin.py create mode 100644 tests/kaleidostrobe_golden.npz create mode 100644 tests/test_round84.py diff --git a/CLAUDE.md b/CLAUDE.md index a7ae6fb..1867947 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -258,6 +258,34 @@ persistence) → GUI (Qt widgets that read the manager and connect to its signal `highlight_palette` overrides a slot, and `theme.highlight_color` reads through `theme.highlight_palette`, so nothing else needs to know. +- **`lintunes/kaleidostrobe/`** + **`gui/visualizer_kaleido.py`** — the + fourth visualizer style (Round 84): Kaleidostrobe, the 2002 iTunes plugin + by Shehryar Lasi, **reverse-engineered from its PowerPC Mach-O** (symbols + intact) to be identical, not "inspired by". Method: capstone listings, and + the original running under a **Unicorn PPC emulator** through its own + VisualPluginHandler (imports answered in Python, GL calls recorded) as the + oracle. `engine.py` is the Qt-free port, routine by routine, with `f32` / + `math.fma` wherever the PPC rounded to single or fused a multiply-add + (a palette index on `x.5` depends on it), `ParkMiller` = Darwin 6's + `rand()` (RAND_MAX 2³¹−1). `tables.npz` holds what the original computes + deterministically, extracted by running *its* code: 22 colour maps and 23 + base wave images (before their random `transform()`, which is ported, as + are the 16 live `calcDelta` warps — each with its **own** static counters + per layer). Quirks kept on purpose: `flipDiag`'s off-by-one. Facts that + shape the port: the plugin renders only after 39,999 µs, so it ran at + **25 fps** and counts frames for rotation and switching — the renderer + steps the engine on its own 25 Hz clock, never the widget's 60 Hz timer; + beat timing is in TickCount (1/60 s). The original's Color/Flash settings + were Apple SDK leftovers its code never read, so the style has none. It + reads only iTunes' **spectrum** bytes (never the waveform); iTunes' byte + scale was never published, so `itunes_spectrum` (√magnitude, 43 Hz bins) + is the one calibrated stand-in. Painting: each GL triangle is planar, so + it is drawn in texture space through a projective **world** transform + (Qt mis-draws a strongly projective *brush* transform); the top cone is + always nearer, so painter's order is the depth test. + `tests/kaleidostrobe_golden.npz` was recorded from the emulated original + and `test_round84` holds the port to it byte for byte. + - **`lintunes/importers/itunes_importer.py`** — parses the iTunes XML plist. Remaps Mac `file:///Volumes/...` paths to the local `--music-root` with case/Unicode-normalization fuzzy matching (macOS is case-insensitive + NFD vs diff --git a/lintunes/__init__.py b/lintunes/__init__.py index 24f7600..f011870 100644 --- a/lintunes/__init__.py +++ b/lintunes/__init__.py @@ -1,3 +1,3 @@ """LinTunes — iTunes-style music library manager and player for Linux.""" -__version__ = "0.52.0" +__version__ = "0.53.0" diff --git a/lintunes/gui/preferences_dialog.py b/lintunes/gui/preferences_dialog.py index 2f45c0b..0d5621b 100644 --- a/lintunes/gui/preferences_dialog.py +++ b/lintunes/gui/preferences_dialog.py @@ -79,6 +79,7 @@ _VISUALIZER_STYLES = { "bars": "Bars", "radial": "Radial dots", "laser": "Laser", + "kaleidostrobe": "Kaleidostrobe", } @@ -599,6 +600,17 @@ class PreferencesDialog(QDialog): form.addRow("", square) self._viz_pages.addWidget(laser) + kaleido = QWidget() + form = self._viz_form(kaleido) + about = QLabel( + "The 2002 iTunes visualizer by Shehryar Lasi, rebuilt from its " + "original code. It has no settings: the Color and Flash boxes " + "it once showed were never connected to anything.") + about.setWordWrap(True) + about.setEnabled(False) + form.addRow(about) + self._viz_pages.addWidget(kaleido) + self._viz_pages.setCurrentIndex(list(_VISUALIZER_STYLES).index(current)) column.addWidget(self._viz_pages) diff --git a/lintunes/gui/visualizer.py b/lintunes/gui/visualizer.py index 7776046..6c01eb0 100644 --- a/lintunes/gui/visualizer.py +++ b/lintunes/gui/visualizer.py @@ -348,6 +348,9 @@ class VisualizerWidget(QWidget): regardless (in color), since opening it is asking to see it.""" if self._no_pcm or (self._mode == MODE_OFF and not big): return + # A style with colours of its own (Kaleidostrobe) can't take the + # gray as its colour; it is told instead. + self._renderer.dimmed = self._mode == MODE_DIM self._renderer.paint(painter, rect, self._bar_color(), self._grid_gray()) def paintEvent(self, event): diff --git a/lintunes/gui/visualizer_kaleido.py b/lintunes/gui/visualizer_kaleido.py new file mode 100644 index 0000000..c7cb753 --- /dev/null +++ b/lintunes/gui/visualizer_kaleido.py @@ -0,0 +1,198 @@ +"""Kaleidostrobe as a visualizer style: the 2002 iTunes plugin's simulation +(``lintunes.kaleidostrobe.engine``), fed what iTunes fed it and painted the +way its OpenGL did. + +Two things are this file's business, the rest is the engine's: + +- **Time.** The plugin rendered only when more than 40 ms had passed since + its last frame, so it ran at 25 fps however often iTunes asked, and its + rotation and pattern switching count *frames*. The renderer keeps its own + 25 Hz clock and steps the engine on it, never on the widget's 60 Hz timer + — otherwise everything would spin 2.4× too fast. TickCount (1/60 s) is + derived from the same clock. +- **Input.** iTunes handed plugins 512 spectrum bins per channel as bytes. + How iTunes scaled them was never documented; ``itunes_spectrum`` is a + calibrated stand-in (``SPECTRUM_GAIN``). Kaleidostrobe divides everything by + running peaks, so it is the *shape* over time that matters, not the units. + +Painting: every GL triangle is planar, so its texture → screen mapping is a +homography; each one is filled with the texture as a tiled brush under that +projective transform (GL_REPEAT, GL_LINEAR via smooth transforms). The top +layer's depth is always in front of the bottom one's, so painter's order is +the depth test. +""" +import math +import time + +import numpy as np + +from PyQt6.QtCore import Qt, QPointF +from PyQt6.QtGui import QBrush, QColor, QImage, QPainter, QPolygonF, QTransform + +from lintunes.kaleidostrobe import engine as ks + + +STYLE = "kaleidostrobe" +STEP_S = ks.FRAME_US / 1e6 # one plugin frame +MAX_CATCH_UP = 3 # frames run at once after a stall, at most +FFT_AT_44K = 1024 # iTunes' 512 bins are a 1024-point FFT's half +SPECTRUM_GAIN = 320.0 # byte = √magnitude × this (full-scale sine = 1) + +_PROJ_F = 1.0 / math.tan(math.radians(ks.FOVY) / 2) +_WINDOWS = {} + + +def itunes_spectrum(samples: np.ndarray, rate: float) -> np.ndarray: + """2×512 bytes shaped like iTunes' ``spectrumData``: linear bins 43 Hz + apart (a 1024-point FFT at 44.1 kHz, whatever the real rate). Mono audio + fills both channels alike. + + The byte scale is ours. Measured against synthetic songs, a log (dB) + scale pins all three of the plugin's band levels near 1, so the cone + height and colour scaling stop moving; linear magnitude starves the + mids. √magnitude keeps all three alive. Beat detection barely cares — + it hears a 90 BPM backbeat on every scale, and on none can it pick a + kick out of a constant sub-bass, which is the original's own limit.""" + n = max(64, int(round(FFT_AT_44K * rate / 44100.0))) + window = _WINDOWS.get(n) + if window is None: + window = _WINDOWS[n] = np.hanning(n).astype(np.float32) + seg = samples[-n:] + if len(seg) < n: + seg = np.concatenate([np.zeros(n - len(seg), np.float32), seg]) + mag = np.abs(np.fft.rfft(seg * window))[:512] / (n / 4) + if len(mag) < 512: + mag = np.concatenate([mag, np.zeros(512 - len(mag))]) + row = np.clip(np.sqrt(mag) * SPECTRUM_GAIN, 0, 255).astype(np.uint8) + return np.stack([row, row]) + + +def _rotz(deg): + r = math.radians(deg) + c, s = math.cos(r), math.sin(r) + return np.array([[c, -s, 0, 0], [s, c, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) + + +def _lift(z): + m = np.eye(4) + m[2, 3] = z + return m + + +class KaleidostrobeRenderer: + name = STYLE + dimmed = False # set by the widget: paint in dim mode's gray + + def __init__(self, config=None): + self._engine = None + self._clock = 0.0 # simulated seconds since the engine began + self._behind = 0.0 # time owed to the 25 Hz clock + self._frame = None # the last FrameOut, or None = blank + self._images = [None, None] + + # ---- the renderer contract ---- + + def configure(self, config): + pass # the original's two settings were never read by its code + + def clear(self): + """Paused or stopped: blank, but the plugin keeps its state, as it + did across iTunes' pause.""" + self._frame = None + + def advance(self, frame) -> bool: + if self._engine is None: + # srand(TickCount()) at 'init': any clock reading will do + seed = int(time.monotonic() * ks.TICKS_PER_S) & 0x7fffffff + self._engine = ks.Kaleidostrobe(seed, self._ticks()) + self._behind = min(self._behind + max(0.0, frame.dt), + STEP_S * MAX_CATCH_UP) + stepped = False + while self._behind >= STEP_S: + self._behind -= STEP_S + self._clock += STEP_S + spectrum = itunes_spectrum(frame.samples, frame.rate) + self._frame = self._engine.step(spectrum, self._ticks()) + self._images = [None, None] + stepped = True + return stepped + + def _ticks(self): + return 1000 + int(self._clock * ks.TICKS_PER_S) + + # ---- painting ---- + + def _texture(self, i, dim): + img = self._images[i] + if img is None: + rgba = np.ascontiguousarray(self._frame.textures[i]) + img = QImage(rgba.data, ks.SIZE, ks.SIZE, ks.SIZE * 4, + QImage.Format.Format_RGBA8888).copy() + self._images[i] = img + if dim is not None: + img = _dimmed(img, dim) + return img + + def paint(self, painter, rect, color: QColor, gray: QColor = None): + if self._frame is None or rect.width() < 2 or rect.height() < 2: + return + # In colour mode the highlight goes unused — Kaleidostrobe brought + # its own palettes. Dim mode tints the picture with its gray. + dim = color if self.dimmed else None + painter.save() + painter.setClipRect(rect, Qt.ClipOperation.IntersectClip) + painter.fillRect(rect, QColor(0, 0, 0)) # glClearColor(0, 0, 0, 0) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, False) + painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform, True) + painter.setPen(Qt.PenStyle.NoPen) + w, h = rect.width(), rect.height() + aspect = w / h + proj = np.array([[_PROJ_F / aspect, 0, 0, 0], + [0, _PROJ_F, 0, 0], + [0, 0, -1.0, 0]]) # rows: x_c, y_c, w_c + screen = np.array([[w / 2, 0, rect.left() + w / 2], + [0, -h / 2, rect.top() + h / 2], + [0, 0, 1.0]]) + # The rim reaches this rect's corners (reshape's gFarHalfWidth). + engine_fhw = self._engine.far_half_width + half = ks.f32(ks.FAR_HALF_HEIGHT * aspect) + rim = math.sqrt(2 * half * half) / engine_fhw if engine_fhw else 1.0 + view = _lift(-ks.EYE_Z) + world = painter.worldTransform() + for layer in self._frame.layers: + painter.setBrush(QBrush(self._texture(layer.texture, dim))) + painter.setOpacity(layer.alpha) + base = view @ _lift(layer.lift) @ _rotz(layer.turn) + for tri in layer.triangles: + m = screen @ proj @ (base @ _rotz(tri.turn)) + pts = np.array([(x * rim, y * rim, z, 1.0) if z == 0.0 + else (x, y, z, 1.0) for x, y, z in tri.xyz]) + st = np.array([(s, t, 1.0) for s, t in tri.st]) + to_xyz = pts.T @ np.linalg.inv(st.T) # (s, t, 1) → object + hom = m @ to_xyz @ np.diag([1 / ks.SIZE, 1 / ks.SIZE, 1.0]) + # Scale so w is 1 at the first vertex: every vertex is in + # front of the eye, so w stays positive across the triangle. + hom = hom / (m @ pts[0])[2] + # Draw the triangle in texture space through the homography: + # Qt's raster engine is exact for a projective *world* + # transform, not for a projective brush transform. + painter.setWorldTransform(QTransform( + hom[0, 0], hom[1, 0], hom[2, 0], + hom[0, 1], hom[1, 1], hom[2, 1], + hom[0, 2], hom[1, 2], hom[2, 2]) * world) + painter.drawPolygon(QPolygonF( + [QPointF(s * ks.SIZE, t * ks.SIZE) for s, t in tri.st])) + painter.restore() + + +def _dimmed(img: QImage, tint: QColor) -> QImage: + """Dim mode: the picture's luminance in the panel's gray.""" + a = np.frombuffer(img.constBits().asstring(img.sizeInBytes()), np.uint8) + a = a.reshape(ks.SIZE, ks.SIZE, 4).astype(np.float32) + luma = (a[..., 0] * 0.299 + a[..., 1] * 0.587 + a[..., 2] * 0.114) / 255.0 + out = np.empty((ks.SIZE, ks.SIZE, 4), np.uint8) + for i, c in enumerate((tint.red(), tint.green(), tint.blue())): + out[..., i] = (luma * c).astype(np.uint8) + out[..., 3] = 255 + return QImage(out.data, ks.SIZE, ks.SIZE, ks.SIZE * 4, + QImage.Format.Format_RGBA8888).copy() diff --git a/lintunes/gui/visualizer_styles.py b/lintunes/gui/visualizer_styles.py index 2024af4..4e58f09 100644 --- a/lintunes/gui/visualizer_styles.py +++ b/lintunes/gui/visualizer_styles.py @@ -10,6 +10,8 @@ audio intake, the timer, on/dim/off, the color. Pure numpy + QPainter. frequency, radius is volume, and a dot that moves leaves fading ghosts. - ``LaserRenderer`` — a laser bounced off a mirror glued to a membrane stretched over a speaker, projected onto a screen (Tame Impala's rig). +- ``KaleidostrobeRenderer`` (``visualizer_kaleido``) — the 2002 iTunes + plugin, ported from its PowerPC binary. Every tunable lives in preferences.json under a ``visualizer_*`` key; ``settings(prefs)`` reads them clamped to ``LIMITS``, and a renderer takes @@ -29,7 +31,8 @@ from lintunes.preferences import DEFAULTS STYLE_BARS = "bars" STYLE_RADIAL = "radial" STYLE_LASER = "laser" -STYLES = (STYLE_BARS, STYLE_RADIAL, STYLE_LASER) +STYLE_KALEIDOSTROBE = "kaleidostrobe" +STYLES = (STYLE_BARS, STYLE_RADIAL, STYLE_LASER, STYLE_KALEIDOSTROBE) BANDS = 20 STEPS = 20 # vertical granularity per bar @@ -995,4 +998,7 @@ def make_renderer(style: str, config=None): return RadialRenderer(config) if style == STYLE_LASER: return LaserRenderer(config) + if style == STYLE_KALEIDOSTROBE: + from lintunes.gui.visualizer_kaleido import KaleidostrobeRenderer + return KaleidostrobeRenderer(config) return BarsRenderer(config) diff --git a/lintunes/kaleidostrobe/__init__.py b/lintunes/kaleidostrobe/__init__.py new file mode 100644 index 0000000..77ddd51 --- /dev/null +++ b/lintunes/kaleidostrobe/__init__.py @@ -0,0 +1,2 @@ +"""Kaleidostrobe, the 2002 iTunes visualizer by Shehryar Lasi, ported from +its PowerPC binary. See ``engine`` for the simulation.""" diff --git a/lintunes/kaleidostrobe/engine.py b/lintunes/kaleidostrobe/engine.py new file mode 100644 index 0000000..87c3215 --- /dev/null +++ b/lintunes/kaleidostrobe/engine.py @@ -0,0 +1,706 @@ +"""Kaleidostrobe's per-frame simulation, ported from the PowerPC original. + +Every function here is a translation of the routine named in its docstring +(the bundle kept its symbols). Where the original rounded to single +precision, ``f32`` does too; where it used a fused multiply-add, so does +``math.fma``: an index that lands on ``x.5`` decides a palette entry, so the +rounding has to be the original's, not merely close to it. + +The engine is Qt-free. ``step()`` advances one frame and returns what the +original handed OpenGL: two 128×128 RGBA textures and, per layer, the +triangles to draw (object-space vertices, texture coordinates, and the +modelview that places them). ``visualizer_kaleido`` paints that. +""" +import math +import struct +from dataclasses import dataclass, field +from importlib import resources + +import numpy as np + + +SIZE = 128 # the index images and textures are 128×128 +TICKS_PER_S = 60 # Mac OS TickCount() +FRAME_US = 40_000 # 'vrnd' renders only after more than 39,999 µs +FOVY = 36.8698976458 # reshape(): gluPerspective(fovy, w/h, 5, 25) +EYE_Z = 15.0 # display(): gluLookAt(0,0,15, 0,0,0, 0,1,0) +NEAR, FAR = 5.0, 25.0 +FAR_HALF_HEIGHT = 5.0 # gFarHalfHeight +ROTATION_STEPS = 1080 # rotation = (rotation + 1) % 1080, drawn /3 + +# Function tables, as the plugin's arrays name them (InitGL picks with +# rand() % len, DrawGL with newValue(…, len)). +MAP_TABLE = (0, 1, 2, 3, 21, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 0, 1, 3, 4, 20, 6, 7, 9, 10, 11, 12, 15, 17, 18, 19, + 21) +WAVE_TABLE = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 31, 32, 33, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 31, 32, 33) +DELTA_TABLE = (0, 1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18) +POLAR_WAVES = {31: 3, 32: 12, 33: 16} # initWaveShape03x: base, polar, transform + +# ProcessRenderData's starting state (VisualPluginHandler 'show'/'vply'). +BAND_PEAK_START = ((1225.0, 484.0, 900.0, 32761.0), + (1089.0, 441.0, 576.0, 24964.0)) +MIN_MAX_BAND_POWER = (1157.0, 462.5, 738.0, 28862.5) +BASS_MAX_FLOOR = 12.788898 +MID_MAX_FLOOR = 7.219702 +TREBLE_MAX_FLOOR = 1.702842 +PEAK_DECAY = 0.99383029715 +# lowpass biquad shared by the three bands: b0, b1, b2, a1, a2 +LP_B0, LP_B1, LP_A1, LP_A2 = 0.0023, 0.0045, 1.8614, 0.8704 +BEAT_PERIOD_START = 45.0 # ticks, i.e. 80 BPM + + +def f32(x): + """Round to single precision, as frsp / a float store did.""" + return struct.unpack('f', struct.pack('f', x))[0] + + +def cmod(a, m): + """C's %, which keeps the sign of the dividend.""" + return np.fmod(a, m) + + +class ParkMiller: + """Darwin 6 libc rand() (FreeBSD's Park–Miller): RAND_MAX 0x7fffffff.""" + + def __init__(self, seed=1): + self.x = seed & 0xffffffff + + def rand(self) -> int: + x = self.x + if x == 0: + x = 123459876 + hi, lo = divmod(x, 127773) + x = 16807 * lo - 2836 * hi + if x < 0: + x += 0x7fffffff + self.x = x + return x % 0x80000000 + + +_RAND_SCALE = f32(4.656612873077393e-10) # 1 / 2^31, as the float it was + + +def _unit(rng) -> float: + return f32(f32(float(rng.rand())) * _RAND_SCALE) + + +# -------------------------------------------------------------------------- +# Tables: extracted by running the original makeMap / initWaveShape code +# -------------------------------------------------------------------------- + +_TABLES = None + + +def tables(): + global _TABLES + if _TABLES is None: + with resources.files(__package__).joinpath("tables.npz").open("rb") as f: + data = np.load(f) + _TABLES = {k: data[k] for k in data.files} + return _TABLES + + +def _norm_coord() -> np.ndarray: + """initGlobals: normCoord[i] = i/127·2 − 1, in single precision.""" + out = np.empty(SIZE, np.float32) + for i in range(SIZE): + q = f32(f32(float(i)) / f32(127.0)) + out[i] = f32((q + q) + -1.0) + return out + + +def _polar_tables(nc): + """initGlobals: radius = √(x² + y²) and theta = atan2(y, x) + π.""" + radius = np.empty((SIZE, SIZE), np.float32) + theta = np.empty((SIZE, SIZE), np.float32) + for y in range(SIZE): + ny = float(nc[y]) + for x in range(SIZE): + nx = float(nc[x]) + radius[y, x] = f32(math.sqrt(f32(ny * ny + f32(nx * nx)))) + if ny != 0.0 and nx != 0.0: + theta[y, x] = f32(math.atan2(ny, nx) + 3.1415926) + elif ny == 0.0: + theta[y, x] = 0.0 if nx >= 0.0 else f32(3.141592502593994) + else: + theta[y, x] = f32(1.570796251296997) if ny > 0.0 \ + else f32(4.71238899230957) + return radius, theta + + +def _cos_index(nc): + """The fishbowl remap of calcDelta014/016/017: int(cos(nc·π/2)·127 + ½).""" + return np.array([int(math.fma(math.cos(float(v) * 3.141592 * 0.5), 127.0, 0.5)) + for v in nc], np.int64) + + +class _Geometry: + """Per-process constants derived from initGlobals.""" + + def __init__(self): + nc = self.nc = _norm_coord() + self.radius, self.theta = _polar_tables(nc) + self.cos127 = _cos_index(nc) + c18 = np.empty(SIZE, np.int64) + for i in range(SIZE): + v = float(nc[i]) + c = math.cos(v * 3.141592 * 0.5) + c18[i] = int(math.fma(c, 64.0, 0.5)) if v <= 0.0 \ + else int((127.0 - c * 64.0) + 0.5) + self.cos18 = c18 + # RectToPolar's sample points: column from the angle, row from the + # distance (both ≥ 0, so fctiwz's truncation is int()). + col = [int(math.fma(float(t) / 6.2831852, 127.0, 0.5)) + for t in self.theta.ravel()] + row = [int(math.fma(float(r) / 1.41421356237, 127.0, 0.5)) + for r in self.radius.ravel()] + self.polar_col = np.fmod(np.array(col, np.int64), SIZE).reshape(SIZE, SIZE) + self.polar_row = np.fmod(np.array(row, np.int64), SIZE).reshape(SIZE, SIZE) + + +_GEOMETRY = None + + +def geometry() -> _Geometry: + global _GEOMETRY + if _GEOMETRY is None: + _GEOMETRY = _Geometry() + return _GEOMETRY + + +# -------------------------------------------------------------------------- +# Index-image operations (in place on one 128×128 uint8 buffer) +# -------------------------------------------------------------------------- + +def flip_diag(img): + """flipDiag: a transpose that skips the cells beside the diagonal. + + The loop runs x < y − 1 where a transpose wants x < y, so (y, y−1) and + (y−1, y) stay put. It shows as a faint seam along the diagonal; kept.""" + for y in range(SIZE): + if y >= 2: + row = img[y, :y - 1].copy() + img[y, :y - 1] = img[:y - 1, y] + img[:y - 1, y] = row + + +def inside_out(img): + """insideOut: each half of the image flipped top to bottom.""" + img[0:64] = img[0:64][::-1].copy() + img[64:128] = img[64:128][::-1].copy() + + +def transform(img, rng): + """transform: none, flipDiag, insideOut or both, at random.""" + k = int(math.fma(_unit(rng), 4.999999, 1.0)) + if k == 2: + flip_diag(img) + elif k == 3: + inside_out(img) + elif k == 4: + flip_diag(img) + inside_out(img) + elif k == 5: + inside_out(img) + flip_diag(img) + + +def rect_to_polar(img): + """RectToPolar: column = angle, row = distance from the centre.""" + g = geometry() + img[:] = img[g.polar_row, g.polar_col] + + +# -------------------------------------------------------------------------- +# calcDelta*: buffer 1 = a warp of buffer 0, by each layer's own counter +# -------------------------------------------------------------------------- + +_Y, _X = np.mgrid[0:SIZE, 0:SIZE] + + +def _block_average(src, rows, s): + """calcDelta005/011: 32-wide horizontal averages of a shifted image.""" + out = np.empty((len(rows), SIZE), np.uint8) + for i, y in enumerate(rows): + line = src[(y + s) % SIZE] + for blk in range(0, SIZE, 32): + cols = (blk + s + np.arange(32)) % SIZE + out[i, blk:blk + 32] = int(int(line[cols].astype(np.int64).sum()) * 0.03125) + return out + + +def delta(n, src, state): + """calcDelta: returns the warped image; advances ``state`` (a dict of + that function's static counters for this layer).""" + S = SIZE + Y, X = _Y, _X + if n == 0: + s = state.get('h', 0) + out = src[Y, (X + s) % S] + state['h'] = s + 1 + elif n == 1: + h, v = state.get('h', 0), state.get('v', 0) + out = src[(Y + v) % S, (X + h) % S] + state['h'], state['v'] = h + 1, v + 1 + elif n == 3: + s = state.get('s', 0) + out = np.where(X < 64, src[Y, (X + s) % 64], src[Y, ((X - s) % 64) + 64]) + state['s'] = (s + 1) % 64 + elif n == 4: + s = state.get('s', 0) + q = src[(Y[:64, :64] + s) % 64, (X[:64, :64] + s) % 64] + out = np.empty((S, S), np.uint8) + out[:64, :64] = q + out[64:, :64] = q[::-1] + out[64:, 64:] = q[::-1, ::-1] + out[:64, 64:] = q[:, ::-1] + state['s'] = (s + 1) % 64 + elif n == 5: + s = state.get('s', 0) + out = _block_average(src, range(S), s) + state['s'] = (s + 1) % S + elif n == 6: + s = state.get('s', 0) + out = np.empty((S, S), np.uint8) + full = src[(Y + s) % S, (X + s) % S] + y, x = np.nonzero(X[:64, :64] <= Y[:64, :64]) + v = full[y, x] + for yy, xx in ((y, x), (y, 127 - x), (127 - y, x), (127 - y, 127 - x), + (x, y), (x, 127 - y), (127 - x, y), (127 - x, 127 - y)): + out[yy, xx] = v + state['s'] = (s + 1) % S + elif n == 8: + s = state.get('s', 0) + out = src[(Y + s) % S, X] + state['s'] = s + 1 + elif n == 9: + s = state.get('s', 0) + row = (Y + s) % S + out = np.where(X < 32, src[row, (63 - X) % S], + np.where(X >= 96, src[row, (191 - X) % S], src)) + state['s'] = s + 1 + elif n == 10: + s = state.get('s', 0) + out = np.where(Y < 64, src[Y, (X + s) % S], src) + state['s'] = s + 1 + elif n == 11: + s = state.get('s', 0) + out = np.empty((S, S), np.uint8) + out[:64] = _block_average(src, range(64), s) + out[64:] = src[(Y[64:] + s) % S, (X[64:] + s) % S] + state['s'] = (s + 1) % S + elif n == 12: + s = state.get('s', 0) + row, col = (Y + s) % S, (X + s) % S + out = src[row, col].copy() + top = src[row[:64, :64], 127 - col[:64, :64]] + out[:64, :64] = top + out[:64, 64:] = src[row[:64, :64], col[:64, :64]][:, ::-1] + state['s'] = s + 1 + elif n == 13: + s = state.get('s', 0) + direct = src[(Y + s) % S, (X + s) % S] + swapped = src[(X + s) % S, (Y + s) % S] + out = np.where(Y + X >= 127, direct, swapped) + state['s'] = s + 1 + elif n == 14: + s = state.get('s', 0) + c = geometry().cos127 + out = src[(c[Y] + s) % S, (c[X] + s) % S] + state['s'] = s + 1 + elif n == 16: + s = state.get('s', 0) + c = geometry().cos127 + out = src[(c[Y] + s) % S, c[X]] + state['s'] = s + 1 + elif n == 17: + s = state.get('s', 0) + c = geometry().cos127 + out = src[(Y + s) % S, (c[X] + s) % S] + state['s'] = s + 1 + elif n == 18: + s = state.get('s', 0) + c = geometry().cos18 + out = src[(Y + s) % S, (c[X] + s) % S] + state['s'] = s + 1 + else: + raise ValueError(f"calcDelta{n:03d} is not in the plugin's table") + return np.ascontiguousarray(out, np.uint8) + + +# -------------------------------------------------------------------------- +# The plugin +# -------------------------------------------------------------------------- + +@dataclass +class Triangle: + st: tuple # ((s, t), …) × 3, texture coordinates + xyz: tuple # ((x, y, z), …) × 3, object space + turn: float # degrees about z applied after the layer's own turn + + +@dataclass +class Layer: + texture: int # 0 = bottom, 1 = top + alpha: float # glColor4f alpha (MODULATE with an opaque texture) + lift: float # glTranslatef(0, 0, lift) + turn: float # glRotatef(turn, 0, 0, 1) + triangles: list = field(default_factory=list) + + +@dataclass +class FrameOut: + textures: np.ndarray # (2, 128, 128, 4) uint8 RGBA + layers: list # [bottom Layer, top Layer] + beat: bool + + +class Kaleidostrobe: + """One instance of the plugin: 'init' + 'show' + 'vply', then a + ``step()`` per 'vrnd' the plugin accepted.""" + + def __init__(self, seed: int, ticks: int): + self.rng = ParkMiller(seed) # srand(TickCount()) + self.width, self.height = 640, 480 + t = tables() + self.maps = t['maps'] + self.waves = t['waves'] + self.wave_inc = t['wave_inc'] + # ProcessRenderData state + self.band_peak = [list(map(f32, row)) for row in BAND_PEAK_START] + self.bass_max = f32(BASS_MAX_FLOOR) + self.mid_max = f32(MID_MAX_FLOOR) + self.treble_max = f32(TREBLE_MAX_FLOOR) + self.hold = 0.0 + self.xn1 = self.xn2 = self.yn1 = self.yn2 = 0.0 + self.lp = {b: [0.0, 0.0, 0.0, 0.0] for b in ('bass', 'mid', 'treble')} + self.signal = self.avg_signal = 0.0 + self.bass = self.mid = self.treble = 0.0 + # checkBeat + self.prev_signal = 0.0 + self.prev_run_avg = 0.0 + self.max_run_avg = f32(0.35) + self.beat_periods = [BEAT_PERIOD_START] * 16 + self.next_cell = 0 + self.beat = False + self.beat_count = 0 + self.period_avg = BEAT_PERIOD_START + self.now = ticks + self.prev_tick = ticks - 1 + self.last_beat = ticks - 46 + self.start_tick = ticks + self.frame_count = 0 + self.ticks_per_frame = 1.0 + # DrawGL / display / updateTexture state + self.rotation = 0 + self.top_object = self.bottom_object = -1 + self.flip = [0, 0, 0] + self.index_offset = [0.0, 0.0] + self.cur_map = [0, 0] + self.cur_wave = [0, 0] + self.cur_delta = [0, 0] + self.buffers = np.zeros((2, 2, SIZE, SIZE), np.uint8) + self.palettes = np.zeros((2, 256, 4), np.uint8) + self.wave_scale = [0.0, 0.0] + # each calcDelta function's own static counters, per layer: a warp + # chosen again resumes where it left off, a new one starts at 0 + self.delta_state = [dict(), dict()] + self.textures = np.zeros((2, SIZE, SIZE, 4), np.uint8) + self._init_gl() + + # ---- InitGL ---- + def _init_gl(self): + for tex in (0, 1): + self.cur_map[tex] = self.rng.rand() % len(MAP_TABLE) + self.cur_wave[tex] = self.rng.rand() % len(WAVE_TABLE) + self.cur_delta[tex] = self.rng.rand() % len(DELTA_TABLE) + self._make_map(tex) + self._init_wave(tex) + + def _make_map(self, tex): + self.palettes[tex] = self.maps[MAP_TABLE[self.cur_map[tex]]] + + def _init_wave(self, tex): + """initWaveShape into buffer 0 (currFrameIndex is set to 0 first).""" + n = WAVE_TABLE[self.cur_wave[tex]] + img = self.buffers[tex, 0] + base = POLAR_WAVES.get(n, n) + img[:] = self.waves[base] + transform(img, self.rng) + self.wave_scale[tex] = float(self.wave_inc[base]) + if n in POLAR_WAVES: + rect_to_polar(img) + # RectToPolar also leaves its result in the other buffer, which + # calcDelta overwrites before anything reads it. + self.buffers[tex, 1] = img + transform(img, self.rng) + + def set_size(self, width: int, height: int): + self.width, self.height = max(1, int(width)), max(1, int(height)) + + @property + def far_half_width(self) -> float: + """reshape: the rim reaches the screen's corners.""" + t = f32(FAR_HALF_HEIGHT * self.width / self.height) + return f32(math.sqrt(f32(f32(t * t) + f32(t * t)))) + + # ---- ProcessRenderData ---- + def _process(self, spectrum, now): + self.ticks_per_frame = f32(f32(float((now - self.start_tick) & 0xffffffff)) + / f32(float(self.frame_count))) + self.now = now + if spectrum is None: + return + nch = len(spectrum) + mins = [0xff, 0xff] + for ch in range(nch): + mins[ch] = int(spectrum[ch][:256].min()) + floor = f32(float(mins[0] if mins[0] < mins[1] else mins[1])) + norm = [[0.0] * 4 for _ in range(nch)] + for ch in range(nch): + for b in range(4): + v = f32(float(int(spectrum[ch][b]) ** 2 - mins[ch] ** 2)) + if v > self.band_peak[ch][b]: + self.band_peak[ch][b] = v + p = self.band_peak[ch][b] + norm[ch][b] = f32(v / p) if p > 0.0 else 0.0 + signal = 0.0 + bass = mid = treble = 0.0 + for ch in range(nch): + for b in range(4): + signal = f32(signal + norm[ch][b]) + p = f32(self.band_peak[ch][b] * PEAK_DECAY) + self.band_peak[ch][b] = MIN_MAX_BAND_POWER[b] \ + if p < MIN_MAX_BAND_POWER[b] else p + row = spectrum[ch] + for i in range(0, 32): + bass = f32(bass + float(row[i])) + for i in range(32, 176): + mid = f32(mid + float(row[i])) + for i in range(176, 256): + treble = f32(treble + float(row[i])) + signal = f32(signal / f32(float(nch * 4))) + if signal > self.hold: + self.hold = signal + else: + signal = self.hold + self.signal = signal + dt = float((now - self.prev_tick) & 0xffffffff) + self.hold = f32(self.hold - dt * 0.04444444) + if self.hold < 0.0: + self.hold = 0.0 + avg = math.fma(signal, 0.5, self.xn1 * 0.5) + avg = avg + f32(self.xn2 * 0.0) + f32(self.yn1 * 0.0) - f32(self.yn2 * 0.0) + self.avg_signal = f32(avg) + self.yn2, self.xn2 = self.yn1, self.xn1 + self.yn1, self.xn1 = self.avg_signal, signal + n = f32(float(nch)) + self.bass, self.bass_max = self._band( + 'bass', f32(f32(bass / (n * 32.0)) - floor), self.bass_max, + BASS_MAX_FLOOR, f32(12.788898468017578)) + self.mid, self.mid_max = self._band( + 'mid', f32(f32(mid / (n * 144.0)) - floor), self.mid_max, + MID_MAX_FLOOR, f32(7.219701766967773)) + self.treble, self.treble_max = self._band( + 'treble', f32(f32(treble / (n * 80.0)) - floor), self.treble_max, + TREBLE_MAX_FLOOR, f32(1.7028419971466064), clamp=True) + self._check_beat(now) + self.prev_tick = now + + def _band(self, name, x, peak, floor_d, floor_f, clamp=False): + st = self.lp[name] # x1, x2, y1, y2 + y = math.fma(x, LP_B0, st[0] * LP_B1) + y = math.fma(st[1], LP_B0, y) + y = math.fma(st[2], LP_A1, y) + y = f32(y - st[3] * LP_A2) + if y > peak: + peak = y + st[3], st[1] = st[2], st[0] + st[2], st[0] = y, x + level = f32(y / peak) + if clamp and level < 0.0: + level = 0.0 + peak = f32(peak * PEAK_DECAY) + if peak < floor_d: + peak = floor_f + return level, peak + + def _check_beat(self, now): + """checkBeat: a rise in the bass-bin signal well above its recent + best, at least 16 ticks after the last beat.""" + rav = f32(math.fma(self.prev_run_avg, 0.25, + f32(self.signal - self.prev_signal) * 0.75)) + if rav > self.max_run_avg: + self.max_run_avg = rav + beat = rav > self.max_run_avg * 0.6 + self.prev_signal = self.signal + self.prev_run_avg = rav + self.max_run_avg = f32(self.max_run_avg * PEAK_DECAY) + if self.max_run_avg < 0.35: + self.max_run_avg = f32(0.35) + since = (now - self.last_beat) & 0xffffffff + if beat and since > 15: + self.beat_count += 1 + self.beat_periods[self.next_cell] = f32(float(since)) + self.next_cell = (self.next_cell + 1) % 16 + total = 0.0 + for p in self.beat_periods: + total = f32(total + p) + self.period_avg = f32(total * 0.0625) + self.last_beat = now + self.beat = True + else: + self.beat = False + + # ---- updateTexture ---- + def _update_textures(self): + level = f32((f32(f32(self.bass + self.mid) + self.treble)) / 2.625 + 0.075) + if level < 0.0: + level = 0.0 + lv = np.float32(level) + for tex in (0, 1): + if self.beat and (self.beat_count & 7) == 0: + self.index_offset[tex] = 0.0 + n = DELTA_TABLE[self.cur_delta[tex]] + self.buffers[tex, 1] = delta(n, self.buffers[tex, 0], + self.delta_state[tex].setdefault(n, {})) + idx = self.buffers[tex, 1].astype(np.float32) + a = np.trunc((idx + np.float32(self.index_offset[tex])).astype(np.float64) + + 0.5).astype(np.int64) + a = cmod(a, 256) + b = np.trunc((a.astype(np.float32) * lv).astype(np.float64) + + 0.5).astype(np.int64) + b = cmod(b, 256) + self.textures[tex] = self.palettes[tex][b] + k = f32(48.0 / self.period_avg) + k = f32(k * k) + step = k * (level * 2.625 / 2.25) * self.wave_scale[tex] + tpf = self.ticks_per_frame / 1.825405 + self.index_offset[tex] = f32(self.index_offset[tex] + + math.fma(step, tpf, tpf)) + + # ---- display ---- + def _pick_object(self) -> int: + return int(math.fma(_unit(self.rng), 17.999999, 1.0)) - 1 + + def _display(self) -> list: + height = f32(math.fma(self.mid, 0.5, 2.0)) + if height < 2.0: + height = f32(2.0) + depth = f32(math.pow(self.avg_signal, 1.25)) if self.avg_signal >= 0 \ + else float('nan') + if (self.beat and ((self.beat_count + 16) & 31) == 0) or self.bottom_object < 0: + self.bottom_object = self._pick_object() + if (self.beat and ((self.beat_count + 48) & 31) == 0) or self.top_object < 0: + self.top_object = self._pick_object() + spin = f32(self.rotation / 3.0) + bottom = Layer(0, 1.0, 0.0, spin, self._object( + self.bottom_object, f32(height / 1.5), f32(math.fma(depth, 10.0, -10.0)))) + top = Layer(1, 0.5, 5.0, f32(-self.rotation / 3.0), self._object( + self.top_object, height, f32(depth * 5.0))) + self.rotation = (self.rotation + 1) % ROTATION_STEPS + return [bottom, top] + + def _object(self, k, h, z): + if k == 0: + return self._draw8(h, z) + if k in (1, 2): + return self._draw12(h, z) + if k in (3, 4): + n = 6 + elif k == 5: + n = 10 + elif k <= 16: + n = 2 * k - 6 + else: + n = 30 + return self._draw_n(h, z, n) + + def _draw_n(self, h, z, n): + """drawNTriangles: n/2 mirrored pairs, each pair turned 720/n°.""" + fhw = self.far_half_width + t = f32(math.tan((math.pi + math.pi) / n)) + hx = f32(h * t) + half = f32(fhw * t) + tv = f32(h * 0.866) + ts = f32((hx + hx) * 0.866) + step = f32(720.0 / n) + tris = [] + for i in range(n // 2): + turn = step * i + tris.append(Triangle(((0.0, tv), (-ts, -tv), (0.0, -tv)), + ((0.0, 0.0, z), (-half, -fhw, 0.0), (0.0, -fhw, 0.0)), turn)) + tris.append(Triangle(((0.0, tv), (0.0, -tv), (-ts, -tv)), + ((0.0, 0.0, z), (0.0, -fhw, 0.0), (half, -fhw, 0.0)), turn)) + return tris + + def _draw12(self, h, z): + """draw12Triangles: six mirrored pairs, 60° apart.""" + fhw = self.far_half_width + wide = f32(fhw / 0.866) + tv = f32(h * 0.866) + tn = f32(-h * 0.866) + left = f32(-wide * 0.5) + right = f32(wide * 0.5) + tris = [] + for i in range(6): + turn = 60.0 * i + tris.append(Triangle(((0.0, tv), (-h, tn), (0.0, tn)), + ((0.0, 0.0, z), (left, -fhw, 0.0), (0.0, -fhw, 0.0)), turn)) + tris.append(Triangle(((0.0, tv), (0.0, tn), (-h, tn)), + ((0.0, 0.0, z), (0.0, -fhw, 0.0), (right, -fhw, 0.0)), turn)) + return tris + + def _draw8(self, h, z): + """draw8Triangles: a square pyramid as one triangle fan.""" + f = self.far_half_width + rim = ((-f, f), (-f, 0.0), (-f, -f), (0.0, -f), (f, -f), (f, 0.0), + (f, f), (0.0, f), (-f, f)) + st = ((-h, h), (-h, -h)) + tris = [] + for i in range(8): + a, b = rim[i], rim[i + 1] + tris.append(Triangle(((h, -h), st[i % 2], st[(i + 1) % 2]), + ((0.0, 0.0, z), (a[0], a[1], 0.0), (b[0], b[1], 0.0)), 0.0)) + return tris + + # ---- DrawGL ---- + def _new_value(self, cur, n) -> int: + while True: + v = int(math.fma(_unit(self.rng), n - 1e-06, 1.0)) - 1 + if v != cur: + return v + + def _switch(self): + """After a beat: every 8th swaps a layer's warp, 16th its colours, + 32nd its pattern — alternating layers each time.""" + if not self.beat: + return + c = self.beat_count + if (c & 0x1f) == 0: + tex = self.flip[0] + self.cur_wave[tex] = self._new_value(self.cur_wave[tex], 50.0) + self._init_wave(tex) + self.flip[0] = int(tex == 0) + elif (c & 0xf) == 0: + tex = self.flip[1] + self.cur_map[tex] = self._new_value(self.cur_map[tex], 37.0) + self._make_map(tex) + self.flip[1] = int(tex == 0) + elif (c & 7) == 0: + tex = self.flip[2] + self.cur_delta[tex] = self._new_value(self.cur_delta[tex], 16.0) + self.flip[2] = int(tex == 0) + + def step(self, spectrum, ticks: int) -> FrameOut: + """One accepted 'vrnd': ``spectrum`` is iTunes' 2×512 uint8 array + (or None for no data); ``ticks`` is TickCount() now.""" + self.frame_count += 1 + self._process(spectrum, ticks) + self._update_textures() + layers = self._display() + self._switch() + return FrameOut(self.textures.copy(), layers, self.beat) diff --git a/lintunes/kaleidostrobe/tables.npz b/lintunes/kaleidostrobe/tables.npz new file mode 100644 index 0000000000000000000000000000000000000000..4a3261ca0efb96de20bf0fbdfc7792aad7e739d6 GIT binary patch literal 112292 zcmZs?1CS<7&@TFpZQJ&aZJRshj=5vop53vvW81cE+qT{_-yi3m6Zgi=i0+Q+tf=g) z?5xVldP+$a44eS~06>3VB!E>!i$LK2CTIXUz}CpYiP6r%0|bB!@YnpV@=Y24RsW{T zOb>7M#m=W3*27=fqhhEcA`*X)Q9)Udq3_W}h(XeV0Y-@=6G3u6G^tDcCqN;DDRBaY zK*Vurs9{Z&N}C)pD!^#f8>pd4wx8>#SDUuByu9AGo}WI8Cy(#F|8y>Mzdu(TzgAxO zEZJAy%l)plqwrx!FB|?t7b=g-!@@1d=&_VIG06-^a}@ z{J=6Dw%;`m_)9R_37&MkA6qX-Z7}!{3T~oM){a=8$R8Lud5R7N(Y}7xi0~28A3rim z+T=^{<`YjmJq8x+6>LO69{*^gq|BwiS=vTSTPTVY#IlWC$r=BxB4Xg2o35%Zk9HGY*D!2k0rDZ7oeNFP~xsv!eVV4bu@6Sf$EE@rLsF}%7!cXq( zFv?gezdQGIMFPdB(|wv$?%2TLp;^Z#P3=hn+1-5;i_RV8HF{k6^_-ae%|8hZ20Vd? ziipMg^Zh3c#?)CkI3g*Fht7Ju;rWkoGq$3Bk(^Ke-0%CHx96h%9DB~0c)@hKKIC3k z5%Sd)Qw2Rg{aWc#kszQpz35e;B&0PxOZY*^t3A}QZ%Xgk8l96vy?^@Gw4#jBq`y?f z_jg<3u>sv-NIgIIi-clq_W9`O_QTG^AnKF>>=%(Fhz-g7tO-q|Rl zw?hZ(GNRkwTR`lGksFl2>Qd}9N8{l=d*$ohsfZn;-RRGIZ3k;lr>;ux@O85E+sz)` ztHi?_(UhSLrilY#JD$RSw@g6bAuz`Xr4DvA7+*wzgo(r;50Gb=$0LFwGAr_11R+=@ zNXOy;!1GnOUItHYZ?h+g1eK8X4i7TxFEUp#{67*G#dvXr4XwHfgMIq`h7LaN#Gnkqo&Eu2F|uw>0w7TiHf` zy6^KiY_<$wFyT?Q>OGiG^E7neXN=G6?;7E|&wZ5G5Bo zKY@?SKrb3%>RWV$g zyRA_-8UAx{fdrRT2pG!4BHu@MX27)h--`^7 zU(moKmc;Yyg4coeKhvK@j;s!t24VC&>opYKSdVOO#y{^xKP0ZG_$B50^%l%7i#eW| z4~W7vx&xnzOE2#r8!52dXWnhEklf?EM5`R#4qUqMfG~dPjzKzcn+I|C-ADI>+jpm` z+qbi2yxun#NFR3RK2;YLyK`MonY?P_*26oCe{b%pcSrD)T=J6n?F9|r+n-mx9|_N^ zHcbbIx9cB0Em7-169R ziGxsC3^9#X@kO*oe^TYKa!>LI*c3y%+&cZk3+0 zG|br|+~alJ*!XOXk;Q|BnpQ-SoG`0-eyh`LAcV!Oaf1zxb}eY7e#}y}BpzozgU(Eo z?aAx$Y?YqHG+~1q(^@mq<#rq*zL2`QU%+phOwKg}caY1i7}qPY_2z;~o!O&Fi+;!k zGX(8cRQ^|T?K*G<-IF6@haW95MAt{!$^noFB0lf=b1G`O(L639w(I%H49fb1W23@p zX(R4cGIC;%=LMI2>nG*uy zD$`~I`(JUv!7p^8IAarKHFQ|G_u)5V-R*ue=#~&5;yYOypV^+-nt2$*c=&ohd2@MKH9t9$cRt5# z^TFF}4Z7MCWoIvG!tCunj}ynNs5AbH5QfinI3TP4GKS>`fm~sDR)UBUNvu6PKobjT zB^0SLssy<@R#cikt2;@fMsm3rP<18~A#?Ii|3TGnOnr(O!K6WgRX<5?3Ej+s(upkv zLc7P9!7MGgR+mom-(tnQCx;bT_Y7wCJV*BO{lx;~lLZo!1=D*&+~?Xf2*HkjS&2&0 zdGq%_vR&@ek&Crbxp^_8&}7Z4)0iZ`HUVjC7_(HPLg%5PSSKc{SrRg_sB30b6t(Ui z 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"ksyF^1-X+QKyJRzxcobRp{onW==CcO+A9g(6pP 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 literal 0 HcmV?d00001 diff --git a/lintunes/preferences.py b/lintunes/preferences.py index 2808eae..80da4a1 100644 --- a/lintunes/preferences.py +++ b/lintunes/preferences.py @@ -14,7 +14,7 @@ DEFAULTS = { "volume": 0.8, # logical 0..1 master output volume "normalize_volume": False, # play every song at one loudness (loudness.py) "visualizer_mode": "on", # on (color) | dim (gray) | off — click cycle - "visualizer_style": "bars", # bars | radial | laser (visualizer_styles) + "visualizer_style": "bars", # bars | radial | laser | kaleidostrobe # The styles' tunables — ranges in visualizer_styles.LIMITS. # Fade times in seconds, 0 = off: how long what a bar or dot left # behind, or the laser's past sweeps, take to fade into the background. diff --git a/scripts/kaleidostrobe/README.md b/scripts/kaleidostrobe/README.md new file mode 100644 index 0000000..9650c84 --- /dev/null +++ b/scripts/kaleidostrobe/README.md @@ -0,0 +1,21 @@ +# Kaleidostrobe reverse-engineering tools + +How `lintunes/kaleidostrobe/` was made, and how to check it again. Dev-only: +needs `pip install capstone unicorn numpy` (never a LinTunes dependency) and +the original bundle (`KALEIDOSTROBE_BIN`, default +`~/documents/misc/lil hacky bits/Kaleidostrobe.bundle/Contents/MacOS/Kaleidostrobe`). + +- `macho.py` — Mach-O PPC parser + annotated disassembly + (`python macho.py _display _checkBeat`): resolves the PIC base, stubs, + non-lazy pointers and float constants. +- `emu.py` — the original under Unicorn: imports answered in Python + (libm, Darwin `rand`, TickCount/Microseconds, Carbon's `pi`), GL calls + recorded. After adding a hook, `ctl_remove_cache` — Unicorn never applies + a hook to code it already translated. +- `plugin.py` — drives `VisualPluginHandler` like iTunes: init, show, vply, + vrnd. +- `extract.py OUT.npz` — the colour maps and base wave images + → `lintunes/kaleidostrobe/tables.npz`. +- `golden.py OUT.npz` — `tests/kaleidostrobe_golden.npz`. +- `compare.py [frames]`, `coverage.py` — the port against the original, + frame by frame / function by function. diff --git a/scripts/kaleidostrobe/compare.py b/scripts/kaleidostrobe/compare.py new file mode 100644 index 0000000..a78a4c6 --- /dev/null +++ b/scripts/kaleidostrobe/compare.py @@ -0,0 +1,107 @@ +"""Run the emulated original and the Python port side by side.""" +import math, sys, 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 +from lintunes.kaleidostrobe.engine import Kaleidostrobe + +def rotz(a): + r = math.radians(a); c, s = math.cos(r), math.sin(r) + m = np.eye(4); m[0, 0] = c; m[0, 1] = -s; m[1, 0] = s; m[1, 1] = c + return m + +def trans(x, y, z): + m = np.eye(4); m[:3, 3] = (x, y, z); return m + +def gl_triangles(calls): + """(texture, alpha, [(st×3, eye-xyz×3)]) per glBegin batch, plus textures.""" + stack = [np.eye(4)]; tex = None; alpha = 1.0; st = (0, 0) + out = []; cur = None; mode = None + for name, a in calls: + M = stack[-1] + if name == '_glLoadIdentity': stack[-1] = np.eye(4) + elif name == '_gluLookAt': stack[-1] = stack[-1] @ trans(0, 0, -15) + elif name == '_glPushMatrix': stack.append(stack[-1].copy()) + elif name == '_glPopMatrix': stack.pop() + elif name == '_glRotatef': stack[-1] = stack[-1] @ rotz(a[0]) + elif name == '_glTranslatef': stack[-1] = stack[-1] @ trans(*a[:3]) + elif name == '_glBindTexture': tex = a[1] + elif name == '_glColor4f': alpha = a[3] + elif name == '_glBegin': cur = []; mode = a[0] + elif name == '_glTexCoord2f': st = a[:2] + elif name in ('_glVertex2f', '_glVertex3f'): + v = (a[0], a[1], a[2] if name == '_glVertex3f' else 0.0, 1.0) + cur.append((st, (M @ np.array(v))[:3])) + elif name == '_glEnd': + tris = [] + if mode == 4: + tris = [cur[i:i + 3] for i in range(0, len(cur), 3)] + elif mode == 6: + tris = [[cur[0], cur[i], cur[i + 1]] for i in range(1, len(cur) - 1)] + for t in tris: + out.append((tex, alpha, t)) + return out + +def engine_triangles(frame): + out = [] + for layer in frame.layers: + base = trans(0, 0, -15) @ trans(0, 0, layer.lift) @ rotz(layer.turn) + for t in layer.triangles: + M = base @ rotz(t.turn) + out.append((layer.texture + 1, layer.alpha, + [(t.st[i], (M @ np.array((*t.xyz[i], 1.0)))[:3]) for i in range(3)])) + return out + +def spectra(frame, rnd): + """Fake iTunes spectra: a kick every ~13 frames, noise elsewhere.""" + kick = (frame % 13) < 2 + row = [rnd.randrange(0, 40) for _ in range(512)] + for b in range(4): + row[b] = rnd.randrange(180, 256) if kick else rnd.randrange(20, 120) + for b in range(4, 32): + row[b] = rnd.randrange(60, 200) + return [row, row[:]] + +def main(frames=200, seed_ticks=1000, w=640, h=480): + p = Plugin(rect=(0, 0, h, w), ticks=seed_ticks) + e = Kaleidostrobe(seed=seed_ticks, ticks=seed_ticks) + e.set_size(w, h) + rnd = random.Random(7) + tex_bad = geo_bad = 0 + t0 = p.k.micro + for f in range(frames): + spec = spectra(f, rnd) + start = len(p.k.gl) + p.k.micro += 40001 + ticks = seed_ticks + (p.k.micro - t0) * 60 // 1_000_000 + calls = p.frame(None, spec, dt_us=0, dticks=ticks - p.k.ticks) + ours = e.step(np.array(spec, np.uint8), ticks) + # textures: the two glTexImage2D uploads of this frame + idx = [i for i in range(start, len(p.k.gl)) if p.k.gl[i][0] == '_glTexImage2D'] + theirs = [np.frombuffer(p.k.textures[i], np.uint8).reshape(128, 128, 4) for i in idx] + for t in range(2): + d = int((theirs[t] != ours.textures[t]).any(-1).sum()) + if d: + tex_bad += 1 + if tex_bad <= 5: + print(f'frame {f} tex {t}: {d} texels differ') + a, b = gl_triangles(calls), engine_triangles(ours) + ok = len(a) == len(b) and all( + x[0] == y[0] and abs(x[1] - y[1]) < 1e-6 and + all(np.allclose(x[2][i][0], y[2][i][0], atol=1e-4) and + np.allclose(x[2][i][1], y[2][i][1], atol=1e-3) for i in range(3)) + for x, y in zip(a, b)) + if not ok: + geo_bad += 1 + if geo_bad <= 3: + print(f'frame {f}: geometry differs ({len(a)} vs {len(b)} triangles)') + for x, y in list(zip(a, b))[:2]: + print(' orig', x); print(' port', y) + if f % 50 == 0: + print(f'frame {f}: beat={ours.beat} beats={e.beat_count} objects={e.bottom_object},{e.top_object} ' + f'map={e.cur_map} wave={e.cur_wave} delta={e.cur_delta}') + print(f'{frames} frames: texture mismatches {tex_bad}, geometry mismatches {geo_bad}') + +if __name__ == '__main__': + main(int(sys.argv[1]) if len(sys.argv) > 1 else 200) diff --git a/scripts/kaleidostrobe/coverage.py b/scripts/kaleidostrobe/coverage.py new file mode 100644 index 0000000..d7ce269 --- /dev/null +++ b/scripts/kaleidostrobe/coverage.py @@ -0,0 +1,45 @@ +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) diff --git a/scripts/kaleidostrobe/emu.py b/scripts/kaleidostrobe/emu.py new file mode 100644 index 0000000..bda20db --- /dev/null +++ b/scripts/kaleidostrobe/emu.py @@ -0,0 +1,253 @@ +"""Run the original Kaleidostrobe PPC code under Unicorn, as iTunes would. + +Imports are trapped at their __picsymbol_stub entries and answered in Python; +GL calls are recorded (name, args) so a frame's draw list can be compared. +""" +import math, struct, sys +sys.path.insert(0, __file__.rsplit('/', 1)[0]) +import macho +from unicorn import Uc, UC_ARCH_PPC, UC_MODE_PPC32, UC_MODE_BIG_ENDIAN, UC_HOOK_CODE +from unicorn import UC_HOOK_MEM_UNMAPPED, UcError +import unicorn.ppc_const as P + +R = [getattr(P, f'UC_PPC_REG_{i}') for i in range(32)] +F = [getattr(P, f'UC_PPC_REG_FPR{i}') for i in range(32)] +STUB0, STUBEND, STUBSZ = 0x11f5c, 0x12d00, 36 +MAGIC = 0x7fff0 # return address: emu_stop when reached +STACK_TOP = 0x0ff0000 +HEAP = 0x1000000 + +NOOPS = {'_GetPortForeColor', '_GetPortBackColor', '_RGBForeColor', '_RGBBackColor', + '_PaintRect', '_EraseRect', '_InsetRect', '_TextFont', '_TextSize', '_TextMode', + '_TETextBox', '_FMGetFontFamilyFromName', '_ShowWindow', '_HideWindow', + '_fprintf', '_fclose', '_strcat', '_MPBlockCopy'} +STUBS = {a: n for a, (t, n) in macho.stubname.items() if t == 'stub'} + + +class ParkMiller: + """FreeBSD 4 / Darwin 6 libc rand(): RAND_MAX 0x7fffffff.""" + def __init__(self, seed=1): + self.x = seed + + def srand(self, s): + self.x = s & 0xffffffff + + def rand(self): + x = self.x + if x == 0: + x = 123459876 + hi, lo = divmod(x, 127773) + x = 16807 * lo - 2836 * hi + if x < 0: + x += 0x7fffffff + self.x = x + return x % 0x80000000 + + +class KS: + def __init__(self, seed=1): + u = self.u = Uc(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN) + u.mem_map(0, 0x80000) + u.mem_write(0, macho.D[:0x24000]) + u.mem_map(STACK_TOP - 0x100000, 0x110000) + u.mem_map(HEAP, 0x400000) + self.heap = HEAP + u.reg_write(P.UC_PPC_REG_MSR, u.reg_read(P.UC_PPC_REG_MSR) | 0x2000) + # the weak import aglChoosePixelFormat must look present + u.mem_write(0x23fb8, struct.pack('>I', 1)) + # Carbon's MathLib `extern const double pi` (fp.h) + self.heap += 16 + u.mem_write(HEAP, struct.pack('>d', math.pi)) + u.mem_write(0x23fa4, struct.pack('>I', HEAP)) + u.hook_add(UC_HOOK_CODE, self._stub, begin=STUB0, end=STUBEND - 1) + u.hook_add(UC_HOOK_CODE, self._magic, begin=MAGIC, end=MAGIC + 3) + itcall = macho.func_size['_ITCallApplication'][0] + u.hook_add(UC_HOOK_CODE, lambda u, a, s, d: self._ret(r3=0), begin=itcall, end=itcall + 3) + self.rng = ParkMiller(seed) + self.ticks = 1000 + self.micro = 10_000_000 + self.gl = [] + self.textures = {} + self.trace_gl = True + + # ---- memory helpers ---- + def r32(self, a): return struct.unpack('>I', self.u.mem_read(a, 4))[0] + def w32(self, a, v): self.u.mem_write(a, struct.pack('>I', v & 0xffffffff)) + def rf(self, a): return struct.unpack('>f', self.u.mem_read(a, 4))[0] + def wf(self, a, v): self.u.mem_write(a, struct.pack('>f', v)) + def rd(self, a): return struct.unpack('>d', self.u.mem_read(a, 8))[0] + def wd(self, a, v): self.u.mem_write(a, struct.pack('>d', v)) + def mem(self, a, n): return bytes(self.u.mem_read(a, n)) + + def alloc(self, n): + a = (self.heap + 15) & ~15 + self.heap = a + n + self.u.mem_write(a, b'\0' * n) + return a + + def reg(self, i): return self.u.reg_read(R[i]) + def setreg(self, i, v): self.u.reg_write(R[i], v & 0xffffffff) + + def freg(self, i): + v = self.u.reg_read(F[i]) + return struct.unpack('>d', struct.pack('>Q', v & 0xffffffffffffffff))[0] + + def setfreg(self, i, x): + self.u.reg_write(F[i], struct.unpack('>Q', struct.pack('>d', x))[0]) + + # ---- calling ---- + def call(self, addr, *args, fargs=()): + if isinstance(addr, str): + addr = macho.func_size[addr][0] + u = self.u + sp = STACK_TOP - 0x400 + u.reg_write(R[1], sp) + self.w32(sp, 0) + for i, a in enumerate(args[:8]): + self.setreg(3 + i, a) + for i, a in enumerate(args[8:]): + self.w32(sp + 24 + 4 * (8 + i), a) + for i, x in enumerate(fargs): + self.setfreg(1 + i, x) + u.reg_write(P.UC_PPC_REG_LR, MAGIC) + try: + u.emu_start(addr, MAGIC + 4) + except UcError as e: + pc = u.reg_read(P.UC_PPC_REG_PC) + raise RuntimeError(f'{e} at pc={pc:#x} ({macho.symfor(pc)})') from None + return self.reg(3) + + def _magic(self, u, addr, size, ud): + u.emu_stop() + + def _ret(self, r3=None, f1=None): + if r3 is not None: + self.setreg(3, r3) + if f1 is not None: + self.setfreg(1, f1) + self.u.reg_write(P.UC_PPC_REG_PC, self.u.reg_read(P.UC_PPC_REG_LR)) + + def stackarg(self, i): + sp = self.reg(1) + return self.r32(sp + 24 + 4 * i) + + # ---- imports ---- + def _stub(self, u, addr, size, ud): + if (addr - STUB0) % STUBSZ: + return + name = STUBS.get(addr, '?') + fn = getattr(self, 'imp' + name, None) + if fn is not None: + fn() + return + if name.startswith('_gl') or name.startswith('_agl'): + self._glcall(name) + return + if name in NOOPS: + self._ret(r3=0) + return + raise RuntimeError(f'unhandled import {name}') + + def f(self, n): return [self.freg(1 + i) for i in range(n)] + def r(self, n): return [self.reg(3 + i) for i in range(n)] + + def imp_sin(self): self._ret(f1=math.sin(self.freg(1))) + def imp_cos(self): self._ret(f1=math.cos(self.freg(1))) + def imp_tan(self): self._ret(f1=math.tan(self.freg(1))) + def imp_sqrt(self): self._ret(f1=math.sqrt(self.freg(1)) if self.freg(1) >= 0 else float('nan')) + def imp_floor(self): self._ret(f1=math.floor(self.freg(1))) + def imp_atan2(self): y, x = self.f(2); self._ret(f1=math.atan2(y, x)) + + def imp_pow(self): + x, y = self.f(2) + try: + v = math.pow(x, y) + except (ValueError, OverflowError): + v = float('nan') + self._ret(f1=v) + + def imp_modf(self): + x = self.freg(1) + ip = float(math.trunc(x)) + self.wd(self.reg(5), ip) + self._ret(f1=x - ip) + + def imp_rand(self): self._ret(r3=self.rng.rand()) + def imp_srand(self): self.rng.srand(self.reg(3)); self._ret() + def imp_TickCount(self): self._ret(r3=self.ticks) + + def imp_Microseconds(self): + p = self.reg(3) + self.w32(p, self.micro >> 32); self.w32(p + 4, self.micro) + self._ret() + + def imp_memcpy(self): + d, s, n = self.r(3) + self.u.mem_write(d, self.mem(s, n)); self._ret(r3=d) + + def imp_BlockMoveData(self): + s, d, n = self.r(3) + self.u.mem_write(d, self.mem(s, n)); self._ret() + + def imp_memset(self): + d, c, n = self.r(3) + self.u.mem_write(d, bytes([c & 0xff]) * n); self._ret(r3=d) + + def imp_NewPtrClear(self): self._ret(r3=self.alloc(self.reg(3))) + def imp_NewRgn(self): self._ret(r3=self.alloc(16)) + def imp_DisposePtr(self): self._ret() + def imp_DisposeRgn(self): self._ret() + def imp_GetPort(self): self.w32(self.reg(3), 0x4444); self._ret() + def imp_SetPort(self): self._ret() + def imp_EqualRect(self): self._ret(r3=0) + def imp_strlen(self): + a = self.reg(3); n = 0 + while self.mem(a + n, 1) != b'\0': n += 1 + self._ret(r3=n) + + port_rect = (0, 0, 480, 640) # top, left, bottom, right + + def imp_GetPortBounds(self): + rect = self.reg(4) + self.u.mem_write(rect, struct.pack('>4h', *self.port_rect)) + self._ret(r3=rect) + + def imp_PlayerGetPluginFileSpec(self): self._ret(r3=0) + + # ---- GL / AGL ---- + GL_FLOATS = { + '_glClearColor': 4, '_glColor4f': 4, '_glRotatef': 4, '_glTranslatef': 3, + '_glVertex2f': 2, '_glVertex3f': 3, '_glTexCoord2f': 2, '_gluPerspective': 4, + '_gluLookAt': 9, + } + + def _glcall(self, name): + ret = 0 + if name in self.GL_FLOATS: + args = tuple(self.f(self.GL_FLOATS[name])) + elif name == '_glTexEnvf': + args = (self.reg(3), self.reg(4), self.freg(1)) + elif name == '_glTexImage2D': + args = tuple(self.r(8)) + (self.stackarg(8),) + w, h = args[3], args[4] + self.textures[len(self.gl)] = self.mem(args[8], w * h * 4) + elif name == '_glGenTextures': + n, p = self.r(2) + for i in range(n): + self.w32(p + 4 * i, 1 + i) + args = (n,) + elif name.startswith('_agl'): + args = tuple(self.r(4)) + ret = 1 if name not in ('_aglGetError',) else 0 + if name == '_aglCreateContext': + ret = 0xc0c0 + else: + args = tuple(self.r(4)) + if self.trace_gl: + self.gl.append((name, args)) + self._ret(r3=ret) + + +if __name__ == '__main__': + k = KS() + print(k.call('_newValue', 3, fargs=(10.0,))) diff --git a/scripts/kaleidostrobe/extract.py b/scripts/kaleidostrobe/extract.py new file mode 100644 index 0000000..3c8bfca --- /dev/null +++ b/scripts/kaleidostrobe/extract.py @@ -0,0 +1,85 @@ +"""Extract Kaleidostrobe's deterministic tables by running the original code. + +- 22 colour maps (makeMap000-021): mapRGB[0], 256 RGBA entries +- base wave images (initWaveShape000-022), *before* their random transform() + (transform is stubbed out here; the port applies it with its own rand()), + plus the gWaveIncScale each one sets +Every call is checked to touch nothing but its output. +""" +import struct, sys +import numpy as np +sys.path.insert(0, __file__.rsplit('/', 1)[0]) +import macho +from plugin import Plugin +from unicorn import UC_HOOK_CODE + +MAPRGB = 0x23fd4 +TEXIDX = 0x457f8 # textureImageIndexArrays +CURTEX = 0x13dbc +CURFRAME = 0x13dc0 +WAVEINC = 0x257f0 # gWaveIncScale (2 floats) + +p = Plugin(seed=1) +k = p.k +tr = macho.func_size['_transform'][0] +k.u.hook_add(UC_HOOK_CODE, lambda u, a, s, d: k._ret(), begin=tr, end=tr + 3) +k.u.ctl_remove_cache(0, 0x80000) + +def snapshot(): + return bytearray(k.mem(0x13000, 0x759f8 - 0x13000)) + +def changed(before, after): + b = np.frombuffer(bytes(before), np.uint8); a = np.frombuffer(bytes(after), np.uint8) + idx = np.nonzero(a != b)[0] + 0x13000 + return idx + +def regions(idx): + out = set() + for a in idx[::max(1, len(idx)//200)]: + out.add(macho.symfor(int(a)).split('+')[0]) + return sorted(out) + +k.w32(CURTEX, 0) +k.w32(CURFRAME, 0); k.w32(CURFRAME + 4, 0) + +maps = np.zeros((22, 256, 4), np.uint8) +for m in range(22): + k.u.mem_write(MAPRGB, b'\x55' * 1024) + before = snapshot() + k.call(f'_makeMap{m:03d}') + after = snapshot() + idx = changed(before, after) + stray = idx[(idx < MAPRGB) | (idx >= MAPRGB + 1024)] + data = np.frombuffer(k.mem(MAPRGB, 1024), np.uint8).reshape(256, 4) + untouched = int((np.frombuffer(k.mem(MAPRGB, 1024), np.uint8) == 0x55).sum()) + maps[m] = data + print(f'map {m:03d}: stray={regions(stray) if len(stray) else "-"} 0x55-left={untouched}') + +WAVES = list(range(23)) + [31, 32, 33] +waves = {} +incs = {} +for w in WAVES: + if w >= 31: + continue + for fill in (0x00, 0xff): + k.u.mem_write(TEXIDX, bytes([fill]) * 0x8000) + k.wf(WAVEINC, -999.0) + before = snapshot() + k.call(f'_initWaveShape{w:03d}') + after = snapshot() + img = np.frombuffer(k.mem(TEXIDX, 0x4000), np.uint8).reshape(128, 128).copy() + if fill == 0: + img0 = img + else: + img1 = img + idx = changed(before, after) + stray = idx[((idx < TEXIDX) | (idx >= TEXIDX + 0x4000)) & ((idx < WAVEINC) | (idx >= WAVEINC + 4))] + partial = int((img0 != img1).sum()) + waves[w] = img0 + incs[w] = k.rf(WAVEINC) + print(f'wave {w:03d}: inc={incs[w]!r} partial-pixels={partial} stray={regions(stray) if len(stray) else "-"}') + +np.savez_compressed(sys.argv[1] if len(sys.argv) > 1 else 'tables.npz', maps=maps, + waves=np.stack([waves[w] for w in range(23)]), + wave_inc=np.array([incs[w] for w in range(23)], np.float32)) +print('saved') diff --git a/scripts/kaleidostrobe/golden.py b/scripts/kaleidostrobe/golden.py new file mode 100644 index 0000000..9b1d54c --- /dev/null +++ b/scripts/kaleidostrobe/golden.py @@ -0,0 +1,63 @@ +"""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) diff --git a/scripts/kaleidostrobe/macho.py b/scripts/kaleidostrobe/macho.py new file mode 100644 index 0000000..21ef125 --- /dev/null +++ b/scripts/kaleidostrobe/macho.py @@ -0,0 +1,188 @@ +"""Kaleidostrobe Mach-O PPC helper: sections, symbols, stubs, annotated disassembly.""" +import struct, sys, re +import capstone +import os +BIN = os.environ.get('KALEIDOSTROBE_BIN', os.path.expanduser( + '~/documents/misc/lil hacky bits/Kaleidostrobe.bundle/Contents/MacOS/Kaleidostrobe')) +D = open(BIN, 'rb').read() + +def u32(a): return struct.unpack('>I', D[a:a+4])[0] +def s16(v): return v - 0x10000 if v & 0x8000 else v + +sections = {} # name -> (addr,size,off,reserved1,segname) +syms = [] # (addr, sect, name) +allsyms = [] +off = 28; ncmds = struct.unpack('>I', D[16:20])[0] +dysym = None; symtab = None +seclist = [] +for _ in range(ncmds): + cmd, sz = struct.unpack('>II', D[off:off+8]) + if cmd == 1: + ns = struct.unpack('>I', D[off+48:off+52])[0] + so = off + 56 + for _ in range(ns): + sn = D[so:so+16].rstrip(b'\0').decode(); sg = D[so+16:so+32].rstrip(b'\0').decode() + a, s, o, al, ro, nr, fl, r1, r2 = struct.unpack('>9I', D[so+32:so+68]) + seclist.append((sg, sn, a, s, o, fl, r1, r2)) + sections[(sg, sn)] = (a, s, o, r1, r2) + so += 68 + elif cmd == 2: + symtab = struct.unpack('>4I', D[off+8:off+24]) + elif cmd == 11: + dysym = struct.unpack('>18I', D[off+8:off+80]) + off += sz +so, ns, stro, strs = symtab +for i in range(ns): + sx, ty, sect, desc, val = struct.unpack('>IBBhI', D[so+i*12:so+i*12+12]) + name = D[stro+sx:D.index(b'\0', stro+sx)].decode() + allsyms.append((name, ty, sect, val)) + if not (ty & 0xe0) and (ty & 0x0e) == 0x0e: + syms.append((val, sect, name)) +syms.sort() +addr2name = {} +for v, s, n in syms: + addr2name.setdefault(v, n) +funcs = [(v, n) for v, s, n in syms if s == 1] +func_size = {} +for i, (v, n) in enumerate(funcs): + func_size[n] = (v, (funcs[i+1][0] if i+1 < len(funcs) else 0x112e4) - v) + +# indirect symbols +indirectsymoff, nindirect = dysym[12], dysym[13] +ind = [u32(indirectsymoff + 4*i) for i in range(nindirect)] +stubname = {} +for (sg, sn, a, s, o, fl, r1, r2) in seclist: + typ = fl & 0xff + if typ in (6, 7): # non-lazy / lazy pointers, 4 bytes each + for k in range(s // 4): + idx = ind[r1 + k] + nm = allsyms[idx][0] if idx < len(allsyms) and idx not in (0x80000000, 0x40000000) else '?local' + stubname[a + 4*k] = ('ptr', nm) + elif typ == 8: # symbol stubs + for k in range(s // r2): + idx = ind[r1 + k] + nm = allsyms[idx][0] if idx < len(allsyms) else '?' + stubname[a + r2*k] = ('stub', nm) + +def symfor(a): + if a in addr2name: return addr2name[a] + if 0x112e4 <= a < 0x11f5c and not (0x113c0 <= a < 0x1140c): return f'K_{a:x}' + best = None + for v, s, n in syms: + if v <= a: best = (v, n) + else: break + if best: return f'{best[1]}+{a-best[0]:#x}' + return hex(a) + +def section_of(a): + for (sg, sn, sa, s, o, fl, r1, r2) in seclist: + if sa <= a < sa + s: return sn + return None + +def fval(a, dbl): + if a + (8 if dbl else 4) > len(D): return None + return struct.unpack('>d' if dbl else '>f', D[a:a+(8 if dbl else 4)])[0] + +md = capstone.Cs(capstone.CS_ARCH_PPC, capstone.CS_MODE_32 | capstone.CS_MODE_BIG_ENDIAN) + +def disasm(name, seed=None): + start, size = func_size[name] + out = [] + base = dict(seed or {}) + stack = {} + last_call_ret = None + for ins in md.disasm(D[start:start+size], start): + m, ops = ins.mnemonic, ins.op_str + note = '' + regs = [r.strip() for r in ops.split(',')] + word = u32(ins.address) + opc = word >> 26 + dest = regs[0] if regs and re.fullmatch(r'r\d+', regs[0]) else None + handled = False + if opc in (16, 18): + mm = re.search(r'0x[0-9a-f]+$', ops) + if mm: + tgt = int(mm.group(0), 16) + if word & 1: + last_call_ret = ins.address + 4 + note = stubname[tgt][1] if tgt in stubname else symfor(tgt) + if tgt != ins.address + 4: + for r in ('r0','r3','r4','r5','r6','r7','r8','r9','r10','r11','r12','ctr'): + base.pop(r, None) + base['lr'] = last_call_ret + elif not (start <= tgt < start + size): + note = symfor(tgt) + handled = True + elif m == 'mflr': + v = base.get('lr', last_call_ret) + if v is not None: base[dest] = v; note = f'= {v:#x}' + handled = True + elif m == 'mtlr': + if regs[0] in base: base['lr'] = base[regs[0]] + else: base.pop('lr', None) + handled = True + elif m == 'mtctr': + if regs[0] in base: base['ctr'] = base[regs[0]] + else: base.pop('ctr', None) + handled = True + elif m == 'mfctr': + if 'ctr' in base: base[dest] = base['ctr'] + else: base.pop(dest, None) + handled = True + elif m == 'mr': + if regs[1] in base: base[dest] = base[regs[1]] + else: base.pop(dest, None) + handled = True + elif m == 'addis': + if regs[1] in base: + base[dest] = (base[regs[1]] + (s16(word & 0xffff) << 16)) & 0xffffffff + else: base.pop(dest, None) + handled = True + elif m == 'addi': + if regs[1] in base: + a = (base[regs[1]] + s16(word & 0xffff)) & 0xffffffff + base[dest] = a; note = f'&{symfor(a)}' + else: base.pop(dest, None) + handled = True + else: + mm = re.match(r'(\S+), (-?(?:0x)?[0-9a-f]*)\((r\d+)\)$', ops) + if mm and (m.startswith('l') or m.startswith('st')): + breg = mm.group(3); rt = mm.group(1) + d16 = s16(word & 0xffff) + if breg == 'r1': + if m == 'stw': + if rt in base: stack[d16] = base[rt] + else: stack.pop(d16, None) + elif m == 'lwz': + if d16 in stack: base[rt] = stack[d16]; note = f'(spill {stack[d16]:#x})' + else: base.pop(rt, None) + elif m.startswith('l') and rt.startswith('r'): + base.pop(rt, None) + handled = True + elif breg in base: + a = (base[breg] + d16) & 0xffffffff + note = symfor(a) + loaded = None + if a in stubname and stubname[a][0] == 'ptr': + note = f'[ptr->{stubname[a][1]}]' + if section_of(a) == '__nl_symbol_ptr': + loaded = u32(a); note += f' = {symfor(loaded)}' + if m in ('lfs','lfd','stfs','stfd') and section_of(a) in ('__const','__data'): + v = fval(a, m in ('lfd','stfd')) + note += f' = {v!r}' + if m.startswith('l') and rt.startswith('r'): + if loaded is not None: base[rt] = loaded + else: base.pop(rt, None) + handled = True + else: + if m.startswith('l') and rt.startswith('r'): base.pop(rt, None) + handled = True + if not handled and dest and m not in ('cmpwi','cmplwi','cmpw','cmplw','stmw','fcmpu','stwx','stbx','sthx','stfsx','stfdx','stw','stb','sth','stfs','stfd'): + base.pop(dest, None) + out.append(f'{ins.address:5x} {m:8s} {ops:30s} {("; " + note) if note else ""}') + return '\n'.join(out) + +if __name__ == '__main__': + for n in sys.argv[1:]: + print(f'===== {n} ({func_size[n][0]:#x}, {func_size[n][1]} bytes)') + print(disasm(n)) diff --git a/scripts/kaleidostrobe/plugin.py b/scripts/kaleidostrobe/plugin.py new file mode 100644 index 0000000..198d8cc --- /dev/null +++ b/scripts/kaleidostrobe/plugin.py @@ -0,0 +1,68 @@ +"""Drive the emulated plugin through VisualPluginHandler like iTunes did.""" +import struct, sys +sys.path.insert(0, __file__.rsplit('/', 1)[0]) +from emu import KS + +def fourcc(s): return struct.unpack('>I', s.encode())[0] + +HANDLER = '_VisualPluginHandler' + + +class Plugin: + def __init__(self, seed=1, rect=(0, 0, 480, 640), ticks=1000): + k = self.k = KS(seed) + k.ticks = ticks + k.port_rect = rect + self.msg = k.alloc(0x100) + self.port = k.alloc(0x100) + self.render = k.alloc(0x802) + # init + k.call(HANDLER, fourcc('init'), self.msg, 0) + self.pd = k.r32(self.msg + 0x18) + # show: port, rect, options + k.w32(self.msg, self.port) + k.u.mem_write(self.msg + 4, struct.pack('>4h', *rect)) + k.w32(self.msg + 0xc, 0) + k.call(HANDLER, fourcc('show'), self.msg, self.pd) + # play + k.w32(self.msg, 0); k.w32(self.msg + 4, 0) + k.call(HANDLER, fourcc('vply'), self.msg, self.pd) + + def frame(self, wave=None, spec=None, dt_us=40001, dticks=None): + """One 'vrnd'. wave/spec: 2x512 uint8 lists (or None for silence).""" + k = self.k + k.micro += dt_us + k.ticks += dticks if dticks is not None else round(dt_us * 60 / 1e6) + data = bytearray(0x802) + data[0] = 2 + data[0x401] = 2 + if wave is not None: + data[1:0x401] = bytes(wave[0]) + bytes(wave[1]) + else: + data[1:0x401] = bytes([128]) * 1024 + if spec is not None: + data[0x402:0x802] = bytes(spec[0]) + bytes(spec[1]) + k.u.mem_write(self.render, bytes(data)) + k.w32(self.msg, self.render) + k.w32(self.msg + 4, 0) + start = len(k.gl) + k.call(HANDLER, fourcc('vrnd'), self.msg, self.pd) + return k.gl[start:] + + +if __name__ == '__main__': + import random + p = Plugin() + print('pd', hex(p.pd), 'gl calls during show:', len(p.k.gl)) + for name, args in p.k.gl[:40]: + print(' ', name, args) + rnd = random.Random(0) + for i in range(3): + wave = [[rnd.randrange(64, 192) for _ in range(512)] for _ in range(2)] + spec = [[rnd.randrange(0, 200) for _ in range(512)] for _ in range(2)] + calls = p.frame(wave, spec) + print('frame', i, len(calls)) + from collections import Counter + print(Counter(n for n, a in calls)) + for c in calls[:60]: + print(' ', c) diff --git a/setup.py b/setup.py index 57a4c6f..dcc5c84 100644 --- a/setup.py +++ b/setup.py @@ -21,6 +21,7 @@ setup( "lintunes.export": ["templates/*"], "lintunes.android": ["andTunes.apk", "andTunes.json"], "lintunes.andtunes": ["buttons/*.png"], + "lintunes.kaleidostrobe": ["tables.npz"], }, install_requires=[ "PyQt6>=6.8.0", # QAudioBufferOutput (visualizer) needs Qt 6.8+ diff --git a/tests/kaleidostrobe_golden.npz b/tests/kaleidostrobe_golden.npz new file mode 100644 index 0000000000000000000000000000000000000000..190af92e5da86f4ed1dfc0e8565300c5e9592b51 GIT binary patch literal 92947 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⪚&yNaLJ&&fUKUuI+i z2Dhh8>hG7E(kjtLlu33bV+gf*8nYzjI9{jD`Yp=m_}~-)>*l;SqD#?ZSPl0Tn{PCd z7Ud3JjLM$|3JyfWQbBUAg{p^U$f^UQGwk}N;8n39s6XXlT5btaX?L8#6!DzLm#JVHe`r>;r-W=+ez zG}#3iyjrb4NJuTTh*>Z{N9!$iB?XiHriCI>b%yE_#5~X3W>PuK3|re7Yf2Jv-2$ zXNCmXqR93&YViF+binZhcWl%}lbMRhKhN)tfOe~{l2yT?0ksCt5jKHUVbJj{~c zh1z$X>=>NG#BRn69RaaXrAvh`V$Oeo4fVk=zd7 z(q^-j`nu9~fLBwJ5hp0g2;J5#ikRaN=ZNa-U1P_TLBtEn)z?}<^W_AGG~Y55m38E< z43~XgSY>gt->XrXjZ7VM&LY`;#D;}QjU=bfG%|SXKBSRWq7w0+fTw-CRDk~wae+ke zWy0EmQwJOi7wux>CA_~eqzIO8%2$i%vXdX+uG5F6+JkFaud-`{j16~Egzo;wF8zTX z*XN>_>&K4)z0TP=oJ% z2{kznhsb}n^^IOk{q(5#*%V3-kP@Dud)+3fX8xDd?3-Bu`&R{X@+fy@_1sjYqk&;( zfGu$wF6+W4OyFaTjR`CITZ?(YMgnJPO~{r)8k8#n^tHki_5HD z4cg~{yA-IK(-?+%1AcsmRZ8-&$f{m9J`k}Z)#LKV3O(1`B94MiuI*N$+7PQGNqmY^ zNjS4kOA8aqzsuPycleR6r_03XQ2)ZGSM1Py$+u(?w{?SVgC2o*-uyJ`i~dMqGy{-1~)ISf$ih0c#Hx3Z_~#;dLsP( zrzl{F-hJw=!|ru{{V=!V^tx@1QnYt}dsxv`4Zb0|z56{LRupqSPdMd4FYaGII%We8 zPq*cRJF!%>htzc#S?c~J5l2%jGWsQH{Vm^xR9vHqUon?IQzCEAt{q+zHJGFOOE9>0 z9|UqQ#`w1GY*-9j9l=L&qPhH`;oL20pfe({EUnUFfU`Sy@gW*_@UPbj-0&1@FXGIiX0c8m?J%G;u4q8VTn0%jbJMh;WW7t3eeugVrwJMv*Up33dkW#J07G zlzVkA@ddtoH&bsm&3cU?Z)5Ewn(;LE-+lJ^I@11;+~DcJ{prl#3wAAX3%-8rzZbhN zW4rAad+uiQJ0i5dyTf|Eqw~8`$m>FUTGv0^*e%EO<**&jvZAt#=>M>>r%e%_kz8YU z&>+1;IUZF3(Hm(80iQcHefpfV1 z0274_A+ltNUQ@xwR)J)@&90*Wcn<$?4RWht(=X>v+g%G2adbt+T`Ps2$+*D4LKd|x z@0RN)FMgX;dtnW{tD4x|5Rpz@0XER`X8Slo8TNYy7H5|g;;YB=(s=anG6u#Fs!+#W zcg`|XwpJFF#Q>SeD4%8JbDC= zr>t5$1;QJKsn1_A80-h?2x8!tgb3PcH2vU{0B1IdM3E%9sp}T~ulk+W$IYELH87vU z4gZ@$CErV><+Culm9xj^3qbbMN$AQ2IQwxIfBAm-nuK(ZLdKIvo{&uhYud4^Y#C_Q zSocP)D}b{^W*e0=f!`IdY1^m@)Ta!w012g1JT$1*SvV~#6G_k8;rsm#mxUrFs{l(g3Yg%-c)69B_Hg#XsY-LacT;2H- zI^5jW(T>*_77eLub+Cn%g*)H>Der}&9d#HxmC8jyb>eN=vlR|baS|j!_#1D( zRa?3M8r#xJ4YZYT#p$ZnO>RsS3Lrt&2>Ied+XXR;m2Qgh8dsNVW zxMzC0_fK6u>&fj!5vZz<0 zp4ReamZL10Ke$tU26>$tQTwKaivUQ>e$h2yc_F+Eu<(^Yg!t8IX-6$`z5)q86%X%` zw+94e{aJPdmrpIq*jKhI!?7h&LMt5(mu{^n7ws*Ra7r<&)wIEu1JSmGiP*0IJA(?H z_BHj5Ru;62a2pxq1t}Jvlyg<%7I7u@qHA?19-I3`s0hGTgM!Z{A~KOAHI#I==-e)4 zZ`C$3v@hOIcgE%Q^?zsWTA4q+$m11T+vyON-?#Vh=UAW|u1=?HXGr`z1_?A{^9M5A9T|%in#O6xj>MA&G z+ePB7Yexsm!4GL5{A*|=%FwW}pE7zv) zU*U7PaJdeWOy-A}B?Ix<%`6X8o-ETbf-TbikjzZ32a4<gYGL%eeI9YT-%_++%O74O&QEbzyZK#phsi3xYfZ3muJ_an(K zep|NoE!Y#nK;)QC^fI@&q5Tn#<2;9gnQ^tsN#D7OVX;EE^e)k zh@;DCB=U+T01eh068#AG&Z7c-DIq(MKGax7oH-tI2MW$naoVb@H0CHP>q^!G@~SPS zPp;U~87_1OGwLn`;E{Y3RJUXMu4ywARiUuc{rd9&Z<0l?9%Efd-}{Tot0nkVTb@C4 z>wCW5g%V`J6*4&CzeMe*~QwUW>J<%-WbU+2mExbS5d;9; z7!p?|9az)zhpoU}SM&kupRd_&CRnVXs`8yxBs4$AJQTv`{@S)*T|;Hp#u<(ZV?zt| z^?0VQ53x4E-RU6L6b;(c-F}WuP~NH8d~# z65Y^IoTEaWN5OEi5&-Iy3IgRfX(>Vnf^j(5{N#H)C+5Ho zy2LUE&5`d3gcugpC6%S~`G!@<@27=(h1bs+qlryFuje^JIgup+nn2E<-BH*dIu=6- zDm*o4Dy49W-<7GWaxBmjYCjll@k1kP13{_8tcbFPWTdW;4D-5~(^Z~I^;V4LPBZS) z*T;||aX!|jFAv=RO~+xKr||J7XuMMA{fkmRup+$iVmYi-^4WA|dmK_~U&qLPZdmbs z20Wb|h$$ho@5}#>thWqmE9|<4DHLfb(&ApAKyh~~g_h#(4#nLiNP*&3+`YKFySr;} z_n-+R1U~NG@AJ((?|Wu4Iho0iJ$tTmoolVV_S%PLM-8`45;}})4iIVKh<^cc)$VYv|e5-E|(6?%b-@(f0OZKYrXACR3Sd5t&ah6ap+%Gsg zPb+ko38>dUg^;B2`^ttv&vG&z{FW?`VPG zk09?83cu}<81Exa(8FW$24wezy$suYI0ik=y(r>FH(>{JUapqK+EI{r4x>`9&mML9 zC#7kL1*NGuD5Ph*%M0Jy1j-(p_O&aKv)@m4CFYuLUYRxIi24!PrV?HJ{$~|Uv&z_vwxqDr0gja8n=Yq z)B^g_fxe<#2VR%I@&6@9=d9OqS{6ZLX~r{Ym4L1bR@2k-Ikv)6mKVf-hYMSPX7QIa zVoboaHf1zaEs1Riq!%h>XyA)Iyq|$IfGswiK~DeRV>^VT%o%bVy~dq>UmD|pQ)78761_m`V^f2sGZ5m&zjLd z^^mp8%jM_y5cet{@XaP9ZK?A}!w+<7@4ZOzxS0KXJ>~}oRz0lg_}#?#o>gsJwYqm+ zAA-}SI;961aMNuAKeAzvoMMvbglzQ;1bk)SpFQ;c>Z1@rKWW@L67`wcYvU}!DVT+Z zVmBHfw%;IBu84J~JF}&uj7cTn+$eDFqf~vwbJoAXIwxKQ&4F6mUltyp9h%rX2tEud zmt4!$HR?>5;Oe>;=z;Rdfenm{ZHsxjax#OyNO<|x>2_?8F{9SK6g(;e@jc(Ll)2~J6i{RF_%KsX%os)3z4$w}Pd)D7 zC_EkzWWB6^pCzov3-qS#%J?62!i=xE>_QDKfK|G`1tzHeq%1X3lRlUcVKyes5?a2o z)7EmU)Fhkb<2D_;XEJMdT9$|g7C47#sDs)gxcSds3cX|l(L4>yeWXCd0bk?qYMf{* zS<4M~W`pzm%oFb-U)PlAezw_bUumr@_{o(kMbJ&tkyI9CyKYk0Klwvzx9;4mSb#;$ z%DNR3K%DOEv_cAanTZ}|H9M=|#xtgS=Kr_~9 z?}RMRI|)%WjY-E_+iwhsYt(Ze`u663sIwz85y)>%?+`iK zd5j@j;)#tyJc~HmnVxy+Zl~}|cJpu|`%9Z)-Bf{prK-)xs!9#-OOVJz?h8}N>I0j4 zdenQqdhu^Qwr{`9?}B!U!cIYt(-GNsNion5O1!)h;uCz9LxGjt2t`0-76KH-AHaFg zx-Gi90iPhE;w$?fA#1BLn+|r#gt7(mH9QzpI_cqPguwW?He_v_ zvlwbm^Hy_FfES?RB*&ZkH0gRX{vCX>z_XJtJH6QD(?LD@p5vU9dcsnQh)M66)O6z8 z?Cm=WENvS!A_9e3w`K{Wuh392hzjd==DyB%3RCNS0(OOi2ClHYL4bG*A5f1n;&2o7zxMoD;2 zl-f1u!z#&kl*4>5h5x>6IjwThlem%ztSd{Dzl!tUc)z*&P&slU8%qMm>1iP0<`KAS{fQ%Cg#T1_0t`|)4C0O zHH?M9A^E|8(n4Ib$|T#t!)oq4B8#@m+WEQFKr`Lf>2takoSZWW12t}jS$(g+X}v?N z5z|Y_a6r5GceYP_zOL}QugiwdRtepK>9XKORrg``@ZAs*Fx>AFhZVkR(D8)ve37c~ zv=-6CR7rLOT=SXF9sNqtCYsuGG5d*VARQeu8F-9b4vItjf<+ zJZDOLIG84_zeFH<7?lkrB|=AA+pS3kSYaQ$k+-c{C)W7Ni0t+O8XxcxpZ(4#b)jBE zg)j)S$?VO$1r|NgceKrADU-(b{mP$?HD^Ag{tj?GPbf>aBBhLJ>i|^Wm(p^`ma&hZ z5C{JDyy*?GnrS(K>@~WQwSU%SQ4(rw{Sh2vY+HXsZr8F^+v@O(6d^YBB z###gpnDT{Ev)(Vle4n$shO*wAbUa?*_6yOuuQw83ep2QJxlDW!Un=YMGXF`8A^Yhyx)fso8?@Ys^GtBVJ!>qV0^akg){MF_Gl5FpcZgtVkt?es5V>;C>0>m~{j6yC!+w z_wj=P?4g;E=K+Jxt$hP{_f*GThaVIy>bWap02)nX?YWd^`|3QgAbym_WMW{2T8M|> z7=LbdG?~avK8W7@fTq%r5_UII4tSl-fOisV#RA6wBDFU)G&CDuBd@zAn$XKj-Y|8H_Xj{Ej*9VHj`6x zLbWuZ*A!kG^xKMgimbII1uZ2gYnjhKK{}2{UL^exVOSsyA^sm?VGInpo8duVg-Nd(AMYj1rqegB2a^U@OPt<8g24tk4BN zwUb%IuwhXNm+Sm$#VU0_T&s1hR<)Ua#jE|fgnYidS($3-Z-eJ+zMpmrhb(wrTzW&*!gAmMHuk9V6QmUYtJS4RUu(EO_^ca}Zq;J$ zG zd5{#FsI1J;w?^K%S-i0JD`(b#0~{|0NSck4Q@Mf;bqcb7<7v)BAHw+Gk2FgQs)~yx zf~(CK)%E|@Ja5+{tZ>r{K1Tt&G}pflGJo97_613b+z;A6u2u=%*mgbGi$3;k-nW@Q zO*Y^b$IH1Su(M_Mb$|(6Y24HG^EN`X>>T-rxC!E_O#g&v4OulXW(9m8N0=DSqQ`|H zfBVY4fx@oqjBhG7dTb2$O3UN&TH~;zn2b`L;ykC^22V%LqQdNuGFHBfhzU-Y-IBbo z&XoN^dnL#P-YOGUjMB0($vu-*3Y9zPr$WG* zW-(8)+@HZA_=^ADxrc(vI3cn8ha#qEH2!-;#1jRvJ?yX?l`pnV!9;8!~+Y<$v3ToaHCG3TMg9t!Xf|u{pODEK*Pp)$Zr{sV zG9Iq^P{@`{Y~ghBfuNRNo^uWl6^uNe*kHd@W1|`J3SjTT6Ei zrmPAd7SGP~8_XN>CS3JuhI+TVf@Q-vj?u`;>DiWCrkwbQD5_TD`aAiap<8J=XuloE_5m?=UPt(WvyvZYLpmQ;mf#`TPcc|W24wXjR4UVEG7S+O8Pir@EwFrv%sgGfE>w9rdCS40~ zlXJ>SaN>KS_KD19-j6m73F11paFDqmoYhzA~Ad!8o}t3z^m)Qj&+U?*X5Z<>OSW>NUZeMFU-bmhDvQj}1W}ZVK z{5&e(I2lX8(mvh*9*Q%Lkt#(Ns?qHtK5(Xsi)AJ zlUd?_Wa;y#&WnaBScfQVFFou2zG(AidrI``OvT`SacuJ`m`)TbXyCm8^SkL1N?i_3 zjCOc6sneR|bV%;gYDoZ)LbF8xoe*VCrn5sf2`bZUm0QSXN=`T}93CwqqEBn0|^x z*w9cSny-&gZE+Haa{N+1tD4!MA5%#ro0aB)Q+(?m?|idC)ZUw~-$8gdQ@5y^bY{iU z>PQa+Z);1(?V*xu@=qDjs<}o>kUeZ9tXqpBD(hv5q0(BUy#;7_wVlm|Wew0YMs1by zmvo@>sg8B*s4xoFw`(1oJNbypb}tj#?5|eBTXj63soQL@Onu;MT=k!0TMQ8VLFQ=5 zj@jPbPu5`UpSjSd+J?2_R4hROP^)i)OYJ`M?Oz_OTugJoaohC*0yuoW@q0OOnvo!P zg<)EuB9k{!lA;aeR6gY85@D_NdIgyps=P){$jVRq#qsB)sS2 zpP>S>s(8J~Eitz;=BvR``XTfnX{gTmdCk#{H=48l;58eGyGUQ>Zsy;&1hO?IYQMi` z7lV_8`-RCSByLyhZ4gk>I5^vIL#z=NhT4M%EnQ=(qZJi^X^+*X8!c!UD8$K<7M3{2 z7ac3aB#ZIlEN(Pk_p5sBVcw*b-WL9Gus&n!G#jIYielCe_DQ|!mbZ;vl1<-yrx5fr zsMj?F)n0%wEQ`Iol%o>vJ>j&n6x$9vE;6YTB~X#7_XE_*(XdA^xye-dQ%9pmh}L|1s8?|Qf; z@P)~AJ--;K(il80y6fM(JOnWRt_fgG*vJUNtXuVak{xf57QMwlchP_BDd*&G(q zp2_Q$vlz3YhNQ`CaMEkXj?7{XkbV~+qrF9yd)FIfAc%nb(Rp9+9Xs)w7x)s@^K;E6 zwu;7s56aJGueyL?;JUsd9?@40yujb&ytX!&A)~z%zIah)?r;A~TVxAA>_Olob)sN@ z3ZI3S!)%|zQxOGVM|=uiR@C)S#0u|^Y2R1Se~5j4$p2{$^u0SRC~nHHW-(RxRA5wh z!@{0Si_e5_677(wt~J^z&Y5)=r0Zb1{6p*%@iI4~Ji;j=brLQ-izM-WX|G#&Ku)HG z@C&xtA@j+)8_y5@fB@;&TQtku>kub9Mm^KtDtb;EN|vrQb=4JmmF^!F*pl@u#n2sQ zoi<~69i=6^5+io0n}!reEzg0voM_1{k#pbq=kK(pK369=49GbjUl#_RM!eShG@j6W zY1-%QJ_TDD9q8X{D(*p4_)caJL&^P9FgT5~2Z)QM64RoXlO_aO@9qCK)d~(IORgzf zeEUug`(}i)Z$-yzptXlSwsLiO|GV>sjSPaBqiu-p!I$3l$T~3D=TM{E^3gw-(PCr~ z1sc}5o_+QJE>hQ`^>g-NXEO#oZ+Rm`$7L`1579>JP*Y^|7VS9*PKS(&%SpSuAghhv zf1vYb6?+x*Kyc$~-{4_ys0*A1@q?pN_-(*Mppy2_M~nur@zd;w6ZfYbtgDkH-CV(= zm7TU2oj~rh#`LP78Z_ZY{jdf;h||r&#V_0fO!W#$2d`xx))E?{GEx(YH;lF5-2 z9m#JsnQeXz&N8U5LGJp#K_zSs>J2`kA3>Bx|iB=bzgw(18F z$-)kj2fn3u87mpDxWxI1_3A^fol3@ufk!$XcG2~@G>dx+3yu};Yx^F_I05b}#kOW9 z8GxHiy#6n(aXMiII1~RWMpqb=jiDK-8zJnb( z#v>93^>+uFr%d5!70IYsfjtMg`1r#vcH>B9FH%X@A`((_%hC||RASsK*Y)YB=CL8O zU~zRLh8hi>NDvUvs0PbFoL<8zDBSgGck%szy8O>%alZR>7kneI_S&?i`Z1@3>}&I!n<-=g3sBC>-@3 zES)*L@rbt=b*;(i`ghxf=SIa9^?%oGNzEu1S>#ZeEtH7aqK`j=jX01HL*~drGLxmM zYqJ$l(88Ydi~A%ERNoj_h-jTJ@rTw{w(b8T>--)e&*10wU6Za`M$wzwLw)GH%*O4@ zLolA)bvFy@yx{hG-g&`y0DTy&%VpJ7!nm3okp1mTjuQU6Lfd`P5dOIjXWMD+{L`)+ z?TwP_<;x*>C)^IRsf)S-a++3+iYTbG?CwE-_HsR$ncm8M#1_e^M|Rqkd&}XU zH(QCGM_lRrQZ(UvH}~hN*4{);K4d@jOF$p~Q3DliA*c20>a14VA34re6c!4Z>qXV9 znK}+(3TuJ*c0t^GbS5+4#>@$&b{G5>MzyPk8z`Ove3ZZ z<+^xxT>0I+*h#J2yUX9{;dL>pAriJ;qu95Fjk_Aabu|@go7;CYk;Ax*MJ0mDFE*Ey zF~(@8%0V74rOwEzq%x@pT~!)JY;Lw4(r-dYT9A`sccwI*3rY7g2k8a~(Uo=O;qJ$` z7*2T_EDOYkN=pquIk{J4#0y#7>X&=PWytjduFZ&L`W{*wI+b2jkbletMdy>6Jq%0% zUyu=n);4wReS7KBb>4)Bbv-?7KDL-=Jw6yeRGEV1qZ^qejBNbHB!$Xb={` za+WwIHN?aFs$?hF8d2o2Wa2E^@s+CKXL&-+DY6q^+iZ%kk=0D}a*f{S*?Q{)(^L6C zc0Mef6J|lAZs=_%E>8OJ@8@~3-d(&povnV_j-np5EAx7NCrnrV`i<>)86m7=T!YyE zuPey9&b8k&ImS0)@*rfexU`tHt%;dul|T>3`&AYU|7RD@>B6D{NC9OyAZwX~?VtPPG{Y51^A_TzYedBQfl4f=GDg1m5mkGzTR- zw0C*`b{$qx$O*5|P1^HSRTumLA`CLI_kHSmo-@z(=yBG+T2biQMFRN_2yR@L`kh8h zE2s^%_T~OmLfY2CA`;WpOj7VVBBvFX;oYp{_`3CX}ZzQ>9xC})2@wn+HP@7 zke%Luihr`~?s369x>Z=V2ZTG|0*rAU!B!Z+_EuO$}MALEkZpeo6=*uD3ti*Ed;2HEMgl zE`QsOZ{lG)_>)ycH`1k&`GUng(^PJ}M1(^qP5{+15eRc;kr`h-mF9 zZ7&>O?Fv`05Vu7EU9qayBm#q18g5KWt$r`+={0?JvXS6`I?R8SyUcPE_iqiOS}0w& zf2Gv%dP&|YqS%^P9_smFVCxJe?q|w-MCo8F)x_!%yGtXHRe-q~o9Q~%kr557e1G7W z&wfEJ#I(&2&#p#PNNBHTRuNUdd;N4>ml?ixsJ@BcbXiHRH3H1!))k=!Y=rKWgPKUB_)7 zrl<|Le44ZFWFo?yzKjXn3i_)Q-Ex2Zp^3Y`Qjh085o(8a<%Onuj9xq{(35JuwH?Lz zUFbm>+fp!NcEdC7o1Tr=?!(}2to*c6oQ!siBEBYpxa}gVv-L`acvQ+i5@k{ zm!g_*I^_SNx{QCuzI_)e*>*B9dFT~kOdQTBr^3ht9%k^JQ#6oXMAE%x{y_t?)U3X` z5g?P_4wmyhKV`fnx$16Kmxuoq7_t#6d(Ty=`y21Hz1+F%z`3Dm6`hG@8JGcfIel7aDb&Iy)j~8SXBLyETtEdk%VKYYSq-z08X;R3*kXbk_(cyn{gbOBL!gleo2Zwz8EDg&QLb<1}NI# z>s}j!|0{v$+=694M`?6i!k?d36ub|SvY};%k0%ufc*&oXX#u!!2a8pQzF%=%q-&{HsgF4?QfyXb&+A{Xpduv(f&Mch|LycK@g5|I0y zHt_u8ne0_&KF4GY2Or?mOd(WEy9mfyAo>G0s}x z&o*$#d-pjt?N7_y^JNPg;=-v~ZOVeLn--23OIBwaJD>q_s*qD{?bWKH0%`oRe>*yQ} zJn8W;GMljRGO69nvl3WR9M{FnN0OL$1jYiDiN`c^^Nn0eF)o-g$Mcpju0H=RJDaFm zb>lsM;xnrJ(~rZ$95PV8_+M>#C#b~lGD<@TwjlcWQt*w)_TIeNcv$QLTx@o3sfk`@ z6+J%=R6S1;Jl!nC_N{)xxE8`J+GL4+kKb>#5XR}KWm^^*L_Bq3!K90gF~mXnZB!st z@wWe<=60N?c=LSw#Omx-Ob7PS7nM0r_c11^G%n(pEOa zA^ezGcg&sm9ti{u>U^C0wbPPqDGwXfNqIU-Eope;>#Iqf0w~#cRM1kEId-yviG`N1 z)TH6Q*hv}r{5p~fKz;b~7W61B&ho8yHt8R&fBF-@ox~{^g+9!G$@`jj<9UPP3F!WG z1r&We$$mIyh0j#M;f(sXqfOp0YK5oiVOHI$CNw8>3<+_CQ4@V2M^3@(wa?AtLU%c@ zq8d(TSWR32i7=nyKbgi&OaV+R24}kc^vOntd`Y!+vcM1OfOBhi2^tEUrV@QncwfkB zElXbMOCz*VO<#UtQ5L?tS8cjVV^B-|$G_8ui1O+P{V=#ua9m>gDT6t%jQ+sR^wghz ziet_-Lk|1TzAvVXXVx1Y$w<2$lL>~q=`ZX=vCcxD*Qv!A+g)tLVd&T;?O?Twc(-LBrk2lTA^}_=f$FSc|FIR+xb>!E4T-E&iMuJ^7_-#kGK&I?bp`#O(>KD}Z$X{-GJq$fE)dGnD3r`LlA z1aOX5C0djFY0n&h=Z-wjAnmWcNa6nl7#VwLl+9|AWLwqE)5`9j-$B`X_etYZxbk-A z1l@S3TaD(LBQm*7XT}jEa$1?!V{szI)}T7ywe4==RYYzCnQ#yjf`qEeO8@+?-9;R! z`g(OJRMt^VZIV6_iEmHyI|bMYkI#xH>fG^X)CX6U3^x_|&wnTG`F6KwH8c-Wh-aG$ z?N~=gy>cLfrV<`0sCrB|FM}ZUIw8m>rpj6M9qEti2I_9_o0N0WHg!FEL9CiRs;#<7dwEkf_LSA$fGB`3<@v`zxHk^GDYwiDb*4w^t!osZR1e! zU+nzDvyBAlMVps(eou*AzR(9&XdeWAcBp@Qz4<(C?|p;%JZ7EsIKAY%yC8aReu&nl z>PUHEwqjJqt1Fk&B|#W+Ar#H2l?~fpjb1Bovx?V}b5~oCy&&>`&?YTH5}Xz?5EK$} z!=ApTO2pI*NId3>RZEq+u^YYk^>@>d0*QT(DI;U#LgH*j&t54}kwVx&Y1CFnmQ>H- zk_y2~Kk<5|ylE=nLU)tk=EgH%d)XD^n{%cb^J&W}ow%c^^N1{CK_?@v$NE-#f;*0` z5d0!(tTOK|g!$2Om%rY$xPQx@4CTWQ%aqB?#Pev!j#?2n0K!WJa=j=eyk%7H)8dUO zH<$j()J&7}gW`Str;j|y-mjd>-&zjJEa9L@v9F2m$aB%NNQ%V7&b-E&?Y86dsz=yI z()^;bh>=c0d1RVw#Udq^V_`)V&wg9kQ!gzLwM1q=r9A00XjJlNr{r^yCh~gLtoQ-o zFR*nrz4R7^I9FpFeOB~8&I|@n;VJ-Zs_S`O^d5B+USThKQ>FjV-==@>4uWQGdTnBL z9MNUL<`udwi#ip}9gYTd9ZNLY%XEySl03H8-mV|!POtA%<{JG`kLfS>QTO3x3o2%w zOmYf=F{m!8!@XRLk>yynIJ8ApO)F?iPXX@QM|P7dd{`_Cx1UX_doA5pT_&(ozs0`G zt7eJn!(`u4=?ZxBAt&l&;B#YzODS{DySKCqdFSLnr%h4&fwzIs;tk~^3@^;F^8v~>3&;#)jfwO;L0BHzEpRw!_C{@_hO z-3;S%`_@+HfSVqKqgOUyI)`=W9V0bqzTXTQ_(A3*F6z<=8b#(1?=jZBojAhZUr)+s zu{;mXW65dmeMJ#q9Itcelwu-9D{U;^BuDO|O*t?j5BV;LV<=2vgT9LHFrSZ18!eCd zcTC8AM6G?QtUPJP-d&p9Kx4f(5dSfJzj69{=f8#|U2wnWyRPTOuBR~tQOJ@XNW*Xc zRKfQW=m(|qd#LU5J~S7-tTpg}&}Dh{Z6a;;yh``h8k~AF^l7Qw%v&S<041oxW>Nc- zDP8A+D}eef&qBB^sR(I{Rk5D3%J?y1vsRV<_JUjv$;n*#{(N?Y4&v!z^zk6e_0v->lFr50sW@rX@atPVy6y0FB^bx(h{vj#0u%4js*FIcPKHn zGmve7-T~Iv2%7+=`Z@9hkq6a{%P!>28o?6psMq3L}@T?~fT}nGkOeLLcB1XA$SJF>8 zQV#0OXhes^!e;_H&jXqnUj{mrwOlANYhLKQDg>kGS0kM#&kK_EdS=N4P1fJPENwk* zO|H%r8x>ZvlD&2}A@w|~U!vN$tv1r!hc)&@7ce)rc?UHAO=ES1;yiiF~M z7`Ls?Tn-5)vMM!a8FHuehP~J~-?sC;9ZX$n(LKbvsS!o{RF|=h6*i01V~^6?Tr|JL zn+g7K+b(jr7i_yGOU}o-sJ+oAjr1-kdT#t(b-eDo@-U#ucb}5_^WcKtK>-&>E#G^I z+G3Ir>XP$$*O(o*q$>qq`*8dSzRFPG#KUl=`O!J{MV^?lmecXi9j4yI59Z9wDMz^p zTc-D#w>RsD^|HRkfUG-&3+Bni>HWPe8{UOWykI-lTgQE)X7?jyTXdb=HT9r&pG=8w zWnY6Qn8@OV66f+Xm9UV^ypL6skhDvUM~cGB9qLcQj~n$ESM+;q`nt7;Mv=6oBqfHc zxzZDGOkYBF``Kw%OzblR{o8DR(6BE)v}~CU7zlkkFc!qP5N(|q+J9CV!PAJ`L!&<1 z+D-LFt8#95isj&Dn0Zsi2lMXV3FjGAQ3mNXGXeqv+RKL$fmHOdwd8)yQ@Wyu zl=52kGN7k(s(h}s09)9mt?PkiNKZghO>Hh}u|XSFkkVd;^f{&y={PFL=rhah;77P? z2-f{?5$_(}$8OeyNMFR6P%**)Bf{wSgkegAQS5{fj)XC9QbNsS2XSS;p%j@v20PXY;#m@F;s2~*lp3;ZS!1gv0QA6kZ)0vZ?k7@(PwS*>u=HM zZ*y<#2#f4+LND<)uW-7QI3Cz@-UMF#Uuj2iy*2)yv}67!?WP_EKP}Boon8JX_rHYx zn{&K(|0nmW9i=ofPRLu#8VWP|GSlBp;Y+4xSKo(Qf|+8qQiI;HbKa8eg?fg28ad`7 ziUgP(cN;ycs+sMD<1tcELqwm>mqg((zsI>lKapoxN6h9$_NLzh7>?DI1c$}gZ)SHr zJ_4tphtH2=QzE`ymqXCat|*Gl&S$W}UDYm(b@QoUd@jcRrt9e*46%Ri>hjAH&7Oij zB~KmRc#CA8-aOc3PaQsbi$D%y2wGN51k+o=RVvXq`3=!f?O3r{5*%sK%|L| zhwkGZ9UG3u(dY0Buc330u46}+2?Wye(9y`@>vwqD5`P7?-o0A&Gc=DR+N}UJz~H_{ z7soyaC^7I3{cg{pq&H_{Z5!u4qFpAoLL_b?LI#^thp;Yx&mQw3L6Apw1PK2!#=K8- z4))}g4NPt8+zguVpTjV?9eBOC;n&l&wU)L>kusQuZ)33ONOy2?&%a@CSz-ix)pY^! zxo@qVyqaw4f-r;lw#T|zIyX1W1^IMAt(8j~aIz-sn9K%Vj}{Jn@92l#MjR$@3g_%C z^{XXmS;FT-*yFelV-0B|YH(%^gSX$t6kWS*{H~kg`)EgzitrT#(1O> z&LO^w{dU_Mo5%&kU|?Hkls9jz;6i5T72Po;^SWo^@difWTn@5Ex{1EPbfkI8No z3gf|v_i6^suMFZY?DsNIr?93T+Iz>`6=YA0& zV~(bFPp8>Svpe*q##W~4=^$K6PeKjbzrmkeXdB-&+(C1_J%>eaEvqz`>tBM=j`j(ZreQy?y zTyyAV$X!;yj$viAeY=5{xxqan~%Zc6{M8VBo; zAgxIyJEhH>&l-!-c+Ts-mkuezevpSnuqxnr1!>HOnz zBSSSV3uw)3D4H^qcK7i>{T^pon^(wE7`2hfP_$T$xTf)DrPIcrKx0&ek?`Fk9-$q5 zmvAI|P3H>s> zlak-KvX)E3YZs0aS>8?ikUU>Obhggw`F#ebk&I;8|y*;xHwKZ2{Ce*y@Z(SA+^EfaLqouR` z(vs3QhLsJl1^r!_3UKov(HwVpSIs(u{@*vVcp9%4=*lt)A+rV4T7-w=4($XTmnt=Y5o ztDAI^7~KAiIgjAuRi|^Q^)*s>Wni5iE?S-_Gkbq&E{VgSsmb+NeKC6}i!6SKd^xqj0$7I0oMMOb}CiS6* zu5wmQ)#?X)ytcQi1UKjRy9nsq{b>%S(bM4Z8IlS$YfNwFoF1GEjLx9UOpkL1HgAXg zJM_Eh%t5c|Srk8%4CiMPjLxkg>IL=1f`dOu8LVuNC!}Qsj~6XFBh5IvT9@WMlP_i; zv4hnVzHGtfEF}D9w4LDJxi!r>yQsdzBMOXs&Gy+>n@KyGl`KcY{Q~A(fPf-`6o9Yx zwx@&h7OXnoP^0{zJ8RkyW-Lf78mn*?1SJWL_Y|yYtHlINKTR5&WCW3#Z90i@nq4O! zBF1XSFFJE3tr}yUQTdwd3y(#5II>#A_!?D)K#(cC)M*tc94>7h^1iQV6?M_G*_%%| zR|yq73Uf*ZZX#9O=~|=AMZ>`&<0ZLjbOK5vRWhaMf&%RhplCf*Yp+n8Q*XZ|YI70+ zbNJ7x+B*EHV)qk&bP?e_3kcmzzIE7?M(^Lc;AwVtqGfDrfvb``J>;PSu@q>Nt)JgA0KU7q6t~yTlJypnik_SiW2OF8zd@$gtEsr{@KyC3TYtXqP6?T|V zW#;kzF>VU{?M!FYfZ=}9IW|B<{^&}UNuOSl>vo3o2cWG-309A_EJTmmyp*JaGex$y zgOrZ%U{gYSDKyF1hhw1WNB$-Tr$R_eVc8ic@PYJpa6|f>J*DZB-q_V~>gF3s{Ca^? zQ08?i%pQh_oaH57OY4iO|K!%U>LbJMy~}yyu!m{=L{fQC?kuC*rV?F^|E5yA%3#Eu ze@KMBYg`Ce?W1sIcM&QevX}-S#>&Vf1aeA3?sN0OiffWWm&+plhw_P6jD!R(Gg&pl zx-iMCCKR_=Nk+(?kJ{R8AKuderwm}_foW`G zDekr=M;uJN79%QT?W44v=)>>4iNV9DjeBEnC_rQ2=Dps0SSBJNMY^7HI#@Kx{r(im zSF6eE!rnWg$b1;=hd&51Jl&Y&EDI-ZM#YYgz4bxOmyX7^KfLqK-=TKpa<(=mhlFuj zXQw=isknJB4)dcol5Xk8^T2elmpF3Yql?g6EWQcB-?5Z(9hQ139#@;evQ}z1+gkk{ z1MZ(fA$XJ<&SZPrcKCOJ1ZpMHK(`Sfb zmn08^og3j;XWzJ8Mml!_6;Lw-E(emXSHkqr+q<@&C!wg2#eV;rh#Cr)!vOmrPeBnC z9GjkHihZ?A&o( z>p%^c;yzc%?<}>j%#PZidlHLz*~lt`$bC-@n(Xy^pM6-`y-y8_^|j!@vAhsTAL^B< zsK8~LRtTVwB$HE}*Z3rWpyvTcztW-@9vs%(I*m2OLIplUKM)YeURYsO;$&zBC*TOD zuW#qU&;e-Z%NG`no?enzZ`11NBJFJ2M@|L3I`VL$YdC$!30BuiFytLhj(}lUd8kIr ze!jUAjO<#Mo&&7lql$F$9Zsj~=U4w5%W%r|1la}&ac@7k%Z$^@FDNOpPX1u} zq1L24&BnzsJu|OVtoD(_VTA2V_h(`0m|5`{6omgBQ^XaW>i@)q_8*|*WcmL`gMf?l zFAmP!|Av#1`6grH4)Q!Sxg5O0HZJ=aw~GzU^xy`prW#sKBNLwRH3?VSCW=Wal8HI# z$Is1C4iJQ{_9x@WZ189j5tR(pQw%30Yf2ad;|IYmu0U6pM^`CBH|_e6o0h{Y=l_qZ zFAs!z{r>;nO5K~{wo0~pb4v(C_HbL|mLmI32xZTZb;i}E5VwRdOe(vvBs(Js*=7_5 z*|SUxGnmF;48P}jkGl8w`LAZid*1K!obx)bbI$8|MvKK*!?L=_B9 z2HiT0Hs>np;cwZ|gSuTaOsRvRBO_t@i`1dek-1V5Sgg-C`6?NRI6_2@qHmOJ6CB3V^6 zt^OkAVYzOjdGy(u6MY_?i#u){b0@qk?$75N`%|BzW4Di{o_1EGY(7-oR(YoS?J{b8 zEbvx62^B!FJ~kIA!2WVyXqv`9*%HZvd5qSY**$LfSbX_OOQVnQN7SK)L#%3CEU%AE zrcSz1%cQPqSEQ`9wQvj8G3wFV=7OQ6*}fd@+#3?sN>;51!eCB} zfADRBf79QME>M{H;^cS?{74FRpu46-!8UHMl3h#MP+Nx7>=oyn6ZB=8MYee1Ivzxsv$TWH|K1Ww$inD~x-Nma@2e(Yt^G5^%dmF`g! zDqZZ^4@>RJ+rn3(npyf<5@M#g#wlMyEzrOQbea4y+RQ*_Q1#o{4%NOQy&L{h`A5i% zOR7eMlK~?~AKK)UIuT=cimFI?>CWayINx93Ut3)HBAUFJYx3#Y?2f*~AeR@wAT=00 zA~pm2=168-dxB4vzk}f$Z%>>HH2g)<`-j-H@O1ckPu+$6-TQ@G3YRyTou!O-^lti6 ze9IylzLikwf-{n5KLHo3#OU3!`b55PVDB{V5ny=RTOsR5%3?Jg7tsBrW{i`Vsg>^2 z*DHp6Oy{) zPNy!HaO2jC6V-4%7@dxn`NS?g5AAeNZBG6iVx792mFXI{zeQ`QKN%<5 zFZ?0FSSfz&N`Z%Ia3-bj9K0h@uRl^Y*$|H=%S~MIGPHhkeVVA;cz)zs`!^MXmu!O@ zjCA4Y*`Om9d6<#p9m#UuZhm_4VkUo9mj&lIBJbT;!Yjx#a}m@ffMYC&j=Lc_UDuaVAlU^n&cheRg*B%J?58VT;U31M5rt8@?tqA4fKTjdsb4D6 z488o;<>qbI>X7>q*;oh7b>XNJtonez$NL+^=hyo-XNNB3PFE99--_FTIE|$fBein=esQo=##02%emvS$1r^>Yn#gcq+AP2zDXm9BpNR95=Y0spzN|y(xJte z=%X$<+nNUZY~4Lro69b;?Iv#emqzJoKF81uhjQiS$|`t+Ug^y0Zp6om$$EG8r<243 zk=CJF60tf>55m%2C80kS%r#UsWV+b-xD)Ql4$17NV%;@@9~S4f3?u0wc3YE+7=6#Q z!jWMGj9!L~P3CTlx)*e?oj9W&jeyEK%z!X92(5U%bnB)3>(E^r!Y5kG7{q`gjq@oc z)E3$JVWPUY1Tn)>6f}I(w^KgUeIRn+Pc4bjgM@Lh^gOuu1ch5! z9<6IdqH^ALQ`nHzzn-$&yy#XWg^B91S)1m|vp4I(x+LVGz%kC%Rn$34H(LWf=Fm#o zUG|we3v!4kg>o&r*v3R`Jr@D5A7Vk^vU`#lcFj!0% zlb)r%RtQ_W90}ZB8nvn{fpN||p|nW?RU5TS-K^^hl1pA%_(#ethpWR}VxYKRT}IkY z0c6-|KcU)_Y>vcPbmKVt6)v{5G9>>9I+!@Et4c?!+w}}e^;^aWl*_0|l*J#Nc;__* zE|$2E-u($>J2S`f%!%mJb;?brT%+^~825ipTfI|@pHV!a{*PR?`?01pTVlz!6s$z6 zpyT6KCTiho%lXXZ7sAMT_$68y=cSZ?H~^9!uTo>gp$6Ft(1Yl!tmZGdT{{Jp>_$qb zuz8g=&zDwd%}6#Wb9l?rTS;RynzuN8#kv>PB=512=!&@n%`UNWEu9}D3D(0}2dsyv zOOskU9==f-SC%WlZ&wE4S6W}Y!Z8?gU4sPPpdU2$p^7xSFr8GED<1fF>d6#O?gKY) zC;sr@8&QS4%P-B+{Vj%O_m-=DE1kj@tSO|86y}p zTkL~*gevcAuo9@eu@?PvL%-;xNV~y&IlA2PK-+_ktcC5pVA_7^-FE)&gdGxei>eP6 z|E$KGfG9tP9=;a(Q59y9m}S*vy+wiPcazq+5a_4SH)usS@Oe$G-age*Q|~Or5&R!6 z_cA{GM9$@)?V%#=LFLkdr{JGY9`4ziH5C4(8Z3vOVCB*8%aO`>x0%>MY5~i!2g66i zq3lulua^yp47{PSbxw6JTni(KhKMS?b#V`9yI8Z>hPg+%@_^|*>QJ@F)cgGeYV8jM zt=R0hrzsx=DN#kcRQk%y^xoH zr6NvH&sn%XTd7OknImjKH0Dq3E9rV#N1m;EIInLKNYwT3VVAoSjy8da=n_(qZO0E&PE+UQv6l`Qf0`|Qg$IaBd@8qZdiAV>ZWYCl z+`Qdy?XkRTVGhIf==zA4my2gR-?*-nQ0vVsR;S$Mlzj;x93;!EDI+VN62Hx=BGF)z zXm`%ty!Jgn6B8{7A-~9dMwmwk89M(|cNgzxxn=-PWmhQIzT}-bByRr#N#q)SB>PNs zrZr3$vY5hzVvO|$INiy?Boj)^AgL8t#ojF`Eu17n8XR1(XxjaCF_}D;Vi26`nuYRd z?@M+a+JnNwh3KJFMR=ZJI)H`v;-?p({AIAs3iS%Esacw-q`#MYJX{A&W48n;v+*oN z96&*-JW=B)%P$S0pP$TXD$jUXoN#^Uo>FYJuU9Y!q>WFVG3g|`)IZlV8UWNZ45-bX zOtx)=ZpIFe+chDPiIA9rFS_dzE1}0f7XbhU`HGRki`{%e8R1p!taGgwFC*ym9CwGk z&vilF1qo|ycISZ2BN_;6Z#yb>#;D{~a!^GLSd8dNUCa}?dA+B5A})Ko;D>)3OF7D% z8%cBR_JHsdmx?*|JsyS@$%4c;MeVCm?NzG2HNsN{;5N07{k^bQ5+?*k_ZF}B6 zX`+T<2lN1|K>dh-lP(yTz!%jr`NpM>#XCiVNCwe@qKn+Ld_Qr(QQTWfxj3e{!gFIe zTs%{B>Ai)md7ZqugLl8mwB>?apYBq0SFcD8`J?H4_E?_Tp3*NX5iVd}{}c z-c9pjb5X9Jx6RX@Ius*o!D^f_q=99(1R1=mE5Sdv?W`8a=3x2c!D0jlRhXfan0?cp zYx5a-i{E_u6mBG_4ZnP0W;fzRCsjSxq>XLxDzCu>Eo@7sBaC2Gl!su^RDJ~V>{MZP z=pn{fQ8akQn`#pD>uj(;Z>|=};M+~4T2h&3K(?^@NU95xEuo}qA!$$P0(0PS!(GTl zqEB6UCqsT!%#Dn=BYWq3d>nBRv~&YQ)1)hZ;!mBplrnfw$daOz_IFU|(4(0@39nv5 z68$lm?ngUdGz2hwzMZ93M#biwa>6Ujf59R5rLI<1*vsjZhiihbv^6#EH-3*qW#{kO z*B%9F)dLpjn_`4s*}LDRAR2|N2`hhfq-%&34)S59tLH4Wn&bEeAyxY|?Nl6R#Ipf^ zn`Eo$6A^%+3_gWA%VlLi154b?xtY5O1210)tX*q|i5zFaP|+Byhqzk&hrbdZZ-hq)HGa(9^8ixUjx(Ij)y+;IRfpNFK$#Q1H!~a=PAb0) z+a#?s3ShGEn(nZCy)+9!s(k@9R~;$UF%i`b%dt!s4c6B*HcS-@%^wdB^nSE~K${T~ z$nmk4lNh!%_*io?BsT>7FRpVcOZz39Q~i}^UK{=21#{3;n|_{e>gjV;yc)c(zT{>uc3P=5lP#u zfGQmJ(-`r9qolw~R8CVnMz8&28s^#p2!ZYyVcf@z8xW}u{x>vsa?a!o$QYOoCvdQ8 zzoO38c^!c?#55o zzxpwW^i-ky&Tb1_u%e60*&g(<>_Vx>%nEnSfGSI^q9-sY?uZrq^U)<_6DN5;gy`UJ zs+p_hpCI9zF~#SVlf`Y3rU$=`LX-tF&@vqiOpZt4i9YYud)C%@Y3?@;?OsHB4p@CE)PihFUFYm zMAxLrN8SaMxYE-6cKHqRG_-PqiQT4adc5%vs{&`lpKGEAs(dcZ{xoyOfzFJBcPXWg z&pWD?{uC~~*)_w6qh;3&Av!InWwvz59O4r>K<$Num6^bq!Cuhv098aP&gkXA9ljYo zKQqN+A?NDLFi{|9!jw&&rR>cs;il{~+cPiSO_(1;OzrL)f!vrslKL8kNY9t^Px|fA zFPNt`_t;XpN(TazC7kl!z*1$+|IHiqOnN^##91X>bosoW>%tw7C_r^l)_SGAZz0}y z-QC!HP*y8JQVf%RB=blxNZ0#^OM)7W>i2vdegk_*nLVlgG*$B!fC6$_5>>v^(vvpQ zFOg{8R7>7lWqR2g5-0mvT_S%Ok|eYwN*;Sn@-hWu=>}Tis8j@yj9jP{=#?I%?B1m% z;LqMqy#aWi!bIzy*t4n?6Zmt=p7nam@5irqd#oJwyJc@72h#PtO>XOVIP&u(-@=5v zx($32G%t84d{PKOH4XXwF&*CxZNGiu#x+zcVch<%!;;NGse*bbvQJ0W7$ZL;WhLHq*BIfc25|QsnbGyovwt@YhQyMkY}kW z=-S&&)^ngL0Al2N`xCtF&De*b(rvXB{ErMivZ$QDeBFNAy!?ga0`DMqpejCA z1>Qkf1kR|g;?4}^0YnqRGwUnIqO9Da(g!xB7^P8{KEMRKNnZODr!LoB>jmMh#!Hmc zitDbM{htin@h=Ha8AQ7>M?LbpJ#bwPs!*ILRbe6EgW%6bosykT8N`DxVL54KUd7Ag zRg^$yP1Wnq`m{1x2B6;6Vmaxy%Wj19T8upzP&11KlxWoWR>KySdp`z#Be>9*w8KE} zvtOWdo3KVO`>H7aAS{USZu%#@YNtT$RCj`jYJSeZF>NYuc%@S7fw=?2F~31(Z&_E1 zZRcD(2)Kd#H}xRI(s720+L3;-eJhvHf_m?YJ7dH~*}Gsd%voOkQ+4^*;g~Es5A^4# zf<$l$pY;`5OI8vDlzYVHcE8A~ibOOQ*wa)kitC-_a1*tT-Sno`>*&!dJVQ|YON7f+d_7<Ohzb5YY_mA}wvdK&PH z0a~$lx0Z_sRXer2+&607&6m|e7kx9SFmXlyUiW58RK9WYm+pkqPES|n)oa8&W)`kD zW^G%-Y=I;~L%_x-C)5BYsMs{W^N-=x{3yeRY1Yd3@Fd{rf3(G~WSMA|W?q2_#d6Ky z_5ClvGnb-DHZ>J)@^k{Bq`l@dUzjf?bd|NI^*ji z*AXB1r&!WqIA(B}D*lCc0Fz>bCkyPen+Q%>r(K4i%`dRl9u^8}cBAJ!Nf1v&g*OXF zw)^97M&7g$VI=R(rPc+z0B*oju}KxF3rk{7_ByCmzot9n_p0A=mP65Vo zQV|T|6MqeJg#)MRJyFqU!)s>-JtDa4U*<9zU@^OgAZ9RJgW;o`60}nQ4S+uEif7nE zle{KgYfMV4qK;0LhUX%rxQPq*CdX@E>IW_F7{-sN?{9Zm%HRJ%AXM`#=o^TJ=-j18 zWSEaTaIo8nBGs>J&w-seK_7!1#LNy&oaqS*Ivt-Tyg6P_M4! zq_t5$G`sgs{+2^9@GIctJz;B4r^zaO5*AgN-zvE4pZpF59A) z%j%DqELRW35KCtheyY{*VQz=5WZSi|97gZihDU&8FJO_lx4kp#AJK2>RK!dK$aA;m z!eUoDX>l*?xU76l%U-}ggrUM*6($DC6P!W#T6PPSC&s)ok4YFE|90>r?Zej1&=)g8 z(p39u#^bKoJxKhAC3F&4PzF>sNX#=ZVwFiVZ@s26V3zuB!K`hp9V0_w?FpmC*Q5V} z{wF#h9u|BUJSmup+zwXoj%kE!_fGH`Z?6xNt=`*d+I1QTfvH<$|Ug=JF({2e0R;7Y(S>n_EL!?ox#F*QpN|#k({5szE0JE8D=?o(oR2etv?rH1+0t!~Y564nKZh@PuElL12-Lf6*nsTJNL zLKBjw>yk8p|5Oi$Csil@V!E0}LA3ILb7X2`3u|mzf@HJV$$EeZy?PtGy z+tbII0;xPX*8XJCW6l8KAFDPYSQvxN`dv>ZshR9D-Rix2@x$F3c?6}m$7;sci%kI2 zTwXw_P@0#LfEhFs2j7ZRYt;o+?~tekA|DZuSWCq~DnP<_QTi}wF}Vng2yRUxRY*EI z{bskiyaR&p+>WiMBJCrz^Y8pOtB)k^30Qm&9#!gO_>fQa-Lo12jTvU0IY>fhepKZl zEk?N?{|D~}^T{^S-nwFK;7HR{tXjy`yv?MO2oc{Gf2rkfmuz>!1hnG!&c+>=#*w}g z0N(0S+XG2?$S3EbgilE$$Vi&3QwT!5^VH@oq)mMxg0l3)Ljk29fDyfFJj_89XU;WW zwnZmaIHV+LUZCr^wdl9~?GjuO#8V_p!N>H5)JrD32fo$neNF5ck|_JPk$=TcwmWlq zQt-8Rwu$f?hTbOWI?bOXh}~$SQm%a`N&8mw!-DNET2SXVu`-Fx+Vc$qZ#eaRFxR=X z2qeYc(`yV|-bT7ruP}5H*Ygy2^an$_ zt^v3~3wgBk_yj-WM-`LZ36SNAyYIri0 z(qU=)x_jjX&1~7$1qQQldxG#2xswtxYqoW*TF=lt3WXq^kKzA~=lcR}3-S#?)aR@J z#Y2VGtG5ynJQN#4!ui?9t;L@~ILm-=E*`yl9?P}g)K#Sv@UgvZ@9rc9aLqDu$09^& z_}G65<<-gG+C<+h%L~u+VU@vtT*OL|$K5_o@+t_u^wX`$a@!LSXcPOMtHezP^K zj|d!u)?HC;@#(nHXYO;8o4itV%a%9!U!?49Bi9+fX~ud zz1U^J=Ane!{tVC(QTLyFb)vX$BFTgd+Y``@Ma;lsI z+{gD~dfb$48!B7QUjWvu8ZA2rVbtp;3~UL!bC#`5MbR0J$A%_UUaz5~*q?%3yt(N) z^+WXT?q~s}#zQ^br0+v*#2Dd0wNLY9)oN4|xTJCB@h`zn2;VAUcqHuepXWSSAmwm0KwYYGp-yyr*<)O5zuUIO0ff?Ajlr#%)H(r&=ka_% zlCHvzoi%Dj#4!r<-s5}1AO!YOnLPhm73**JmArG?;?@$#AZ=e2N@T-i zO)0a>`Mc(d2jT4?9<_bZ_MV10Oo$r2jD3q3@KNk`wB{iQRaaxIda2||^@0C-X>X^% z;v)DIi21y$`u1ECAHQD{1+J&6mU)$at@msn5)m4f_64ROLru&sZ+An3uTX%c%>9!C zpp;4KPRMzcQ|5+Fqh&h@7P8bf0=~?2S-XjL54LD6{5-HKn(JBZ12aWXJm}&(nuurc*7C{K!DL{(s;YHk%=_UqRX+mawFf6D82P z@YN}t9fly9MW|2r<7QnQkjeY1Vb0e9iO5-=g=fwirZuo^w@ zz+BAs;YN{OS~50BERr*42$nbb@}-6u&mDt(^C60I9;kPU7b5km zSL7Fm4(E(D1!;Zu1IOBYH71Awwv;wB(Ywi^fz1QCdf(S@6$2N}ey+8L9;o_15V6s+ zcT)#ut!QIws3Wydg-6pkc@ffeGzV)f`fS78P3tvH9BK?Nl8J4)R4YRD?OCq$OaGz) z>2%o{5?uhB-pILfhRR#TR}l9D5Dv4-AJ1EQL3{5-oEHy!4+Zg@v2Q7Lp7f+++rzHk3Q20A(YUQVFA7Aj`tyv^dxLYLwoCi60sMR=hd&Zx3JJTnFD?*aQ1 zBLnvC0sj5pt|FOt+U7%)KbXgpLGx*wg2Udn2v~3$^IvaIJaNtaI>91WzuUuv*0J&q zXb|ML4@5ZzZ-=;-qGJ6gR>k@)tkZcs8y}+8m5RVEfj9%(@xlXgx-;E9G6BOsOGP8m zXR3MYe8xaC^pFb|A9^a+fmkCTg(|r?h1_juC`s|_{uspCB+c!Pr z@(r_vZt)|d@kZDYdlesn^3^{Lp{b^jzf~CYU}FyxoVD(NUO`tfO84RKo0A0{Rf$$Q zO7bSg9x06gfOxGvQjEm;pZ?mA^x2kBLCS0VfS-sQL)G*_tx&c%J$PTuOoe zHu=;CoWi7zM}lt_C|^|r2`<+_%c~R_`~XP_t@dy~@N#cuU%ks5*}C??619yizh?Jk zaA#Z)6mML;pK;p)wgiwOYC<=fG2I%SkIUMH`i3!f;lxLs*P7$}3`-f)YP&1e(Og7W z(mOU%RRlRr&-_?_LvL_GVMz+8LU(BJ@9G0Va;jQO_O0Rr(DAGVb3;}A);)X&U>!e1 zUfelI=#Pdgw26f!Hg8_uUezk!R18-Pj6XkXfS*ikrHEODJSW>6%V+YGXY3s3MQOdc zZ3y9qJn8K23xim9S=B`IxIY}F6_DPn_b0L{M@41lc|7xp*)k~?AL^8zRBrUavT6d{ zbDr(;Cp-j=?0ssPE5vA;$Ad37Uu|-rtXzFf^ z-e4c+`Vcqa6=bX1U5T|po^TKNg0B%`Vx`{ufi}966+K&-|N=O)99Nb|>s4$z7?DGVNS>H@|G>Vr;|h zs1^+Q%l(0IiyH<`eJ6P9CYlJK+LU&!te~naAkVYv&zAEp@zoPuNEL{IwQTOm8L@I5 zWa9H9<4tzo_ncJ=hv+P*cZ4W4?)=B4Yurfl*wG50I>k$PZlR(#k-wX{D@f~hFy;qx zXfWS5N10YYJgPxxE|5DB*&_MVCN5;$>Or$<-hoRgMnGn_o719+C<&`H6ill3591K5 zc2djSy)|y{VEo*0O*Y_91=ki2XVOy9KyHyfh27pR_Yk?~qLC}-w}k`WEvv*C6_WRp z2M}6BoMm)1Ux45JHU*fi*rFYqfz0=nnZ$GcUOa0DafNH=9{duJS9HjI7C!Lx4C=I~*p*m8j6+T)Ck&fogRv#aUjKT8__+y$ zGh0hbg4!iHPQ+?G1f~F`4Ct*aUmg&Y!|^*24L;suVz#&)`jHX)vGnVWLJyn4?C>?x zph9G2_id_YW~K=VAR`WsV)P!F9d5{{;U5(V3#f%=J2)Gae4Z2<|8&5vlzf6q5Dk)f|%)@$*69*^jtUe?=D|Qqb`y* z&>%-d?pUR>jvy!@=Gq>9s8$R|9(V|)FKN;cCnVkbSr7Q#{mGp=iy&K1%p85?%-rYz zerFT={1ttvfUF}pD3TIuQYPT5RU0gitm&oYGbo>nkwQ{4!I>B_i8;>GS>9h;Z`uz> zJ}R;wE>;{KVci6RmUsD^dr7}BciNg=#|@7#!@)%JU4C#c{cV?WfQYtg^^gNZRqI~A zRA8k_gWTA(WfrJ$1#a26MeVH8Bd?s93;H~*TTw_2$n|=ItEc`S&{SIYGQ*jtwiURP zQ^glQCjv9h1hs;+6y6gEoC>^qSZg@A!?1v`H+kW4kfsq`$N!dAl7T`BT?gFaQ1vHO z?f0V!WlMb@-zSWYB!>J%nnc=xT5UOpKt=Y2VzUPnqiGy-#Hn(gMwu$p$3SS}r~j?= z{ZxlL&}IHg&=}rEzItnY>Ce^O>eU-r55}&@sU3q&CqAjYYgN@`f!npi428;V`y46? z*;^ZX3)#OWdCg(&fk~b{>%vlEBe;vXwJ2yB8ZSiNt#pMOoTC9+5jYXh9TvDH)^&}a>Zq9c4e*|Fz}!SIOMsg}_o4TSaF!|yqXG}+h3L2lr+61Wky)5;}#-B!Rn z<_7etO1WI{_iFNp&#Wj?1D#c@m7DTwUcpZnxU>Upj+PAW4s{ED`BFt86HrU36^3&G z;Z2gV)u3kKeR52xNo)H7Z?*VY=s8(tvf0lLyjk9AMa=>os7o$IrK{&QnB%t#aSd(z zsNAr6Cz@DjmI2c*i}Lh!&WQg`h+aQvdPC>IiaTzyPQayjJpUnHDBl|3#WEfXet$Eo z2l1T!997NL3O>Bt7To$(_9jT9cyQ_`8V@P=l13S_kiXc@sR}JB`~~PTj(!3P{CIHE z4&Z`2H8Wo^Uyd*?ai?XNaNbioPCzFqtrbr4Dgq<`WWL*^M?e~;yNFt<1_g;vmOzMX zBUqy)>>~t%Zj)H%B!&7>ls3Yy82Oo-NeaM!mO`G!ljbz**Jc{S zj2TP2pEboui#)KG%&VE;6~&y+#?=S@A7UwQzMt5FuLy!*S|N4-5IkybSOvn_>s0wH zwYC$3uR;vM`imTVreF_RR-+-jrKLvD#@_k&0YwS|e;8;Ei=jHzL$~a}r0!>!@P?SC zSJ%P-4pAh%8G;-0thzvcI5xy8*aKw%KsR`zIxwK#b5HPn_p3-5^2@(H$4sXuT}i1h_eOHCJHF2i zlr|r%m_<25j<%^s4@mKT7xKAQIj`|W#fWgd_ILiDCs5u)2>^x|^-FA(%}>mUR;+!` ztek=T`z|oj4X%;&gw~T)=bcor{4TJ%<0Ym$LU$robgme9i;9MN-ClyOgIa>Fj9qtu zMIM-yFR*St@H(p%&fo(X5Ll?f6{-l*NKSC;)n^~C1A*Tw_G+FJp z-vh~3eY3&Nt!m#xZcp=%$$4RJyMDUh{u6DkF0#?W6V-l=bpK*2h;15EPT2A;PVJTJwD zfAQkJ&AAu|a=Zf!wFG6kYL5jCZtSg`xvE!jf=uNt8}@bnDooTt1T?o9{e6T#LGE?h zI$0+K-H{Sj(TNysSO&S(+l*p7MO7uHUwJs#aMF|uFu)hf6>(u~3yQa11(-(bQ0w*? zg5pck?2vK6t^C9sS#qr|Rfi%b`L!*t0h#-IY51+}{sM-3h0wpSAsi&bWPR!lRIyj+2in$L)r|3ab9{nAj8XKCCHhl3=e^3tVkpnpMLh&op&KbwI8a z3UUMnGFt&=N%`6-!xEi;QNUF-APYnz>-SGYg&DWK3L8zsYNlKm=V{)u@Br>YCYg(b$uy$7Xh5WUSqtQowrYnjE2$o1XxH`MnReEP5t#_Y2AkT?D}-bTt0? zP3czPQ-nrkvBvx*9j*vAkZ*x?znb!+p$*iJo&_1HmW_ae3IT=p^})+XAnfe^fKLeB zi?D?oY7+M6t@KEJ-!V-7hV#>e&^pdZzzzp+u?UeGq8u%h%L3>#h2dj~mmsjse*PMF z8a#CQdJa^E$(7Tkt0WYeJ89y&ssmo}+okL!v(LYgcKq8*<;Ei6X%Cv2p|RYOfF1RLoOidc9$&z*)55gRQFNX6 zz=P=C?S}7LgcAy8-wTwR00YEaT8akaF0696Tuw&Lz;H**0}#d?s9%r?M=ZZ0kU@m} zHVj_%7Vy=3w}a|}2_F6)tx6AkYA90;955nq(~RsF&XfQI7hJz$FN%tYZ;j7sAgckl zqZ2yfkDmC(i#a01D1^(A`X~m~(hYebPkuG=--dQg^Fw-8UL8c~ z9hqlHJfIf?`k@2rc%^8{rkmoQN)o?LrrPS7cPiB;WYA4hBvR)Wn%-$Hj z5UuoUt{I+xjMRn`|JF;ySGZf#a_mIdL4?SAJNOY$rJaPF1+TBWkEDo)O=#W$1+`2f zT2TB}epVe~{I1-U>za={j`jm@HtLbryh)JuAB2mt*1vKtv*FPnrE*t>7ym0JY@cG6 zt_&Lh5m`f+TTt1i0 zTus&NVhw?R-bgWG<=KoM`)dtR#H#~2+J&KaNM-%+kb#~)^U&2K@&E!S*3AG;7?^M? zbMmYb`YFi!*dW({+d|)sa)sWcBUKK>cBPXF-hO_18oT^2T>e`43DItXCcs+i$^Klq zM+vp*qCti6h(LKRrdRn$T!x3Ozfyd@Eug4DDFf272^5r^(7>U}r%0_l~J zt)|=qt6ajfJPpQ6a0>;SzH8X1%(`4bo;nV(esa#tKOO(xs` z6$_+($UmZ9+z9)&7z)@`&2t zLBuXZc8dK)p0bN{OGrqW?w_2xzqR>%r(BZ8USVc-_hpI3P6<>_*2tod-omoHJ46%) zjaM;h*KFkkmo{8VeEb{G3~x+>g#t@nn0MX|jSq*K77h7P!9eKPbf7~v#v#nKX%)L; zHgY$l4FmW3g{nI5lVM%L`l=@UzLq2`W`Ns~&*% zo6(D<)RV0aVhY3wPT-$?V3@NZ9VAxC^^M7t$Q1#-H88o|Yb0L|$0XeBu64vy1XZ$8 zu5TTGp^fIZFAamV2kfw-yl()=@XSHy);P0E+O=cO={wgj%ItjIfjS`;W0K;yu20oT zrsaHXv*y;@UNvv04itGVi*dO|6B_&55YAs54&l1gfvW#&;(LKTzJmnq6@^Y>U5Rg3bmv8M`P^v1fV!R9GWNrm;DO6H?Xw z-;G?nnAuU?z9trBy3g(tdsm3dXDz@$U@g((9wfL6MLo$ykmc4r=i0tGZsbXNU*aE@ zl)2)OEH8`}V&furXk+x?S4_$E&?GR#qJR0f_haJvxfgw1|0IH>GN8}xb#5zc~HAMnBN{3Oj5{EW}Fwo1Uzr>#DdvPT9^1JhIwKQ z`|TO9NeS9O57CeE%`!l?nM6vqI#N-j1|^+B`5vHC!kr7Rk(7d%hh^MeO$Yr&*O^OR zi1y`<*KE7j*j#QMXnTKV9e6|d$2;xy z_VGw9-0y(Xv6~SkuoB#eBmJ)@n^cORUhhx6ij*LGXX5;TrWl#50lo3JP1nDqcj9o8jQ7HIw{DYZi-*!PklTAzr;|Lu&U#13v|UC$#h zR)q(k@{K$OTu8)j*H~lYC4_$T?b|beEk!i9z{3gZvdwt3A~5jV?vJY7ISYzFWCu83 zAS<*U3g&cHvH@H?EXdu?8o)Ef%~1-c0AquKP5l&UX{Boa+mP^&jt45A_7$vrz^zLX zuqLNxM4IRxI%sJplV90@I)Cp)4WZL+;JZGtmyn6WkM@c{icnR|AZsV$Um|{bvVW~@ z<6;IfRukv61TLGoa*mkirZexst&Km%5Z$#<+P)9s#r^MArgYbGh44skO0UlLU2MYv zSnDC$`G8nu7{g&g8K^=fgSVf}klgXF&|Ww%+b8uw)iv0SK?fF>GRDLqjrRMm0*tDJ z-kWD%3>qeRiFZm+h>^eR;{Pj{hpP$r^FsU|tdPt<+%y%i+q>Zmnt>@ZulcX27l{*;ZV_I8gxL5R7(Ex|^>BNAfeg|7I02i_ zbeI2a&zSa^`l;IW9MG+3^3!{V%}lphN*sp-pS2eIXfS^);Wcd0u*!+e@o@#&SqCE@ zflQb-6u(;E{n8>tE6Kd(MMCH=k6w=o?!(K4)V#R=!=tHqWakFt1e#-%t`Bb!*tk+K z^ct6@V_2z+x)D_4?EuFeoTb_!jV#-r;T*Hf4iA2}eD=O;cF!X2aFVKFY_nC{FhR0;OOLbH2a3g3GI-Ni<{+G$F-ZEeqSt4|0?`ghNu ztelR7?P@3N8c7qDZ7GW<;PsI`haLZA9SiS|KilQPw3(n>JtESU0X7f;{?_>-eej!H zChUJ_vuYpsiyc*uo7MR|zZ-1b$K=1T3cVTyx^QmKQBrS)ltAMN8N_AvYyQ%{Y(1zgM?!TcYmu(G@QwsNzgCs67iY* z-cG)%RH?%H>oiwpGW0=8`&?Lf0^Hvc*faM_Z3@!Uy!D3YouLRfo;azPgsc>~Z)|+k zI2n*-i59BuQDve7=B_*|!7mfo3!cvgJv3~=pk1g~w<40QR|1?{vs+bh_D%q6(4iRV zq*It>F;bPZ)ZL&bLeot#nmhF+s+zJ3uv`R7rYzJHzFD`mQM%%igS1>@Lt>1A_iW4^ zTsd3jISn{&KZK@%{mog1#;snwWCtIdyV>)%IHVuiK*>{?`*8Dy+D~1LWlWcuL>|FH z{rHA1+LO<7W|D0mvImH?6QZvJ{e+eXsBE%W7Un>hHt+;HJHZGpDSKzDW~o_rfuQpP zQCJS$UY%u&aKnkn^uN_hmqvKXVu}wJuj5p5|M~FOv+IbM%0O28*!9}GNC?IF@hwL0 zE>s4JRnR#LWkf#MNlgIzZK~vJAM|FS0$C~&+@l-1*i#7^#D&(0UeHkvT}{s}K11oM zO0+8GZgL$`qh-|`rISbT6N6@SDx>m^gXSK&3~$_9}9BmRrSl|ivS*nX0w zd+~-=1*d`gwhwama0wBa4CqUJCtN^|xlJJ*pyI0*|5Z|g^P^^>n>~|(=+M*mR)2R? z0ibr}g<~T)t&4qA6UD_#(!FPmaTKLjMc?z_m4frgp#v}v4$b~+R#w;@;!6eMJjwc3 z(E0J3-n(0YqAw3SOexh#$IiQ3H)w^P3keg-N4ZYFGXE)98AKnY#>*rkLN`u;L2Bq= z^^hj;Kh+ef_Q1+U!ZzTo;ELdI%t^cd%6@lC?D$*59GTY>-VGHX%%kRY#jC38^}a}% zLT?UGp8q64W&saDPCFR=a0d8q{$n8BKGh1i2ciT#D4Ha?Rx{`XT6S~~qU zkw*Ra*(o?=njMLs1=Ma%Ee6?)c2Hx*aG)PEVpgEy>Sth)swGpx-yag`JWgAm4ms;Evb>yHX73y zT)55IIEVuw#*ASg@5>f~5gFE>fpV>DG&d;kJzQ#wP^*Lr?S`a>k-cgcz!tJxR3Pbt zqTN$R;LV_#Ma~0(l^*K<<8H$2+pbp0xSddYurulPS?27`0mLc!E#rNu%xCr*U}vMI zz`SRTQEMI@0&>;XxPdp~%iL2sfKRR?`RxWc?Bl0bK$!#H3PJU*Qm6In%OO(Q-&=1)cItsnE%e~eFcTJi=f2@Vu`l^m z9^Mq-@&%?#!fglgeSc)@s)Fg^$S_B1q{Oi8QdJ!B1qUz7B;d`E{_m-ZXAdf?|G~$C zMPG1!a0x@nLs-V#GgG~(E#OOlR|mRzu%O?AhSw3~RGe{uEh*!at0ZR=k5#TWK4Nd2 zF2h)j2YY{w#s&-c3rYyJAnJR9%zTW31_~$ld1tF-iZT|@MnaVjRmc<$kv^Y%6MEen z{S3q@^#j)}OEFyT>pdtO9Fq#X(!E9$j{UtkIQXe8eW_=FPNP)w;{l;k*~?U&I;I=c z?%Pu*p}X9n&b`6x{akwj2SR`*1ZN{ zfSb6-G8OtgS(#)3o%nuM^*1Oyxk4X);*m0@z8lWpypRq=+7V=rgpd@|l(o+7ZUQ}| zTG@g!bsiX+hR(R#4Ov$2dgNg+=N5b5JD5!j3YZ! zaR|7{@CfQ6@M=xcweO0FJyZe4g4YnWs;go#lu8vWJ!!U4iebxArD-9tpB!Ppxq$te zyPt6fZnGOlfN@P2w{bccFhzCH+@;s%thdVUgU<PzpVnsHiPD7cb6p40p`zqKXFYtDTXv9g^4zZDAl^RdK(+BQD0hLsoo|D*onAh-pTTyD?m&^k zI_fw4aZl`vdnooPXwCbr{V%2Q%{P#WcxZb{O13|&xM=f;K3BsD84~!o`kS2W6ppms zr3qgOiOm z#u#H}eWR#u5RceSAZmRuQC_(04U4V1K-9ph8j}3)wbwf$Y-q2#d-DhCOxa`{1{4KKE`1YmpY*Jr|k4Tz)%f^_|-jTPYc?%-_!f=B<#N z^X9nTy@jr6>RmQ%n$Yu$I$!6!TK&6df9C3{!-vOHNK7m5j@7o z2mxO+BOv6x;1v)Em#4s(2AY1+Mh&SH#PS;J_5$0;gwG-D71iz~c0cXG-qxGv^f>~< z6ppZP_)1Ju?zld`4lcq zw1X6`^m690j4e7_;F&s}`Lcs`F0=-Y*)*QvG_H@?Vw4WfgPnO5gLG%l376NqKtV0q z#!DYu*sH}Gy(Eu~;%}3rxO9Nm11WOH>7U^wcDWA%<4`4){Aloms=%^ED42m>N~sSV z{XTc_`67PdThQryc5=Q}pG*_;jR0(X@FO{QGIud;z5w;SnkK-}4=go_8MPR|v6oVh zUK*AF+RYCvqmTV_8u2Te1QyW(1OeVomJ29+7SPtu2xTBH?oj`)$+zZDw4_eHmT;%v zb|!v?GE$lOaB2l4l4xr$$xc5(<{*_aqNbmizYSiHneJA}mkty=Jtg^5D+%yZ`c?i1 z@~eQP)xL+~EkaMqXMqnQh0nt58AkhU_QG|}(QoRNwQw&Y(0qjcjwImL{+_I*jTYht6~xx+p@jak3z}%MmH+3C+)IO6^s7Rne_<_Ml_xSO~8}y4ZmZ< zvM1MF_3OP%mN-wJw$8>)Y4QPORE6A|KHv2RE74#Nwl7Wr+KE1-*NZ+*7APMmWIF*| zv0teHx~J$>jNHY87)mDL?Y%+%zu8;g`G$spmj?=d&0rq{nRi6v;@F`9<#kXjq1^AKqubIIaN-lB+>W{ z;meO`2kX%nke7AKNmEI*aPTrB2l6of%0_t)8{)<8kp-8j`w(px%Z{sX8DN286EXq; zIL?O@&>Ls<-BO`8j(KIocGBot?uI|TB@{r4Q-{7*g86@Ky$L+j`}aTIa?7Vw+Ev88 zNh*c1jlp6N72FDk*N8br7;IQ(49m(;^aP2s7D6*#?6tjKP?h|LgUp zyL|t@?&H>@$$LAmbDrmUp69&Yv$@Ng_NzT!VxGdbRvsL){?2N=uR5G(%<6&;RbJ-N zG6$Gu8#TL0vkA~q8P+YrOaEJWV3ti&=8{bm*rjMlQx6Zj<9`P9tX^`?zAQK$OLK$| z%CUQ2G#&v(HyMmEs}b5`PPMj(@(_NMV5FW;1n*{$VR4?i*-LZyfK7*}8M9VFhnhP< zFN%CLxAh0+rNS50{A4hDC&N0_Exwke23?A!b!lgoyN%-M#Zu$Nv}jwd-p)L@u`$zgxBKCz?%~l&=XaKK-s#Mg;jy0n;Fxh1C#wj%lFR* z62NP9o(`jahoYc_M2lYM)cghxc-15jXMGVaN^Si5{ZAdkk8{%;%n!*sN;<@&a8``S zDcF5>Ej9d%Tor|i~nb~2gYP!hFM+Ut<%Go{H3wNsMo zIf+Bea||2X50i)|V6Pj?I|q%2L)h~c$zbL~8J!sDdx$@ATG^>uV8U84wCfCiHk=W4jGE0`@V)%x^QTm#-y|YB z=fw1$?K9U`AQ=I?(9|dWqjxhCjx^rn*)#i#rGBnk*tLnpyUf~-q=-PivHe%@f;}j9 zPS|<+FrvJLYWC5o&yD&&^b>q(oICFC&x4M;-9acw`l=c<8No>x`6or>M2jeS+#O7ufh9~1KmTx)<2}? zvu(3(3G~_@oMhW`S?8Hsq$C8C?(Sg!61UKuoc!<1bFLKRg)d2V+RvJyn{D@Bp9u3u~P+eBTAW#hZ->;yuql+s^yX` zk|_9Lj6$~x8Ooiw9*65k;syuJ9ltXtXi4#d9C&<{<^A#u)J+?QSyZgnQ2gK~fPaBx zc}J6gyAp%D0IhsKDEFSAPgjY01kM3>5w%Y?+k#;W`pc5596SdAT0CZyXbsd^hFy7E z-7ya^#i9u=9Ej^wAEVtsObK}Ev$L1+bkTp>Nek}?$SnzYT+W4^3D6wgzbXgg>m2ImMEGPi_8c+eolYar2J42*mx9H!xv`!g1iGy;3|JICI@D>vAz7+6I zy-V?0CSX!`@Vr(=ART^~nYvO7Tmk_6MK5f*Ta`LM0Fu{aOvcr)O9dJnK9F_xdkC&G z3Ij6&2N5514&8uFyA-L(snjIjlTh>CIrzFFV-}F$CTxljDo8ln$G|`4jO^@5&>En_um}3*J8hA{d#~8tr(nVAYV6P+9%r zTX>{MfldC!`CQ^`dELnAeUKGz{YU+!$K2h)C)ZH49WsM>eHjhgDfez;e6M76UEA!{ z%>{T7g4IN(!&U*>vs5#uzo~ok2!v$*e|Jgd`7l&EO!{vffUrRaU_>RIG8< z$7Axw8FAD!_Gi;2%Gr9!U9Dr9ez8x~i1!9}_?I;59kcKM+EYHx+}7D8+q$Ln1bbuW z8@X0}g)R{ryN{&CxMSeDWtLT*Ra@Y7ql*-$6iE$j$LxE*40<;c6nfOCqW+Hx2bMRW zY$J8V2V+Ky8yh*IX`H>Pa>_}>PgcEOdm_z5yHorJidVJDju-4@KGfBt+P85JzmiH( z@V!L7tA4e7`JiCeU_k2@jVPBZU-FDi;QfA{IF&J0pK0T%e9fVWSvTh$tuami;x}cq z|G`$)hLMeQh0lQ^F~NyL+3CaJ&V0Z0u5j{YIP%W2MepjV4^N&o!=e9r)#xT`8}5WJ z^v)k`AN-IyUhhMBF}Mv)0}n{2zr%hR?7CmR%n);UXQ#GFt9~S3C)DUT*SKEN4BC$& z*SNypbMm;kc-hM;%lxs9!RXY2x6P90YSk3C_&;*O8Gf>W5UpwYr@@#@=sw@6J>c`3F=Lj{52Iiozy7QhxU(U zgbB{ocU^)P)jiaBXxei!(p(&6tNWJFGWNZ7zG-z|gb7XHsxyN3c!}va?yIv4K2^TR z=CY__`AwLeBdZD6&`xda@npee9b`#Ww_GjfVs#EIm^JASSF4N+=pRB(-5^uBA9$s7 zHA-=4@(N$w$Zm%3ZEA@BFlzV_daLIHUx!IU^64o_8uV79{=~|`pGrx@s(DchTo>bH z(kQr#Q#BDksvIXvAC+F?4}G>H8j9C*HJfw}QsSPopXWr_%_ROzc@vZq zSo6bnGlB!Nyp=;>wML5FhZv6&oQn0w2lt}qJShH-L_G(AgGl+OSLE#D?iEo?y+81x z%j|pi7@#Ik6+fiN9}hV131URCi51F>xaq5Nteamsj;(s&duO`iOOh@08PaoS5#?_o zWl|~Q?=@nELdfhHvk?xs+-p&Jp1-$k9s_+-*@^BvJC$$HqOUM7z@k(1cHwj8E7$pj zOKcx#$lyHV%Pco)yKX><7E@vp)B}7*<{Q$(GAtvMWjL;_amNXnHlH~#Sm)Pavp(^2 zNx`&@{wpZ*?y=1AG1U1y!>kCqQqwQRcW`Vm!|JZc@@33sb*uPi+0aMtN1Ljm3v@nS zt?xSJLlK?Rz94MeSSyg)-qY;e>HqqC)R~yl$9tJ;N61=-p6IveQ?@E@d%}E}zoW*n zBFr(qGLd^?qCZRdZtRse)qQauvXT7muj$#O)DytSJfa5rR@Lns02zuzr?{4>*AqDf zZ{y5ZJN-lT(2+A-;C-*iqQV2$aQUA|9WLJ*a3a3l%fp=Dl7oN2kLHb4X$<)sqNgbM zD5nt)#e|Md4NsM|!3btoNco-4{lxhnc+@5b+YU@Fd>kuNH?)H0tD8AI1A zRGI{v-u(U1;FL)ln8r=mGi~6(+H8JCW2Q}k+j)&`@kXKbQOdbLrA>Lxn2%&f2r8-$ z7T=^sEG`x|zKv_`F?6x-f6sOir}?n=Nhl6#0@y3WO~{!Re(ubN*O=2$?PyomGRhML zAn}iL(+AJH7xtZnSLxJ)TXJO=lmau_K;3np=59G&njPrR&blBuqYVN{>c`H5ZqF` zrPMP@rKDpQeb48(R_^Tv=*`^`tkQOWsRd+o%hBO&9mjdP zQS%`zx*vY|tS)&sJ?*4+Eh@gyzLjU(l?Q-Il{zte-~~J) zcWBETT@Ra#1no`m)@Qx5ANAbcxvC~T`Vg$N0$7-UL1)Y*@KyHJpPN&$i8`(J@Y>)Y z0v;gEsHTK#dA`!N6@eBGp;GeTDXq^mR=RVNFMAo<-<%v;qultp)ek&kw?q7;__dE< z(!=^b{bk~?5b@KRbH`0>e_t@MA1mfxCZ;CFjo{k`i@OI)bbC%rT&c_0uxGpC&+B_& z-cZG}zMJSdxE4DX*btPD_8heY;A#Ex$J)%fOTfPXY=}kRG3C@)MFBq*xDs*n@iKMy ztDAB?S5jWktd&_H_|*pK{)W@|6Ak`ZMqMH1lmiW&qbh+D%FxJqY~m}5dIjsg|I+^e z#vXj@7fJqkfL2(A)s!5k~m zM_4ttE(f}#astusvs6|V0Hb{hy1kp*?0!#1i$I(z?N~8Bqt=*L@=0gwfbmtK8vux} zJ@?i8lFCgxvu>LdQp&78d@#kAck1|3kT>G$&TYq$~hVG*TT`4gVX>&al%g>Fs1g# zE5LJ~N~G4qMNY$t1&K8Kfn=p6R>^Y(=GP0Nr(zXMuvZAmQ;~-3Ac&ArjDy2Fp)G;s zu9MpQ9*J_}qzk^aXcdF=-(h?ows(Lmp$hk=DbxFZ;0mf~cD)HJLMoa7ErN^}O?ErW z-p4XkYVnSur9IjDAYe%1`BO-G-}76;Ou9ed6}BSWEJjl?>4JFKHOI;E&*Q4j1J&g> zATfBbe$jAq+S)DinI(2nFu6UaJ^`Qt7LESn!@5w`ggZp=WlYZS6zX5@SJ;ymGgozp z*IBLZ^Z-4VLHOHjbI~R}MV=)M_R@c6sAdvw?hbL75{U^{U2dZV?%xStWOdYiD|jfA zRKh8aB8UyUSRtj}*X^MJ^e*>fMQSgGcZrX?7fi+;cRvfA$!2+4v66{+*$=HRk7~kI zHB3mJgtWNEx?(+j=wj{I~Ra21uDcFzNskV&(Sz9Z#}{zc45^=9DI>GaaHiFsfbI`^Jv8`GvFA z4{XFaxUq9HA_xbiFH$bVsqbk}T=7Bp<7%j6zG0_Yl)tN38RB!t@Fr#fX6~DMW3_k)~xSpIs?F19u`=qAeWNl@n)*lg(j$VB4umw zLtlsKx%`D_wVSDW2Kgw7WV5|SIZ^ewvdA{7-=07I&MJOeZ&6Ns^@z*;m*2IEX)aG4 zUTxRguqsif8M>VxEsXNUwY)n2f$yF+p)M?OqbSo&+oesczpY8!ms+TggeK*1bKD*i z?ne!@EAil183;~rXg~zznj0wBloK|gYXQ=Il}@xwQ+9{GsVQTK9%yB)00wQ>)=bMB z-iUR2YD8G|qVOg-UkPwIW=UYw-PwT{>ClM);g)9wUP_o;!l z$o|C&3ZPiwPd@{PmMx{#alx7iMCcY-;!8NcHTi|xt_O)i_dHA#(j49AQUIMeXEoLj ztl`)_XNV#e4AMD66*1xd{I>;LJ8uQqxt5cvVX_#?Pk{mMXlp^qOp*d&`XQB&BDJg4 z=mhjjbN0rOOCV!lgPs~q8K*Gz{W4>;V)ChhpSjaPVVQpSTGK)dYryOFP9kRf9@x_B zGS2CC*s_3n@z!xLHn?LY_Z9e=02&OdK4rojmgfH49l|pxfx}W@34l~B=Br1d$(@DrQdh|@GomwWk}T{*3z`_Mgw%ergt)PPJ#23 z2G-|{nEQxxKH_*-HBJ-FFI$}Z(VTLI>NV26@UgW9XARxY@ge4)LdCGMIoq&2gBJjk zLpWm;JivEeZCLFlo$splHYTsM+&^J7Z*NSsoBqj6aN{S7N zMJtcGuZbnP=HH?ncoD1*8J+9HKWV2uO15i6(Og_Xo`PnGU!T7gU;?w*W^?{2fX-nd zH*5|l6>ZG`?gom!#f0Fx_AX5T5POFKDvI`}tLI60Y_SPsA9}0zzo@F`qW+2vy!F#q z*?f`4m4YS~aaOAF%B%J}yvo06oL;=nab;H(`*>%J#%Eaf9=_KJ#A>lTz~id~c1y#jMKMCbPS2*eH7)L$TIV(X-hV)> zouHBiNLFdJ@tOFw3%PCUzQ)}kw*f|KZmz zI8+$tq7M8G7QKXaf9tT>FiJ+#_Gh1TNiA}keuMf886b-CwdsNc5{!j9el>>R+}hN0 zR+My*kO1MxW@bS0tEYKfADyiN$}>>tE+}o%iAz%pkHDYt%eY6`3S1D94Bvq6Q6&MT zJ?PVcDkr1eW(C?Isi$g;w3F(fp3;%3UU}RW76|N*i`>=;PmD@tO(pIF?Ad-Rvtb2> ztChT^V52Y;2!YciVKS#{Ioa__vA!4nsd5;bStjbeO>qGVI39^Chq#agBzHAD7gQux z?8z_eI1S2Lx^O$Q%m`j+8TxF`!Nag}J6#f^o}9Fgo_5cRpzI`~?Y+*?(G=bs-$AQw61m-pfLIg9fDh8TG`y~sA=`7q+P;^gpB(Du){0%gT}Du)j4$DSZ0kf zl3z2AD}t!?t4XH(aH>jmSkk)b$f9L~)}K*ahFF#%(z^U8Ty1meijm6a!(I^>hmi{3 zg)|oX++kC^SE2@UMMx5)9}poP9jR0WVS7J~V5lRW#k~cSM*;!TkTKjqCdF-V{>mP! z9?7~VEj_{Se`yG#-k-Mh;9Rl+o#s;hR>g>2#KJ_;9rZd~K(ZUE<)%?wogdL%jw>MV zml~3dG10sFwL=B7q-CaDvN%wM`$U zlv3S4hv1IHlo|piozFr%b<4D{r2_vP+yM!Mf&@8~W>;(vs20#gyNZ5@DGzNg3rJJ& zA)P>Bdc}(8*`oFwT^S&+M;(|D+A{-?g4ZdHFv~oy${)Qum-F)h!v4x8Tu0_ZQ%M)B zYESBEOo0GRppS4Uuuz0=ji!AE90E z;+?=0+dwE{V6RQF2P@*G!L0MQh7Zc_vsf{dbtUyv7|+ab%dAO7%suG6?mGt>vKm$S zR}%})^=(HGbkd5fnytGk^We#;8#TfDl`pb0ix5@~GX2X82b!AgVEji^R1mraRG$zp zle$|gY$0CyEBt|w*r2BtL|?!g{;A&#bxN}7B>y%@Nq+Q{>D%YKPGV%YGTdN*0GIDViglQ>aRxFQTL)tLZX@LaQ@bEFe%aVcT>A3-!DNVU0fRBLNP}I{nIb-p%i3X zj&?JI!g=NnL~T;e#@vj9pQ=Xh{9!c<)wfN3glrNn9t_CBKoF&e1@T=Rf{rkFH_Ju( zpcE6`4_Kt`5-*@`miBioc?2xyFwzx( zphM%e(+$37|3ev7Zr^j+fTVuow4iXtPH_K7Yi;t$ju(Q^`p`qNEOmp4{`vaM_`mh? z;@ILg));)EgnxjSQm2UOF#p2lZMVoZ0+5d9EaRi~_u1(oyehGBXgH$DFEQEp5Jd0FUd)m}xkyhRv_o~VA zo$x~I9$*G*-IEWoI<3wCRis??`1y(%AYd3HE%$SQhpxz?JM#Vqlo$0G7?0i z@Xieb#teJ8IsRZhdo*jIAe{AimfXQD#v5F|vv*KFUjMZ6sq{s*v~qvrvEp`@Z`$#d zr*QpyzPD%Sa8*@%W zwj^!cCf4UYLnX(H5j)q{J;8e8KmYRHQDWY_Df?Y8#D$T+ao5{@IKq_kS@j%vGQLCz zyFv3?#DaAzaJVEKYjT1V)GF(B=Bd#$l- zT^}&K<{pgn3hrGQilx2#Jw(hj;_w@x!os)pH=G_Ho5PUWu7z$W&>idHs+IlO%g*FXoc$kor<3vPUdGiymxR zB-Pfb1Kv&lRGhV;9S{fJ>;sE#F^A*>pgkcw&fm*4aep@UWqTk}WZ>x^D4@N#pzazq z>La=;F3&#BP3Oqpasp7#zdF(c%JZOg*~U9?jS-4I2;?isN;+d<0)MEUaIPo6AIm(bGFqz9H~VfZbP)+9u6X8034og5^RpNkuo~jyQCaQ{p!03nor1Lbvgr|aU&Xw? zZx5aB7#s=NqagP=aB^Lh(V~-dq=Tt|{tzo7hq9arXy2(qS;$yknA-Al6 zpLHhh1!DKwX)WMsSG_PG=)X)m<&tsVjb5NNcNg^?Z`J&59Q}!+NOOk!#1=iSF}~LvGUsN2_(;mpFnw! zmLG@-Isj`t^58Q8D^Dso^}IM>UE1-FP9a^R_kvVjNK3yR(rkdh!wCYp$HYtTgX7t8 z71+o!r1s{PggO-iJ&@}Ji`wzSI169`raV|{jk|vg20*D$oFIJJaoBnrbEYdi2P}jr zr6Q~R-E5qzG`$}svDhJcH!GEU(6=v5GFcvR8*yE6IjV9vkhNDtQq3=T%0}{6FiA+S zww74~LROrX)*q;9i9Jc^!}uZ%RgI`L7)_HpNV=mMB_U^8$$YwtvsZ)q0x;lMF|V6I zWXk-mQ)oe@-WCko`~PkeRkQ9o0~K7k2r?Ihx{aPy9=8@Wro4R@6dIo+npi>szphTP zK$f=RKO+##DpJikT>h(^1%VEUC=xmGyZ3054OlTy@_zg?t;Ys*#YeS}klHyd++KsZ zCeQ|Jj~PKw#tHv!_ImC?jI2*2bs!fIs`9$fC7?0vBfShU4`{7D=8NTlntHqfHj)50 zU%{7x((6&-JrJ35#-QsCKRXBwM65-P=Uys)R;pyShZmSt?%pTK-Cz!R!%^}wuxyfC zy)z)TMiqyUldYZ8I5A@0#6AjIyzk4CN0tAer5$$?51SpRza<5#P@z<|A#*I~UAu7B z=MW-^kncMt4u+Oa9fGYU7HDRsZ%+ig=~9wiz$Z6h9Axy4K9scWaVqklg%Qc$qAM(j zJHPu^$Ki#8BAA%rg^bN7czI`nC7X0rv=$oljah>h@-&_+KNoQMyy z6u{%!5D}22#K(E3r?t-c19@z`5D}7Zg?d5wdGc8VVOmEWH9@-dYGNt?01CbSE7VHt zO0*jk&4QcS>#59U1Y_e>Z=JiCqXmP7tczTA4J1d3$fro zx4_$ZF6iT2hwg8Zi$X6&x}27`t>!rWvWF)bvCss+rQ2}X{zx}L16?D_TL=Ab zzQTC=iIu-Pcvh!;xCT*kXxzXZK=$P$e8a1{)6?0IcmqFawVtmR`fWh;!R^Ajqv%UL z&lU_W?SF`r20C4Gk3-s#KKS5n-n-m#OrKqg0J1p0(9t9q zHZA}guj(eL@lU|Xg08oFV}`^Tg+4d{>4^NcQ{q|JtaI;6D~E?q(m1Xiv>1Y@V8#fs z==ab9V9`sHr}IGs5PznWd!-k1s^=eoKw)OhjbT4)wr*f88*$jme1ms1pIk7hcoMtp zM~L#s$>YF9wCAc4p3PJxzyb@~aw9-ckdMv<)yJFeojM(TF9cNp1W!TjxBZp51CUKf z19{HghCG}c^XJGa)3`aYGTWjv5rTKkOF^ zus$Z%{VA_i0pV)jH3Kr|#&O+LXwffS>BT_rsLdXGG=SLjnS#SN?ehmfbgUgT)*pGF z(%-co^k>6*w4O}9KG$8}OSlkAXh}!998ygwnWS7UDpq218MP=W`1e;yKqdu^4a~z( z?a(ubX~n?V&4x#@My=Nk6y8wX;M4}UCzHZf-|IEB)>S;;ura8rx1j)B5u!8JdAg^| zhxnklW0&=gfj4gTBjw(S9cLP-kXqYT4T)sdNiAf6U&4AAkF#1=?+FUaEEvzkOVCY2g&`xsSS9*l5YDK$#c;l;n+d|1`#_@>a}@EV zTY)bC=>3#Dha{SJ^OhhZ7^O;5L$)k5jBW)Mf~?+sG1PO4zZb=%T?GwL#aN;|(j`t} zxdX_1DcHkYm0NE15tZZw=vuAdR$w*~&mG>#;)^$gY(clDc_|rgMJ1`{E~+BTu`SsG z7jYtSTyyTljxO zI)wwe#ktBl@<_vLoTqnqOON6iV4$?grTXEMOA$E1s6U%wW3|mHsnsFt2ee0Ib$*72 zjIe0T9J|Zg5!@qP79+firF- z?fo1l9VzVZ>Y4CICNDHeU=m(*0HLfMD#Y(i3qxC2yx<)BQzE>$NH1a5^I~>;5kue| zUHU__W=z%EQ4j{_h?)YcSsR%fAhQZ34V~>Ly*X?RebTOQFM5aGxmt3rmHe-Of98@t z(e{$B7sIc_6-n_!DU!^VAj6LfRZ&6roI2^s$X=ztO?L5>UVq_=F?d4T^W()p40EDwb-UK}M757j&W$Xj8)@CdkCrxqnH zq^{~V610lzg1TmF;WQB#H5}c0*X1PaIg-EZZy%SgkSglf#l<~UE~*J+x2;`J$;btA zYS*ld-Q6<^$=L9lTEeRzMjTx>Q1<7FADB+LBcW((ezw1-BRw0LdPztl zpk@Mg;=6mJLH4>k`@1-lSfA}=teULfg2vlT*F0+uY7K3-LtFLfRYUWOhYH>CU*0dO$7=h~~Nz?==Vxjm0#o{@n)AYR!DB z;vj>N1~6b$1Z$FtOpiB(Q|~naN&uDluFEKhwXmM=F6c6T(hg4`3vTaN9*^@BU8s<~ zYtz?usnyyvR<8T>ByPVaN=-*o;pkZ8 zJ&a4LR*gy`oRk384ixe!o2}ckfeR^ThejjeoO?fFeqClXB3Eh2e2&{Nz?#G0)GUBp zHI1F7OoSf%1f-Snb*2Nk64Lf(rbqSCI78PX0!>MK$Pu&m;WV+L63365xLO7h7xuSK z|1SRs+xxTIVHWns;>Y?;>$if`wwgeixbrh{_`n^c*e$2;Y3b$80W$=)GKZ&62)hwu zSKaNH^Tz44fibA~z08B76_2MivLOhwqhW_`R8wOM70hSNs6Rd7k`~{0a4_yyS71Ie z^u?<0G8<5%~&?D6UC-#A;<5 zFW6iWe|98;$ZdeoCDH!vWhn+>LNvpduOY?dT7wxB>5ysH_VI*N&d`_blZjwfYSZKvST*O)PY#dg^2T3v>{3_% z9QaT=r;lNo`z$sYYQ^fMAFWMW6i|RVfhsZS#r8M}`1rt+yK2Dq@`b>^EMuA{XO4%@ z?nZn-#=(Q--Q8jfxqh+EYr>+*y{(~#>%L60+ixaS@J;+cu*_pQ#l%BBzjT;ORmmOI zc~x*KG+`&Rq5MkEQ3QY=@uhvh*p?;89B@(#ZO(8((qYeN0V|$d11GKT1l=1gowi%B zID4peZI_(h)qPL|@bZ1CY`t}7z?}!@k>tRwnXFG7w}f{s-$zKPEGc4IK}KHrGUz4t zVgzLB=^E&yPtwk`sYg^}NZ#0B6fL%dIA#Sxc6p97ipZVSDMj=Ad)uFgGpif=?h6?vi7k*|QIUy+ygs zQ?9J!^USLp-A&f=p94+y90c8a1kHI^X!7Xf*`VuH6{9!r3*s8B4JNLbH?H`n72VgV zqTF{CG8gFxI6SgorMc9z=<1LKEC7vdpCB$H6%gd_+?0j!u43rsobz_S=HW-Z?Z%dI zU#T_1@}l}-lggt^-SM9^T5CFseX9HhD(SzQ)8EV6B3W-LxOL#V>K{>)Ub7;` zq%H7zART{vM$Qnn0`X;!sv^u*qwMjJFhRynI&8X!cWxVKD024alT1CcezBEL9p>2~ zD>`#ybWpo(qK4WBKBs=TT!jpqce;=QCau-jX#DSs0abZck(GGZbfUfA8;Wkc=A>)H1((Zj+y|iSQ+bhTetfJae z{E$bYJlhvg2YDAx4Exztc~w^UkQrk*(f`*5(SN!RV2bc@QXM2lW;LinnRaXwWNXxU zRobiz3HTl8?xenHGzG&K7DVwfC9{P=MOZR{-gBt^-xKm9MytC+W%>^# zghStuKR51(V#!=?j$y0{zk>;ZhI zVGjz!=gpx?(8VkP!;5ZT3YcH)_bm;-6BB2ibNp*$4dM%1QAIR5gKClf@ z=0iMI>!r(#8Ur-&22@ z=X-kPf{Xk!Tz<#J|7Stn{LXx2DS5197+89uh*w;z2EOsPKri14TW~UeJ9L4eK6NJnh z0R_R%G=loY^PX6KH(q>Fc?2*`tVhL%l(=V59UlxI(hbh@H^RlC~9cxCBpf>n^UI7Vg|@lIQw68 zyR0y|mf3AO%r^8>dpkXET(VJw+BYr|%?tqBS;l6Q7|ZQCdCNw2iLj+3$8=Wsn?1x# zF$z1TLqYO;$BTYd8Iv*|jdXomS^Dc3iXol2y?~a)1PMQZ+Ww6h_I0InqHo(&2Q}@>f1E!e*uZ>HHszFQmPth_7rqnP zll$>#lr2bggO$t6#;e}HLY(t!PZ)k{X{B{P!sse?eFoo_b(gXmA#Q-Xo3_+L5>e(u z`Nu)M#=o@Mn(qP>u2Pi}*Nk45qO1$V!b>~tW@Hl&o@Fch;8G;6r zs?k~q_OgKS0^S{_%x%UUwW1ZLF1cK9@xhWklY-OBLwYt-<9Nd8@m+SP$Br8oaonMWRSXU z^XkRQ%~kkqV=@>|ULzQ<{YoDEI$Z{ftg5oZodV5P{dLoud3+=+8h_FZ6aUDeQ1yfo(aV~(y z{P>e4SIYF3J1AZoW&gC@QI1}dEtAX_vG1ik@NLC3r6fhe!7!q~NKYJXfn47asJSle zX28wTJ~O@=L2d^6Juh4D-I0dwZv8lxS3Lc{K-YE34YMs8Db}{JiaKJ@pKfZh~#hhMQj!vhJ3^c7xW; zQ~(%+b6}@v7*@XLhowj5aJQHJn9T`E!M6)yJ_7s0Gr8F0dI+1+p8?e@lK*gjL9g|n za0J>7Ek^CcnzE@!3Qu`3xnMBpx%7>SnlI{0K-jVrkA(cs&X&9kxaFL*Mv3k!VCz5_?i&l4O;%9B7y_HhU;D*Xt*yMWS_XAt0WQuordvsCa&kt`0Sa}^5tC~( zUNf3)W!tZI0@bG*%Zk(zq(XB-%`e#X=QSWY3&b71TFwHn-m+1IhLSJm!|7k zke@68vJd||!5~`KH>=`OSFNcH88u>L?ZR@r3vH$C#7cm(=3wv$rl2|DY>DnoU>S!T zJv-PV@7V$c+zZYQIgXVUc5TA+x;H12j5!}7;P9>_596(s?DF`&{~xIme?zCD@Rb(f zrY%y`p(*X0s!5j$dnC{Wm2)Ss;|XRLU=B*h50=l88#XMckh+>Fk2){4u0kdXG=VLL zSxpVDaN-`Dz%9Uhn@I-c%JvT2>4oyvKSk6*zEcVAr@;jglyB#(eZD;p_N&;W#^mNv zYfjLLNSDUB7KbFz3kFYtHQd3Iu|5bT&yDK4z!1)+*L(}^d`it0Fu=9`g3QH_B5r^q8Z<=SNc%aBoF=CnwE|t8!biB8>4}Ms--cEbP{AQ6?)RlsTiDqu z_Iyn%!*rShDgW=HYLwVxVo`sG;dDW7SvUS8swLD@&!W=A1d@HyOe82AX~#!63gMWH z;f~XS&nZ*3zzb=N@`N~p-L=D$50BLYG{q31Xz)UH$ecc=~d_Xr<3B^-yaih20iV-gWB z9BY2+)Tm)s{S*H@_v_T2;7-CmP=6_^I_^b^yPLZ%8!hfH zxGgW(SlvR)40un)!l)5spgm44UIC%|A=X7kVO)|6X>LDVj9zqhcxO*KL&pT?ggg$JVplQLF>b3)|@i`mGoGT-zWz= z)H9VBHz(ovp{hCFMy&NyW$b9(bdOu;5nyFx8!3*5&X}(pw>=t{3ND^uV}*pIoE?ugLO+ z!oe7u!5^s#K5mmim96t_0A#~@gvh4z`Dr2evg7^6#6fSCmVAfxL4vx(Lh9nu!*v?R z{bymjOb?kM2Hi5Ck+i!$$1w1a1}sAl?hK}*O8eab%@?JQdFKsJ6O=zdn!hD#pj3ih zDLc3p>F;TzKhnyr0p%gsx9Vbunmk6D7#A#6uGS8RcXIb?=r>78eg!0C|Lm9m18+}F zcFF>d>bVo>zoynZKEv%5m#Xk?PudxLG(ZT7c1Tt#o>pcCd>CMM+n+T8`<{FYykqb9 z1K&aBs3iVtSx>f47*Mxj;f}GV4(hua6rbEF*37J_YYr-^NMoKGt*~C`PqH(Xj&<4F zQcHlUp&fMRQ&1Lhp=RaIg|W5LBH`c_&;b_Pw{SDJH+diHcgUf&DSyuaT!^rl{V@0} z2X@iiY#o0|>Iq1XJDuJr))#op)Snz7^xbVXK0fqIY6M$dVms>BY*PTI+oG``?AnzI zN5Ynxk~UTV9&jK|5LtMYrH*)Ww9xKDx6gNsRp%PQ@JwJNZtlM7WyTSR_WQ|?Y~9Ob}hW;JdvVc%SFOp3QE zBxv3tcg-5Iz6f*Z6@O6T=F;Tnz`WlDIFU%*psqIUs3mmbaAmztJyp*1r~EXl^vc{} zy)ddQVHUC%G=f8$W(o5ISDkpZj~cRx)AyjZ8_DNuWG3Qj<#&QTgWXaC+H*A>0HPLk z^!XI`#4UXi;mEwwFIz7(h_m$yO8z}fKnIq_J5Jq$DojFPqw%kXr5xhd{4Mns)K{Bw zcwj(If1GRS|9<9N!K-Yp0*Sip@0L7yQ7 zXA<>q+yHuuGIzR7E(Vq*hP5cn*nH9*+H0uy`oH8znB>29Y-P!gSMNpN0i;dHo&a4s zz`HmBJ9wFtjvPT%b@2n=jOK?ZLDi+s*3x69pGAaXXN;Erc5um(CI18e|FPsH-SdEO z@z?q#o0nX1_VBypc*PCvjPX$h_Q>#|L-*>Fu-~Tmo@A?SFt{v6ZKR&pogUxgLA5S-H#{InRGM>odGWoSwY2C_e zdfmh_PG(TDbjECB?aM}zTa^@BZ+xJWS&L&)?~n#q7G#sjmY9i3s#r_z%kGSsIW>Ng zV3O^8jUvnJ8YIY5%Ek${1dKzEb-O9kt_Am(cPqZoGQW~hF|Au$|GGWNBs2yy-sGT| z{M=iDvig3@kNm4bS=;6g-@2d!4l#}O!V?cIdDf$yMc&OFS4r{Zluk~*{GIl4k5i!+ z0*D&syj?-h?v(3H=T8(9*51}1n$t zA0@}rHfT1#wanGKowhXC``cX+QntM4h~rAHGt0xBq$e7)P)=4^iM4MnqGpZ01saS? z_zjw>0JR{m?x_m-UG|Kx)#J@H|@XM`~)%+NxFLnAKA;y_l^?UQ`0j!EzL-Iw*j#Um`V_Gq7A*?+?ayX%M3ukaBA;e)*t z;QW80XUW=ysF_{5@aNdGN*Fz1ccU{;ivQ*Hy{p>vbw~WV6NM|b+}~-t`JO(vz;(UZ zJJGafl#|K3_GhhEKfAd$DOp(=U8C2d^Cm?2JuIY<&37OUeChG$^FRDGXF(^`*0(tG zCVu{WO=sR#?_|2``13g})5X)+?%ZvrM6>Rw@u=jOgt&t)w1xviwv8T#3)>nfE@}zw zUM{!ebn4N{5*(M|#Pm(OD~9quW$?BYOI^}BLi|L{s@z*~oAUU_h8U-uiSKjzYJ2J| zhsvvJ4=ok`&sL`Q;Nzc#e-awrN~a&s)4D8G#Qv&2T$;Z`(hIkus?hiROEzcH&f|5= zdgij(qmFvgSLi;nGY9YC{~~VxY4~H0YY!`NLzI(K*D9gDdsOABH0I&Ycj+%yVV)|W zN|#`dgcy7}*LvBYOGfFpAFA)Yjz;dk{$@!sbI<1z-VfoL&>(4p`~;ep-mSg}59-V0 zcejJ@)dt!=S5A}qe&Zv~X&JV1db^H~(uqj%?L);Rt_)fSn_d7OLi9Zyf_lH~O*g?IWb{kh`})NL~oj~O8B8c*)zPZAk= zcpQG7Jt-7FW3+VH!R7xzuTiZ=(D%Y6OKyByxdkJFj|2MHAR;+|SBLe=5 N19rXQ27X)e{{aeBTSNc= literal 0 HcmV?d00001 diff --git a/tests/test_round84.py b/tests/test_round84.py new file mode 100644 index 0000000..ff70ed5 --- /dev/null +++ b/tests/test_round84.py @@ -0,0 +1,320 @@ +"""Round 84: Kaleidostrobe, the 2002 iTunes visualizer, as the fourth style. + +``kaleidostrobe_golden.npz`` was recorded from the *original* PowerPC plugin, +run under emulation through its own VisualPluginHandler: every frame's two +uploaded textures (as digests) and every triangle it handed OpenGL, for a +fixed run of spectra; plus the output of each warp (calcDelta) and each +wave-table entry. The port has to reproduce them exactly. + +1. The engine against the original: textures byte for byte, geometry. +2. The pieces: warps, wave shapes, transform's quirks, Darwin's rand(). +3. The renderer: 25 fps, the GL picture, dim mode, pause. +4. The style in the app. +""" +import hashlib +import math +from pathlib import Path + +import numpy as np +import pytest + +from PyQt6.QtCore import QObject, QRectF, pyqtSignal +from PyQt6.QtGui import QColor, QImage, QPainter + +from lintunes.kaleidostrobe import engine as ks +from lintunes.gui import visualizer_styles as vs +from lintunes.gui.visualizer_kaleido import KaleidostrobeRenderer, itunes_spectrum +from lintunes.preferences import Preferences + + +GOLDEN = np.load(Path(__file__).with_name("kaleidostrobe_golden.npz")) +RATE = 44100 + + +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) + + +def _rotz(deg): + r = math.radians(deg) + c, s = math.cos(r), math.sin(r) + return np.array([[c, -s, 0, 0], [s, c, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) + + +def _lift(z): + m = np.eye(4) + m[2, 3] = z + return m + + +def _eye_space(frame): + """Each triangle as (s, t, x, y, z) × 3 in eye space, the way the + golden file recorded the original's GL calls.""" + out = [] + for layer in frame.layers: + base = _lift(-ks.EYE_Z) @ _lift(layer.lift) @ _rotz(layer.turn) + for tri in layer.triangles: + m = base @ _rotz(tri.turn) + out.append([(*tri.st[i], *(m @ np.array((*tri.xyz[i], 1.0)))[:3]) + for i in range(3)]) + return np.array(out) + + +# -------------------------------------------------------------------------- +# 1. The engine against the original +# -------------------------------------------------------------------------- + +class TestAgainstTheOriginal: + def test_every_frame_matches(self): + engine = ks.Kaleidostrobe(seed=1000, ticks=1000) # srand(TickCount()) + engine.set_size(640, 480) + counts = GOLDEN["tri_counts"] + offsets = np.concatenate([[0], np.cumsum(counts)]) + for f, (spectrum, ticks) in enumerate(zip(GOLDEN["spectra"], GOLDEN["ticks"])): + frame = engine.step(spectrum, int(ticks)) + for tex in (0, 1): + assert _digest(frame.textures[tex]) == GOLDEN["tex_digest"][f][tex], \ + f"frame {f}, texture {tex}" + ours = _eye_space(frame) + theirs = GOLDEN["tris"][offsets[f]:offsets[f + 1]] + assert ours.shape == theirs.shape, f"frame {f}" + np.testing.assert_allclose(ours[..., :2], theirs[..., :2], atol=1e-4) + np.testing.assert_allclose(ours[..., 2:], theirs[..., 2:], atol=1e-3) + + def test_the_run_saw_beats_and_switches(self): + """The recorded run must exercise more than the opening state.""" + engine = ks.Kaleidostrobe(seed=1000, ticks=1000) + deltas = set() + for spectrum, ticks in zip(GOLDEN["spectra"], GOLDEN["ticks"]): + engine.step(spectrum, int(ticks)) + deltas.add(tuple(engine.cur_delta)) + assert engine.beat_count >= 8 + assert len(deltas) > 1 + + +# -------------------------------------------------------------------------- +# 2. The pieces +# -------------------------------------------------------------------------- + +class TestPieces: + @pytest.mark.parametrize("i, n", list(enumerate(ks.DELTA_TABLE))) + def test_every_warp_matches(self, i, n): + state = {} + for it in range(3): + out = ks.delta(n, _pattern(n * 3 + it), state) + assert _digest(out) == GOLDEN["delta_digest"][i][it], f"iteration {it}" + + @pytest.mark.parametrize("idx", range(len(ks.WAVE_TABLE))) + def test_every_wave_matches(self, idx): + engine = ks.Kaleidostrobe(seed=1, ticks=1000) + engine.rng = ks.ParkMiller(4321) + engine.cur_wave[0] = idx + engine._init_wave(0) + assert _digest(engine.buffers[0, 0]) == GOLDEN["wave_digest"][idx] + + def test_rand_is_darwins(self): + rng = ks.ParkMiller(1) + assert [rng.rand() for _ in range(3)] == [16807, 282475249, 1622650073] + + def test_flip_diag_keeps_its_off_by_one(self): + img = np.arange(128 * 128, dtype=np.int64).reshape(128, 128) % 251 + img = img.astype(np.uint8) + before = img.copy() + ks.flip_diag(img) + assert img[10, 3] == before[3, 10] # transposed… + assert img[10, 9] == before[10, 9] # …except beside the diagonal + assert img[9, 10] == before[9, 10] + + def test_inside_out_flips_each_half(self): + img = np.repeat(np.arange(128, dtype=np.uint8)[:, None], 128, 1) + ks.inside_out(img) + assert img[0, 0] == 63 and img[63, 0] == 0 + assert img[64, 0] == 127 and img[127, 0] == 64 + + def test_a_reselected_warp_resumes_its_own_counter(self): + engine = ks.Kaleidostrobe(seed=3, ticks=1000) + engine.cur_delta = [0, 0] # calcDelta000 on both layers + for _ in range(5): + engine._update_textures() + engine.cur_delta[0] = 1 # another warp: its own counter, 0 + engine._update_textures() + assert engine.delta_state[0][1] == {'h': 1, 'v': 1} + assert engine.delta_state[0][0] == {'h': 5} + + +# -------------------------------------------------------------------------- +# 3. The renderer +# -------------------------------------------------------------------------- + +def _frame(dt=0.016, seconds=4096 / RATE, hz=60.0): + t = np.arange(int(seconds * RATE)) / RATE + samples = (0.4 * np.sin(2 * np.pi * hz * t)).astype(np.float32) + return vs.Frame(samples, RATE, np.zeros(0, np.float32), dt) + + +def _paint(renderer, w, h, background="white", color="blue"): + img = QImage(w, h, QImage.Format.Format_RGB32) + img.fill(QColor(background)) + painter = QPainter(img) + renderer.paint(painter, QRectF(0, 0, w, h), QColor(color), QColor("gray")) + painter.end() + a = np.frombuffer(img.constBits().asstring(img.sizeInBytes()), np.uint8) + return a.reshape(h, w, 4)[..., [2, 1, 0]].astype(float) + + +def _bilinear(tex, s, t): + u, v = s * 128 - 0.5, t * 128 - 0.5 + u0, v0 = np.floor(u).astype(int), np.floor(v).astype(int) + fu, fv = (u - u0)[..., None], (v - v0)[..., None] + T = tex.astype(float) + + def at(y, x): + return T[y % 128, x % 128] + return (at(v0, u0) * (1 - fu) * (1 - fv) + at(v0, u0 + 1) * fu * (1 - fv) + + at(v0 + 1, u0) * (1 - fu) * fv + at(v0 + 1, u0 + 1) * fu * fv) + + +def _gl_reference(frame, w, h): + """What OpenGL drew: cast a ray through each pixel centre, take the + nearest triangle, interpolate (s, t), GL_LINEAR + GL_REPEAT, blend.""" + f = 1 / math.tan(math.radians(ks.FOVY) / 2) + px, py = np.meshgrid(np.arange(w) + 0.5, np.arange(h) + 0.5) + d = np.stack([(2 * px / w - 1) * (w / h) / f, (1 - 2 * py / h) / f, + -np.ones_like(px)], -1) + out = np.zeros((h, w, 3)) + for layer in frame.layers: + depth = np.full((h, w), -np.inf) + col = np.zeros((h, w, 3)) + hit = np.zeros((h, w), bool) + base = _lift(-ks.EYE_Z) @ _lift(layer.lift) @ _rotz(layer.turn) + for tri in layer.triangles: + m = base @ _rotz(tri.turn) + p = np.array([(m @ np.array((*v, 1.0)))[:3] for v in tri.xyz]) + e1, e2 = p[1] - p[0], p[2] - p[0] + n = np.cross(e1, e2) + with np.errstate(divide='ignore', invalid='ignore'): + x = d * ((p[0] @ n) / (d @ n))[..., None] + d00, d01, d11 = e1 @ e1, e1 @ e2, e2 @ e2 + v2 = x - p[0] + den = d00 * d11 - d01 * d01 + b1 = (d11 * (v2 @ e1) - d01 * (v2 @ e2)) / den + b2 = (d00 * (v2 @ e2) - d01 * (v2 @ e1)) / den + b0 = 1 - b1 - b2 + take = (b0 >= 0) & (b1 >= 0) & (b2 >= 0) & (x[..., 2] > depth) + st = np.array(tri.st) + s = b0 * st[0, 0] + b1 * st[1, 0] + b2 * st[2, 0] + t = b0 * st[0, 1] + b1 * st[1, 1] + b2 * st[2, 1] + c = _bilinear(frame.textures[layer.texture][..., :3], s, t) + col[take] = c[take] + depth[take] = x[..., 2][take] + hit |= take + out[hit] = out[hit] * (1 - layer.alpha) + col[hit] * layer.alpha + return out + + +class TestRenderer: + def test_runs_at_the_plugins_25_fps(self, qapp): + r = KaleidostrobeRenderer() + for _ in range(125): # 2 s of 16 ms widget ticks + r.advance(_frame()) + assert r._engine.frame_count == 50 + + def test_a_stall_is_not_replayed(self, qapp): + r = KaleidostrobeRenderer() + r.advance(_frame()) + r.advance(_frame(dt=5.0)) # the GUI thread froze for 5 s + assert r._engine.frame_count <= 1 + 3 + + @pytest.mark.parametrize("frames", [3, 30, 90]) + def test_paints_what_opengl_drew(self, qapp, frames): + r = KaleidostrobeRenderer() + r.advance(_frame()) + r._engine.set_size(96, 60) + for _ in range(frames): + r.advance(_frame(dt=0.04)) + ours = _paint(r, 96, 60) + gl = _gl_reference(r._frame, 96, 60) + assert np.abs(ours - gl).max() <= 3 + + def test_fills_any_shape(self, qapp): + r = KaleidostrobeRenderer() + for _ in range(5): + r.advance(_frame(dt=0.04)) + for w, h in ((140, 36), (300, 900), (4, 4)): + img = _paint(r, w, h, background="magenta") + magenta = (img[..., 0] == 255) & (img[..., 1] == 0) & (img[..., 2] == 255) + assert not magenta.any() # the cone reaches every corner + + def test_dim_mode_is_gray(self, qapp): + r = KaleidostrobeRenderer() + for _ in range(5): + r.advance(_frame(dt=0.04)) + r.dimmed = True # the widget then passes its gray + img = _paint(r, 120, 80, color="gray") + assert np.abs(img[..., 0] - img[..., 2]).max() <= 2 # gray tint + + def test_pause_blanks_but_keeps_the_plugin(self, qapp): + r = KaleidostrobeRenderer() + for _ in range(5): + r.advance(_frame(dt=0.04)) + engine, count = r._engine, r._engine.frame_count + r.clear() + img = _paint(r, 40, 30, background="white") + assert (img == 255).all() # nothing drawn + r.advance(_frame(dt=0.04)) + assert r._engine is engine and engine.frame_count == count + 1 + + @pytest.mark.parametrize("rate", [44100, 48000, 96000]) + def test_spectrum_bins_are_itunes_43_hz(self, rate): + t = np.arange(4096) / rate + tone = (0.5 * np.sin(2 * np.pi * 1000 * t)).astype(np.float32) + spec = itunes_spectrum(tone, rate) + assert spec.shape == (2, 512) and spec.dtype == np.uint8 + assert abs(int(spec[0].argmax()) - round(1000 / (44100 / 1024))) <= 1 + assert (spec[0] == spec[1]).all() + + def test_silence_is_zero(self): + assert not itunes_spectrum(np.zeros(4096, np.float32), RATE).any() + + +# -------------------------------------------------------------------------- +# 4. In the app +# -------------------------------------------------------------------------- + +class _FakePlayer(QObject): + audio_buffer = pyqtSignal(object) + playing_changed = pyqtSignal(bool) + track_changed = pyqtSignal(object) + + def is_playing(self): + return False + + +class _LastFm(QObject): + login_finished = pyqtSignal(bool, str) + status_message = pyqtSignal(str) + + def is_logged_in(self): + return False + + +class TestInTheApp: + def test_is_a_style(self, qapp, tmp_path): + from lintunes.gui.visualizer import VisualizerWidget + prefs = Preferences(tmp_path) + prefs.set("visualizer_style", "kaleidostrobe") + vis = VisualizerWidget(_FakePlayer(), prefs) + assert isinstance(vis._renderer, KaleidostrobeRenderer) + + def test_preferences_offers_it(self, qapp, tmp_path): + from lintunes.gui.preferences_dialog import PreferencesDialog + prefs = Preferences(tmp_path) + dialog = PreferencesDialog(prefs, _LastFm()) + dialog._viz_radios["kaleidostrobe"].setChecked(True) + assert prefs.get("visualizer_style") == "kaleidostrobe" + assert dialog._viz_pages.currentIndex() == 3