maalata 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +155 -0
- package/dist/index.d.ts +111 -0
- package/dist/maalata.c368e3b2.es.js +853 -0
- package/dist/maalata.c368e3b2.es.js.map +1 -0
- package/dist/maalata.c368e3b2.umd.js +854 -0
- package/dist/maalata.c368e3b2.umd.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maalata.c368e3b2.es.js","sources":["../src/crt-shaders.ts","../src/crt-display.ts","../src/pipeline.ts","../src/maalata.ts"],"sourcesContent":["/**\n * CRT Post-Processing GLSL Shaders\n *\n * Combined from two open-source CRT shader implementations:\n *\n * - Ichiaka/CRTFilter v1.1.0 (MIT)\n * https://github.com/Ichiaka/CRTFilter\n * Original basis for the effects pipeline: barrel distortion, chromatic\n * aberration, static noise, horizontal tearing, glow/bloom, vertical jitter,\n * signal loss, scanlines, dot mask, desaturation, contrast/brightness, flicker.\n *\n * - gingerbeardman/webgl-crt-shader (MIT)\n * https://github.com/gingerbeardman/webgl-crt-shader\n * Performance optimizations adopted: early-out guards for disabled effects,\n * out-of-bounds check after barrel distortion, vignette function (Chebyshev\n * distance squared), `highp` precision selection via GL_FRAGMENT_PRECISION_HIGH,\n * combined lighting mask (scanlines + flicker + vignette in single multiply),\n * configurable scanline count uniform.\n *\n * - Blur Busters CRT Beam Simulator (MIT)\n * https://github.com/blurbusters/crt-beam-simulator\n * By Mark Rejhon (@BlurBusters) & Timothy Lottes (@NOTimothyLottes)\n * Rolling scan BFI with phosphor decay and variable per-pixel MPRT.\n * Adapted: 3-frame trailing buffer, interval overlap formula, gamma-correct\n * operations, GAIN_VS_BLUR tradeoff, per-channel independent processing.\n *\n * Design decisions for the combined shader:\n * - Pipeline reordered so all UV modifications (jitter, tearing) happen before\n * any texture reads, eliminating one redundant texture read from the original.\n * - Chromatic aberration conditional: 1 texture read when aberration ≈ 0,\n * 3 reads only when active. This is the biggest per-fragment win.\n * - Every effect block guarded by `> 0.0001` threshold check for early-out.\n * - Bool uniforms (u_retrace, u_dotMask) replaced with float intensity values\n * so they participate in the same early-out pattern.\n * - Vignette from gingerbeardman added as part of the combined lighting mask.\n * - gingerbeardman's 5-tap bloom intentionally NOT adopted (4 extra texture\n * reads per fragment); current smoothstep glow is much cheaper.\n * - Noise hash seeded with u_time for temporal variation (animated static).\n */\n\n/**\n * Vertex shader: fullscreen quad [0,1] → clip space [-1,1].\n * Same coordinate mapping as the passthrough vertex shader in canvas-ultrafast.\n */\nexport const CRT_VERTEX_SRC = `\n attribute vec2 a_position;\n varying vec2 v_texCoord;\n void main() {\n v_texCoord = a_position;\n gl_Position = vec4(a_position * 2.0 - 1.0, 0, 1);\n }\n`;\n\n/**\n * Fragment shader: CRT effects pipeline (optimized).\n *\n * Pipeline order (UV modifications first, texture reads second):\n * 1. Barrel distortion + curvature → OOB early-out\n * 2. Vertical jitter (UV offset, conditional)\n * 3. Horizontal tearing (UV offset, conditional)\n * 4. Texture sampling — 4-way: BFI×aberration (1/3/3/9 reads)\n * 5. Static noise (conditional)\n * 6. Glow/bloom (conditional)\n * 7. Signal loss (conditional)\n * 8. Combined lighting mask: scanlines + flicker + vignette → single multiply\n * 9. Dot mask (conditional, float intensity)\n * 10. Color: desaturation → contrast → brightness\n */\nexport const CRT_FRAGMENT_SRC = `\n // gingerbeardman: highp precision selection for better quality on capable GPUs\n #ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n #else\n precision mediump float;\n #endif\n\n varying vec2 v_texCoord;\n\n uniform sampler2D u_texture;\n uniform float u_time;\n uniform float u_barrel;\n uniform float u_aberration;\n uniform float u_noise;\n uniform float u_tearing;\n uniform float u_glow;\n uniform float u_jitter;\n uniform float u_brightness;\n uniform float u_contrast;\n uniform float u_desaturation;\n uniform float u_flicker;\n uniform float u_scanlineIntensity;\n uniform float u_scanlineCount;\n uniform float u_curvature;\n uniform float u_signalLoss;\n uniform float u_dotMask;\n uniform float u_vignetteStrength;\n\n // Blur Busters: BFI rolling scan uniforms\n uniform sampler2D u_framePrev2; // 2 CRT cycles ago\n uniform sampler2D u_framePrev1; // 1 CRT cycle ago\n uniform sampler2D u_frameCurr; // current CRT cycle\n uniform float u_bfiStrength; // 0 = off, > 0 = BFI active\n uniform float u_bfiPhase; // 0-1 beam scan position\n uniform float u_bfiFramesPerHz; // displayHz / crtHz\n uniform float u_bfiGainVsBlur; // brightness vs motion blur tradeoff\n\n // Blur Busters: gamma-correct operations prevent horizontal banding\n const float BFI_GAMMA = 2.2;\n vec3 bfiToLinear(vec3 c) { return pow(max(c, vec3(0.0)), vec3(BFI_GAMMA)); }\n vec3 bfiToGamma(vec3 c) { return pow(max(c, vec3(0.0)), vec3(1.0 / BFI_GAMMA)); }\n\n // Blur Busters rolling scan with phosphor decay + variable MPRT\n // Ported from getPixelFromSimulatedCRT in crt-simulator.glsl\n vec3 bfiCompute(vec3 pixPrev2, vec3 pixPrev1, vec3 pixCurr) {\n vec3 linPrev2 = bfiToLinear(pixPrev2);\n vec3 linPrev1 = bfiToLinear(pixPrev1);\n vec3 linCurr = bfiToLinear(pixCurr);\n\n // Photon budget: brighter pixels persist across more sub-frames (variable MPRT)\n float brightnessScale = u_bfiFramesPerHz * u_bfiGainVsBlur;\n vec3 cPrev2 = linPrev2 * brightnessScale;\n vec3 cPrev1 = linPrev1 * brightnessScale;\n vec3 cCurr = linCurr * brightnessScale;\n\n // Physical scan position (top=0, bottom=1), undistorted\n float tubePos = 1.0 - v_texCoord.y;\n\n // Current native frame's interval in CRT-cycle frame space\n float tubeFrame = tubePos * u_bfiFramesPerHz;\n float fStart = u_bfiPhase * u_bfiFramesPerHz;\n float fEnd = fStart + 1.0;\n\n vec3 result = vec3(0.0);\n\n // Per-channel: compute overlap between phosphor emission and current frame interval\n for (int ch = 0; ch < 3; ch++) {\n float Lprev2 = cPrev2[ch];\n float Lprev1 = cPrev1[ch];\n float Lcurr = cCurr[ch];\n if (Lprev2 <= 0.0 && Lprev1 <= 0.0 && Lcurr <= 0.0) continue;\n\n float s2 = tubeFrame - u_bfiFramesPerHz;\n float s1 = tubeFrame;\n float s0 = tubeFrame + u_bfiFramesPerHz;\n\n result[ch] = max(0.0, min(s2 + Lprev2, fEnd) - max(s2, fStart))\n + max(0.0, min(s1 + Lprev1, fEnd) - max(s1, fStart))\n + max(0.0, min(s0 + Lcurr, fEnd) - max(s0, fStart));\n }\n\n return bfiToGamma(result);\n }\n\n // Ichiaka: barrel distortion — same math in both implementations\n vec2 barrelDistortion(vec2 uv, float amount) {\n vec2 centered = uv - 0.5;\n float dist = dot(centered, centered);\n return uv + centered * dist * amount;\n }\n\n // gingerbeardman: vignette using Chebyshev distance squared\n // Cheaper than radial distance and produces a natural screen-edge darkening\n float vignette(vec2 uv, float strength) {\n vec2 d = abs(uv - 0.5) * 2.0;\n float v = max(d.x, d.y); // Chebyshev distance\n return 1.0 - strength * v * v; // squared falloff\n }\n\n void main() {\n vec2 uv = v_texCoord;\n\n // --- 1. Barrel distortion + curvature (Ichiaka) ---\n uv = barrelDistortion(uv, u_barrel + u_curvature);\n\n // gingerbeardman: OOB early-out after distortion — avoids all further work\n // for pixels that land outside the texture. Returns black immediately.\n if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n\n // --- 2. Vertical jitter (Ichiaka, moved before texture reads) ---\n // Originally applied after texture reads; moved here so the offset is\n // baked into the UV before sampling, saving a redundant texture read.\n if (u_jitter > 0.0001) {\n uv.y += sin(u_time * 5.0) * u_jitter;\n }\n\n // --- 3. Horizontal tearing (Ichiaka, moved before texture reads) ---\n // Originally applied after chromatic aberration, requiring a 4th texture\n // read. Moving the UV offset here eliminates that extra read entirely.\n if (u_tearing > 0.0001) {\n uv.x += sin(uv.y * 10.0 + u_time * 2.0) * u_tearing;\n }\n\n // --- 4. Texture sampling (combined optimization) ---\n // 4-way branch: BFI × aberration. When BFI active, sample from 3-frame\n // history buffer via bfiCompute(); when off, original u_texture path.\n vec3 col;\n if (u_bfiStrength > 0.0001) {\n if (u_aberration > 0.0001) {\n // BFI + aberration: 9 reads (3 frames × 3 UV offsets)\n vec2 uvR = uv + vec2(u_aberration, 0.0);\n vec2 uvB = uv - vec2(u_aberration, 0.0);\n vec3 p2 = vec3(texture2D(u_framePrev2, uvR).r, texture2D(u_framePrev2, uv).g, texture2D(u_framePrev2, uvB).b);\n vec3 p1 = vec3(texture2D(u_framePrev1, uvR).r, texture2D(u_framePrev1, uv).g, texture2D(u_framePrev1, uvB).b);\n vec3 p0 = vec3(texture2D(u_frameCurr, uvR).r, texture2D(u_frameCurr, uv).g, texture2D(u_frameCurr, uvB).b);\n col = bfiCompute(p2, p1, p0);\n } else {\n // BFI only: 3 reads (one per history texture)\n col = bfiCompute(\n texture2D(u_framePrev2, uv).rgb,\n texture2D(u_framePrev1, uv).rgb,\n texture2D(u_frameCurr, uv).rgb\n );\n }\n } else if (u_aberration > 0.0001) {\n // Aberration only: 3 reads from u_texture\n col.r = texture2D(u_texture, uv + vec2(u_aberration, 0.0)).r;\n col.g = texture2D(u_texture, uv).g;\n col.b = texture2D(u_texture, uv - vec2(u_aberration, 0.0)).b;\n } else {\n // No BFI, no aberration: 1 read\n col = texture2D(u_texture, uv).rgb;\n }\n\n // --- 5. Static noise (Ichiaka, enhanced with temporal variation) ---\n // Original used only UV for hash seed, producing a static pattern.\n // Adding u_time makes the noise animate, which is more CRT-authentic.\n if (u_noise > 0.0001) {\n float n = fract(sin(dot(uv.xy + u_time * 0.01, vec2(12.9898, 78.233))) * 43758.5453);\n col += (n - 0.5) * u_noise;\n }\n\n // --- 6. Glow/bloom (Ichiaka) ---\n // Cheap smoothstep-based glow. gingerbeardman uses a 5-tap bloom (4 extra\n // texture reads) which we intentionally skip for performance.\n if (u_glow > 0.0001) {\n col += u_glow * smoothstep(0.5, 1.0, col);\n }\n\n // --- 7. Signal loss (Ichiaka) ---\n if (u_signalLoss > 0.0001) {\n col *= 1.0 - (u_signalLoss * abs(sin(uv.y * 50.0 + u_time * 10.0)));\n }\n\n // --- 8. Combined lighting mask (gingerbeardman pattern) ---\n // Combine scanlines, flicker, and vignette into a single multiplier.\n // One multiply is cheaper than three separate multiply operations.\n float mask = 1.0;\n\n // Scanlines (Ichiaka effect, gingerbeardman's configurable count pattern)\n if (u_scanlineIntensity > 0.0001) {\n mask *= 1.9 + u_scanlineIntensity * sin(uv.y * u_scanlineCount + u_time * 10.0);\n }\n\n // Flicker (Ichiaka)\n if (u_flicker > 0.0001) {\n mask *= 1.0 + u_flicker * sin(u_time * 60.0);\n }\n\n // Vignette (gingerbeardman: Chebyshev distance squared)\n if (u_vignetteStrength > 0.0001) {\n mask *= vignette(uv, u_vignetteStrength);\n }\n\n col *= mask;\n\n // --- 9. Dot mask (Ichiaka, converted from bool to float intensity) ---\n // Original was a bool uniform; now float so it participates in early-out\n // pattern and allows variable intensity.\n if (u_dotMask > 0.0001) {\n vec3 dotEffect = vec3(\n 1.0,\n 0.9 + 0.1 * mod(uv.x * 100.0, 2.0),\n 0.9 + 0.1 * mod(uv.y * 100.0, 2.0)\n );\n col *= mix(vec3(1.0), dotEffect, u_dotMask);\n }\n\n // --- 10. Color adjustments (Ichiaka) ---\n // Desaturation\n if (u_desaturation > 0.0001) {\n float lum = dot(col, vec3(0.299, 0.587, 0.114));\n col = mix(col, vec3(lum), u_desaturation);\n }\n\n // Contrast\n col = (col - 0.5) * u_contrast + 0.5;\n\n // Brightness\n col *= u_brightness;\n\n gl_FragColor = vec4(col, 1.0);\n }\n`;\n","/**\n * CRT Display — Post-processing overlay for the \"2002 era\" experience.\n *\n * Takes ownership of the display loop on a shared WebGL2 context.\n * Reads from UltrafastRenderer's ready texture and applies CRT shader\n * effects (barrel distortion, scanlines, chromatic aberration, etc.)\n * before blitting to the default framebuffer.\n *\n * Shader lineage:\n * - Ichiaka/CRTFilter (MIT) — original effects pipeline\n * - gingerbeardman/webgl-crt-shader (MIT) — performance optimizations + vignette\n *\n * See crt-shaders.ts for detailed attribution and per-effect documentation.\n *\n * Config is backward-compatible: existing boolean fields (retraceLines, dotMask)\n * are accepted and converted to float uniforms internally. New fields\n * (vignetteStrength, scanlineCount) default to off / current behavior.\n */\n\nimport { CRT_VERTEX_SRC, CRT_FRAGMENT_SRC } from './crt-shaders';\n\nexport interface CRTConfig {\n barrelDistortion: number;\n curvature: number;\n chromaticAberration: number;\n staticNoise: number;\n horizontalTearing: number;\n glowBloom: number;\n verticalJitter: number;\n retraceLines: boolean;\n scanlineIntensity: number;\n dotMask: boolean;\n brightness: number;\n contrast: number;\n desaturation: number;\n flicker: number;\n signalLoss: number;\n vignetteStrength: number;\n scanlineCount: number;\n bfiStrength: number;\n bfiTargetHz: number;\n bfiGainVsBlur: number;\n}\n\nconst _DEFAULT_CRT_CONFIG: CRTConfig = {\n barrelDistortion: 0.001,\n curvature: 0.002,\n chromaticAberration: 0.0005,\n staticNoise: 0.001,\n horizontalTearing: 0.00012,\n glowBloom: 0.001,\n verticalJitter: 0.001,\n retraceLines: true,\n scanlineIntensity: 0.6,\n dotMask: false,\n brightness: 0.9,\n contrast: 1.0,\n desaturation: 0.2,\n flicker: 0.01,\n signalLoss: 0.05,\n vignetteStrength: 0,\n scanlineCount: 800,\n bfiStrength: 0,\n bfiTargetHz: 60,\n bfiGainVsBlur: 0.7,\n};\n\ninterface _CRTUniforms {\n _time: WebGLUniformLocation | null;\n _barrel: WebGLUniformLocation | null;\n _aberration: WebGLUniformLocation | null;\n _noise: WebGLUniformLocation | null;\n _tearing: WebGLUniformLocation | null;\n _glow: WebGLUniformLocation | null;\n _jitter: WebGLUniformLocation | null;\n _dotMask: WebGLUniformLocation | null;\n _brightness: WebGLUniformLocation | null;\n _contrast: WebGLUniformLocation | null;\n _desaturation: WebGLUniformLocation | null;\n _flicker: WebGLUniformLocation | null;\n _scanlineIntensity: WebGLUniformLocation | null;\n _scanlineCount: WebGLUniformLocation | null;\n _curvature: WebGLUniformLocation | null;\n _signalLoss: WebGLUniformLocation | null;\n _vignetteStrength: WebGLUniformLocation | null;\n _bfiStrength: WebGLUniformLocation | null;\n _bfiPhase: WebGLUniformLocation | null;\n _bfiFramesPerHz: WebGLUniformLocation | null;\n _bfiGainVsBlur: WebGLUniformLocation | null;\n}\n\nexport class CRTDisplay {\n private _gl: WebGL2RenderingContext;\n private _canvas: HTMLCanvasElement;\n private _program: WebGLProgram;\n private _uniforms: _CRTUniforms;\n private _quadVBO: WebGLBuffer;\n private _quadPositionLoc: number;\n private _rafId: number | null = null;\n private _getReadyTexture: () => WebGLTexture;\n private _hasContent: () => boolean;\n\n // BFI state\n private _frameCount = 0;\n private _bfiActive = false;\n private _measuredHz = 0;\n private _smoothDelta = 0;\n private _lastFrameTime = 0;\n private _bfiCfgStrength = 0;\n private _bfiTargetHz = 60;\n private _bfiGainVsBlur = 0.7;\n private _historyTextures: WebGLTexture[] = [];\n private _historyFbos: WebGLFramebuffer[] = [];\n private _srcFbo: WebGLFramebuffer | null = null;\n private _historyIndex = 0;\n private _lastCrtCycle = -1;\n private _historyInitialized = false;\n\n constructor(\n gl: WebGL2RenderingContext,\n canvas: HTMLCanvasElement,\n getReadyTexture: () => WebGLTexture,\n hasContent: () => boolean,\n config?: Partial<CRTConfig>,\n ) {\n this._gl = gl;\n this._canvas = canvas;\n this._getReadyTexture = getReadyTexture;\n this._hasContent = hasContent;\n\n // Create CRT shader program\n this._program = this._createShaderProgram(CRT_VERTEX_SRC, CRT_FRAGMENT_SRC);\n\n // Cache uniform locations\n this._uniforms = this._cacheCRTUniforms(this._program);\n\n // Set CRT config uniforms\n this._setCRTConfig(config);\n\n // Create own fullscreen quad VBO\n this._quadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n this._quadPositionLoc = gl.getAttribLocation(this._program, 'a_position');\n }\n\n /** Render one CRT frame — reads ready texture, applies effects, blits to screen. */\n render(): void {\n if (!this._hasContent()) return;\n\n const gl = this._gl;\n const u = this._uniforms;\n\n // BFI: detect cycle boundary, capture frame, bind history, set uniforms\n if (this._bfiActive && this._historyInitialized) {\n const framesPerHz = this._measuredHz / this._bfiTargetHz;\n const currentCycle = Math.floor(this._frameCount / framesPerHz);\n\n if (currentCycle !== this._lastCrtCycle) {\n this._lastCrtCycle = currentCycle;\n this._historyIndex = (this._historyIndex + 1) % 3;\n this._captureFrame();\n }\n\n // Bind history textures: TEXTURE1=prev2, TEXTURE2=prev1, TEXTURE3=curr\n const idx = this._historyIndex;\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, this._historyTextures[(idx + 1) % 3]);\n gl.activeTexture(gl.TEXTURE2);\n gl.bindTexture(gl.TEXTURE_2D, this._historyTextures[(idx + 2) % 3]);\n gl.activeTexture(gl.TEXTURE3);\n gl.bindTexture(gl.TEXTURE_2D, this._historyTextures[idx]);\n }\n\n // Bind default framebuffer (display canvas)\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Bind ready texture\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._getReadyTexture());\n\n // Use CRT program\n gl.useProgram(this._program);\n gl.uniform1f(u._time, performance.now() / 1000.0);\n\n // BFI uniforms\n if (this._bfiActive && this._historyInitialized) {\n const framesPerHz = this._measuredHz / this._bfiTargetHz;\n const phase = (this._frameCount % framesPerHz) / framesPerHz;\n gl.uniform1f(u._bfiStrength!, this._bfiCfgStrength);\n gl.uniform1f(u._bfiPhase!, phase);\n gl.uniform1f(u._bfiFramesPerHz!, framesPerHz);\n gl.uniform1f(u._bfiGainVsBlur!, this._bfiGainVsBlur);\n } else {\n gl.uniform1f(u._bfiStrength!, 0.0);\n }\n\n // Draw fullscreen quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.enableVertexAttribArray(this._quadPositionLoc);\n gl.vertexAttribPointer(this._quadPositionLoc, 2, gl.FLOAT, false, 0, 0);\n\n gl.disable(gl.BLEND);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n gl.enable(gl.BLEND);\n }\n\n /** Start CRT RAF display loop. */\n start(): void {\n if (this._rafId !== null) return;\n // Reset BFI timing state for re-calibration after idle resume\n this._lastFrameTime = 0;\n this._smoothDelta = 0;\n this._bfiActive = false;\n this._loop();\n }\n\n /** Stop CRT RAF display loop. */\n stop(): void {\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n }\n\n /** Clean up resources. */\n destroy(): void {\n this.stop();\n const gl = this._gl;\n gl.deleteProgram(this._program);\n gl.deleteBuffer(this._quadVBO);\n\n // Clean up BFI frame history resources\n for (const tex of this._historyTextures) gl.deleteTexture(tex);\n for (const fbo of this._historyFbos) gl.deleteFramebuffer(fbo);\n if (this._srcFbo) gl.deleteFramebuffer(this._srcFbo);\n this._historyTextures = [];\n this._historyFbos = [];\n this._srcFbo = null;\n this._historyInitialized = false;\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n private _loop(): void {\n this._rafId = requestAnimationFrame(() => this._loop());\n this._frameCount = (this._frameCount + 1) % 100000;\n if (this._bfiCfgStrength > 0) {\n this._updateHz();\n }\n this.render();\n }\n\n private _cacheCRTUniforms(program: WebGLProgram): _CRTUniforms {\n const gl = this._gl;\n return {\n _time: gl.getUniformLocation(program, 'u_time'),\n _barrel: gl.getUniformLocation(program, 'u_barrel'),\n _aberration: gl.getUniformLocation(program, 'u_aberration'),\n _noise: gl.getUniformLocation(program, 'u_noise'),\n _tearing: gl.getUniformLocation(program, 'u_tearing'),\n _glow: gl.getUniformLocation(program, 'u_glow'),\n _jitter: gl.getUniformLocation(program, 'u_jitter'),\n _dotMask: gl.getUniformLocation(program, 'u_dotMask'),\n _brightness: gl.getUniformLocation(program, 'u_brightness'),\n _contrast: gl.getUniformLocation(program, 'u_contrast'),\n _desaturation: gl.getUniformLocation(program, 'u_desaturation'),\n _flicker: gl.getUniformLocation(program, 'u_flicker'),\n _scanlineIntensity: gl.getUniformLocation(program, 'u_scanlineIntensity'),\n _scanlineCount: gl.getUniformLocation(program, 'u_scanlineCount'),\n _curvature: gl.getUniformLocation(program, 'u_curvature'),\n _signalLoss: gl.getUniformLocation(program, 'u_signalLoss'),\n _vignetteStrength: gl.getUniformLocation(program, 'u_vignetteStrength'),\n _bfiStrength: gl.getUniformLocation(program, 'u_bfiStrength'),\n _bfiPhase: gl.getUniformLocation(program, 'u_bfiPhase'),\n _bfiFramesPerHz: gl.getUniformLocation(program, 'u_bfiFramesPerHz'),\n _bfiGainVsBlur: gl.getUniformLocation(program, 'u_bfiGainVsBlur'),\n };\n }\n\n private _setCRTConfig(config?: Partial<CRTConfig>): void {\n const gl = this._gl;\n const c = { ..._DEFAULT_CRT_CONFIG, ...config };\n const u = this._uniforms;\n\n gl.useProgram(this._program);\n gl.uniform1f(u._barrel!, c.barrelDistortion);\n gl.uniform1f(u._aberration!, c.chromaticAberration);\n gl.uniform1f(u._noise!, c.staticNoise);\n gl.uniform1f(u._tearing!, c.horizontalTearing);\n gl.uniform1f(u._glow!, c.glowBloom);\n gl.uniform1f(u._jitter!, c.verticalJitter);\n gl.uniform1f(u._brightness!, c.brightness);\n gl.uniform1f(u._contrast!, c.contrast);\n gl.uniform1f(u._desaturation!, c.desaturation);\n gl.uniform1f(u._flicker!, c.flicker);\n gl.uniform1f(u._curvature!, c.curvature);\n gl.uniform1f(u._signalLoss!, c.signalLoss);\n gl.uniform1f(u._scanlineCount!, c.scanlineCount);\n gl.uniform1f(u._vignetteStrength!, c.vignetteStrength);\n\n // Backward compatibility: boolean retraceLines controls scanlineIntensity\n // When retraceLines is false, zero out scanline intensity to disable the effect\n gl.uniform1f(u._scanlineIntensity!, c.retraceLines ? c.scanlineIntensity : 0.0);\n\n // Backward compatibility: boolean dotMask converted to float intensity\n // true → 1.0 (full effect), false → 0.0 (disabled via early-out in shader)\n gl.uniform1f(u._dotMask!, c.dotMask ? 1.0 : 0.0);\n\n const texLoc = gl.getUniformLocation(this._program, 'u_texture');\n gl.uniform1i(texLoc, 0);\n\n // BFI config\n this._bfiCfgStrength = c.bfiStrength;\n this._bfiTargetHz = c.bfiTargetHz;\n this._bfiGainVsBlur = c.bfiGainVsBlur;\n gl.uniform1f(u._bfiStrength!, 0.0); // starts off, activated by Hz detection\n gl.uniform1f(u._bfiGainVsBlur!, c.bfiGainVsBlur);\n\n // Initialize frame history ring buffer if BFI is configured\n if (c.bfiStrength > 0 && !this._historyInitialized) {\n this._initHistory();\n\n // Set sampler uniform bindings (once)\n const prev2Loc = gl.getUniformLocation(this._program, 'u_framePrev2');\n const prev1Loc = gl.getUniformLocation(this._program, 'u_framePrev1');\n const currLoc = gl.getUniformLocation(this._program, 'u_frameCurr');\n gl.uniform1i(prev2Loc, 1);\n gl.uniform1i(prev1Loc, 2);\n gl.uniform1i(currLoc, 3);\n }\n }\n\n /** Allocate 3 history textures + FBOs + source FBO for frame capture. */\n private _initHistory(): void {\n const gl = this._gl;\n const w = this._canvas.width;\n const h = this._canvas.height;\n\n for (let i = 0; i < 3; i++) {\n const tex = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n this._historyTextures.push(tex);\n\n const fbo = gl.createFramebuffer()!;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);\n this._historyFbos.push(fbo);\n }\n\n // Source FBO for reading from ready texture via blitFramebuffer\n this._srcFbo = gl.createFramebuffer()!;\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.bindTexture(gl.TEXTURE_2D, null);\n this._historyInitialized = true;\n }\n\n /** GPU-copy ready texture into current history slot via blitFramebuffer. */\n private _captureFrame(): void {\n const gl = this._gl;\n const w = this._canvas.width;\n const h = this._canvas.height;\n\n // Bind ready texture as READ source\n gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._srcFbo);\n gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._getReadyTexture(), 0);\n\n // Bind current history slot as DRAW target\n gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this._historyFbos[this._historyIndex]);\n\n gl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);\n\n gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);\n gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);\n }\n\n /** EMA-based Hz detection with hysteresis for BFI activation. */\n private _updateHz(): void {\n const now = performance.now();\n if (this._lastFrameTime === 0) {\n this._lastFrameTime = now;\n return;\n }\n\n const delta = now - this._lastFrameTime;\n this._lastFrameTime = now;\n\n // Tab-background guard: reset EMA when delta > 100ms\n if (delta > 100) {\n this._smoothDelta = 0;\n return;\n }\n\n // EMA with alpha ≈ 0.05 (converges in ~20 frames)\n if (this._smoothDelta === 0) {\n this._smoothDelta = delta;\n } else {\n this._smoothDelta += (delta - this._smoothDelta) * 0.05;\n }\n\n this._measuredHz = 1000 / this._smoothDelta;\n\n const framesPerHz = this._measuredHz / this._bfiTargetHz;\n\n // Hysteresis: activate at ≥120Hz, deactivate at <110Hz\n // Guard: only activate when framesPerHz ≥ 1.5\n if (!this._bfiActive) {\n if (this._measuredHz >= 120 && framesPerHz >= 1.5) {\n this._bfiActive = true;\n }\n } else {\n if (this._measuredHz < 110) {\n this._bfiActive = false;\n }\n }\n }\n\n private _createShaderProgram(vSrc: string, fSrc: string): WebGLProgram {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n return program;\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n","/**\n * Click-to-Photon Latency Pipeline\n *\n * Models 4 discrete stages of a 2002-era hardware/software pipeline,\n * from USB input polling to LCD panel response. Each stage is a class with\n * historically-accurate timing derived from real measurements of the era.\n *\n * Total worst-case latency: 8 + 10 + 125 + 25 = 168ms\n * Average latency: ~119ms (USB avg 4ms, AppFrame avg 62.5ms phase jitter)\n *\n * GPU queuing latency is now handled by real WebGL triple-buffer FBOs in\n * the WebGLRenderer rather than a simulated delay stage. The triple buffer\n * provides natural 1–2 frame buffering (0–33ms at 60Hz) that replaces the\n * previous 50ms GPUDriverQueue setTimeout.\n *\n * References:\n * - Dan Luu's input lag measurements (iMac G4 2002)\n * - USB 1.1 HID polling specification (125Hz default)\n * - Windows XP timer resolution and scheduling\n * - 2002 TN panel response times (Dell 1504FP: 25ms)\n */\n\nimport type { CanvasCommand } from 'canvas-ultrafast';\n\ntype Sink = (batch: CanvasCommand[]) => void;\n\n// ---------------------------------------------------------------------------\n// Base classes\n// ---------------------------------------------------------------------------\n\nabstract class PipelineStage {\n protected _sink: Sink | null = null;\n\n /** Connect output to a raw callback. No _ prefix: cross-file access. */\n pipe(sink: Sink): void { this._sink = sink; }\n\n /** Connect output to the next stage. Returns the target for chaining. */\n pipeTo(stage: PipelineStage): PipelineStage {\n this._sink = (batch) => stage.receive(batch);\n return stage;\n }\n\n /** Accept a batch of commands from the previous stage. */\n abstract receive(batch: CanvasCommand[]): void;\n\n /** Tear down timers and resources. */\n abstract destroy(): void;\n\n protected _forward(batch: CanvasCommand[]): void { this._sink?.(batch); }\n}\n\n/**\n * A pipeline stage that applies a fixed delay before forwarding.\n * Subclasses only need to declare _DELAY_MS.\n */\nabstract class DelayStage extends PipelineStage {\n protected abstract readonly _DELAY_MS: number;\n private _timers: ReturnType<typeof setTimeout>[] = [];\n\n receive(batch: CanvasCommand[]): void {\n const timer = setTimeout(() => {\n const idx = this._timers.indexOf(timer);\n if (idx !== -1) this._timers.splice(idx, 1);\n this._forward(batch);\n }, this._DELAY_MS);\n this._timers.push(timer);\n }\n\n destroy(): void {\n for (const t of this._timers) clearTimeout(t);\n this._timers = [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stage 1: USB Polling (pull-based, 125Hz / 8ms)\n// ---------------------------------------------------------------------------\n\n/**\n * Polls the CanvasAPI command buffer at 8ms intervals — mirrors how USB 1.1\n * HID host controllers poll devices at a fixed 125Hz rate, reading whatever\n * input reports have accumulated since the last poll.\n */\nexport class USBPolling extends PipelineStage {\n private readonly _POLL_MS = 8;\n private _interval: ReturnType<typeof setInterval> | null = null;\n private _source: (() => CanvasCommand[]) | null;\n\n constructor(source: () => CanvasCommand[]) {\n super();\n this._source = source;\n this._interval = setInterval(() => this._poll(), this._POLL_MS);\n }\n\n private _poll(): void {\n const cmds = this._source?.();\n if (cmds && cmds.length > 0) this._forward(cmds);\n }\n\n receive(): void {} // Pull-based; ignores pushed batches\n destroy(): void {\n if (this._interval !== null) { clearInterval(this._interval); this._interval = null; }\n this._source = null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stage 2: OS Kernel Processing (10ms delay)\n// ---------------------------------------------------------------------------\n\n/**\n * Windows XP interrupt handling: ISR processes USB completion (~1ms),\n * DPC queues the input message (~1ms), thread scheduling adds jitter\n * on a loaded 2002 system. 10ms total accounts for realistic scheduling\n * latency without conflating with the 15.6ms timer tick (which only\n * affects Sleep()-based timing, not input delivery).\n */\nexport class OSKernelProcessing extends DelayStage {\n protected readonly _DELAY_MS = 10;\n}\n\n// ---------------------------------------------------------------------------\n// Stage 3: Application Frame (collecting, 125ms tick / 8 FPS)\n// ---------------------------------------------------------------------------\n\n/**\n * Game loop processes all pending input once per frame. Collects incoming\n * batches between frame boundaries, delivers as one merged batch at each\n * 125ms tick. The demo's own 8 FPS drawing loop and this stage's 125ms\n * tick are unsynchronized, creating 0–125ms phase jitter (avg 62.5ms) —\n * historically accurate since USB polling and app frame ticks were never\n * synchronized in 2002.\n */\nexport class ApplicationFrame extends PipelineStage {\n private readonly _FRAME_MS = 125;\n private _buffer: CanvasCommand[] = [];\n private _interval: ReturnType<typeof setInterval> | null = null;\n\n constructor() {\n super();\n this._interval = setInterval(() => this._tick(), this._FRAME_MS);\n }\n\n receive(batch: CanvasCommand[]): void {\n this._buffer.push(...batch);\n }\n\n private _tick(): void {\n if (this._buffer.length === 0) return;\n const batch = this._buffer;\n this._buffer = [];\n this._forward(batch);\n }\n\n destroy(): void {\n if (this._interval !== null) { clearInterval(this._interval); this._interval = null; }\n this._buffer = [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stage 4: LCD Panel (25ms delay)\n// ---------------------------------------------------------------------------\n\n/**\n * 2002 TN panel physical pixel transition time. The Dell 1504FP (2002)\n * was rated 25ms. GTG transitions were 30–40ms. The 50ms figure only\n * applied to VA/IPS panels, which were rare on desktops.\n */\nexport class LCDPanel extends DelayStage {\n protected readonly _DELAY_MS = 25;\n}\n","/**\n * Maalata — \"2002 era\" Retro Canvas Experience\n *\n * Combines canvas-ultrafast's WebGL Canvas 2D renderer with:\n * - 4-stage click-to-photon latency pipeline (168ms worst-case)\n * - CRT post-processing shader (barrel distortion, scanlines, etc.)\n * - 60s idle shutdown with transparent restart\n *\n * Public API is backward compatible with the monolithic library.\n */\n\nimport { UltrafastRenderer, CanvasAPI, type CanvasCommand } from 'canvas-ultrafast';\nimport { CRTDisplay, type CRTConfig } from './crt-display';\nimport { USBPolling, OSKernelProcessing, ApplicationFrame, LCDPanel } from './pipeline';\n\nexport { CanvasAPI } from 'canvas-ultrafast';\nexport { type CRTConfig } from './crt-display';\n\nexport interface RendererConfig {\n canvas: HTMLCanvasElement;\n /** Enable CRT post-processing filter. Default: true */\n crt?: boolean;\n /** CRT filter parameters. Only used when crt is enabled. */\n crtConfig?: Partial<CRTConfig>;\n}\n\nexport type RendererEvent =\n | { type: 'ready' }\n | { type: 'resuming' }\n | { type: 'canvas-replaced'; canvas: HTMLCanvasElement }\n | { type: 'suspending'; done: () => void }\n | { type: 'canvas-replacing'; done: () => void };\n\ntype RendererState = 'active' | 'suspended' | 'starting';\n\nexport class CanvasRenderer {\n private _canvas: HTMLCanvasElement;\n private _renderer: UltrafastRenderer;\n private _crtDisplay: CRTDisplay | null = null;\n private _crtEnabled: boolean;\n private _canvasAPI: CanvasAPI;\n private _eventListeners: Map<string, Set<(event: RendererEvent) => void>> = new Map();\n private _initPromise: Promise<void>;\n private _hasContent = false;\n\n // Pipeline stages\n private _pipelineStages: { destroy(): void }[] = [];\n\n // Last submitted batch (for visibility change replay)\n private _lastBatch: CanvasCommand[] = [];\n\n // Idle shutdown state machine\n private _state: RendererState = 'active';\n private _idleTimer: number | null = null;\n private readonly _IDLE_TIMEOUT_MS = 60_000;\n\n private _boundActivityHandler = (): void => {\n if (this._state === 'active') this._resetIdleTimer();\n };\n\n private _boundVisibilityHandler = (): void => {\n if (document.visibilityState !== 'visible' || this._lastBatch.length === 0) return;\n this._ensureActive();\n this._resetIdleTimer();\n this._renderer.submitBatch(this._lastBatch);\n };\n\n constructor(config: RendererConfig) {\n this._canvas = config.canvas;\n this._crtEnabled = config.crt ?? true;\n\n // Create UltrafastRenderer on the user's canvas\n this._renderer = new UltrafastRenderer(this._canvas);\n\n // Immediately stop the passthrough display — we control the display loop\n this._renderer.stopDisplay();\n\n // Get the shared CanvasAPI from the renderer\n this._canvasAPI = this._renderer.getCanvasAPI();\n\n // Set up CRT or passthrough display\n if (this._crtEnabled) {\n this._crtDisplay = new CRTDisplay(\n this._renderer.getGL(),\n this._canvas,\n () => this._renderer.getReadyTexture(),\n () => this._hasContent,\n config.crtConfig,\n );\n this._crtDisplay.start();\n } else {\n // No CRT — restart the passthrough display\n this._renderer.startDisplay();\n }\n\n // Build the 4-stage latency pipeline\n this._buildPipeline();\n\n // Activity listeners for idle detection\n this._attachActivityListeners(this._canvas);\n document.addEventListener('visibilitychange', this._boundVisibilityHandler);\n\n // No async init needed — WebGL context is ready synchronously.\n this._initPromise = Promise.resolve();\n this._resetIdleTimer();\n\n // Dispatch ready event asynchronously\n queueMicrotask(() => this._dispatchEvent({ type: 'ready' }));\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n public ready(): Promise<void> {\n return this._initPromise;\n }\n\n public getCanvas(): HTMLCanvasElement {\n return this._renderer.getCanvas();\n }\n\n public getCanvasAPI(): CanvasAPI {\n return this._canvasAPI;\n }\n\n public on<K extends RendererEvent['type']>(\n eventType: K,\n callback: (event: Extract<RendererEvent, { type: K }>) => void\n ): () => void {\n if (!this._eventListeners.has(eventType)) {\n this._eventListeners.set(eventType, new Set());\n }\n this._eventListeners.get(eventType)!.add(callback as (event: RendererEvent) => void);\n\n return () => {\n const listeners = this._eventListeners.get(eventType);\n if (listeners) {\n listeners.delete(callback as (event: RendererEvent) => void);\n }\n };\n }\n\n public screenshot(): Promise<ImageBitmap> {\n // Trigger a synchronous CRT render so the canvas has the latest frame\n if (this._crtDisplay) {\n this._crtDisplay.render();\n }\n return createImageBitmap(this._canvas);\n }\n\n public getCanvasSize(): { width: number; height: number } {\n return this._renderer.getCanvasSize();\n }\n\n public destroy(): void {\n document.removeEventListener('visibilitychange', this._boundVisibilityHandler);\n this._detachActivityListeners(this._canvas);\n this._cancelIdleTimer();\n this._destroyPipeline();\n if (this._crtDisplay) {\n this._crtDisplay.destroy();\n this._crtDisplay = null;\n }\n this._renderer.destroy();\n this._state = 'suspended';\n this._eventListeners.clear();\n }\n\n // -------------------------------------------------------------------------\n // Private: click-to-photon pipeline\n // -------------------------------------------------------------------------\n\n private _buildPipeline(): void {\n const usb = new USBPolling(() => this._canvasAPI.takeCommands());\n const os = new OSKernelProcessing();\n const app = new ApplicationFrame();\n const lcd = new LCDPanel();\n\n usb.pipeTo(os).pipeTo(app).pipeTo(lcd);\n lcd.pipe((batch) => this._submitToRenderer(batch));\n\n this._pipelineStages = [usb, os, app, lcd];\n }\n\n private _destroyPipeline(): void {\n for (const stage of this._pipelineStages) stage.destroy();\n this._pipelineStages = [];\n }\n\n private _submitToRenderer(batch: CanvasCommand[]): void {\n if (batch.length === 0) return;\n this._ensureActive();\n this._resetIdleTimer();\n this._renderer.submitBatch(batch);\n this._hasContent = true;\n this._lastBatch = batch;\n }\n\n // -------------------------------------------------------------------------\n // Private: idle shutdown lifecycle\n // -------------------------------------------------------------------------\n\n private _attachActivityListeners(canvas: HTMLCanvasElement): void {\n canvas.addEventListener('mousemove', this._boundActivityHandler);\n canvas.addEventListener('mousedown', this._boundActivityHandler);\n canvas.addEventListener('touchstart', this._boundActivityHandler, { passive: true });\n canvas.addEventListener('touchmove', this._boundActivityHandler, { passive: true });\n }\n\n private _detachActivityListeners(canvas: HTMLCanvasElement): void {\n canvas.removeEventListener('mousemove', this._boundActivityHandler);\n canvas.removeEventListener('mousedown', this._boundActivityHandler);\n canvas.removeEventListener('touchstart', this._boundActivityHandler);\n canvas.removeEventListener('touchmove', this._boundActivityHandler);\n }\n\n private _resetIdleTimer(): void {\n this._cancelIdleTimer();\n this._idleTimer = window.setTimeout(() => {\n this._suspend();\n }, this._IDLE_TIMEOUT_MS);\n }\n\n private _cancelIdleTimer(): void {\n if (this._idleTimer !== null) {\n clearTimeout(this._idleTimer);\n this._idleTimer = null;\n }\n }\n\n private async _suspend(): Promise<void> {\n if (this._state !== 'active') return;\n this._cancelIdleTimer();\n await this._dispatchAwaited('suspending');\n if (this._crtDisplay) {\n this._crtDisplay.stop();\n } else {\n this._renderer.stopDisplay();\n }\n this._state = 'suspended';\n }\n\n private _ensureActive(): void {\n if (this._state === 'active') return;\n\n if (this._state === 'suspended') {\n this._state = 'starting';\n this._dispatchEvent({ type: 'resuming' });\n\n // Backward-compatible no-op events\n this._dispatchEvent({ type: 'canvas-replacing', done: () => {} } as RendererEvent);\n\n if (this._crtDisplay) {\n this._crtDisplay.start();\n } else {\n this._renderer.startDisplay();\n }\n this._state = 'active';\n this._resetIdleTimer();\n\n this._dispatchEvent({ type: 'ready' });\n this._dispatchEvent({ type: 'canvas-replaced', canvas: this.getCanvas() });\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: event system\n // -------------------------------------------------------------------------\n\n private _dispatchEvent(event: RendererEvent): void {\n const listeners = this._eventListeners.get(event.type);\n if (listeners) {\n listeners.forEach(listener => listener(event));\n }\n }\n\n private async _dispatchAwaited(eventType: string): Promise<void> {\n const listeners = this._eventListeners.get(eventType);\n if (!listeners || listeners.size === 0) return;\n\n const acks = [...listeners].map(listener =>\n new Promise<void>(resolve => {\n switch (eventType) {\n case \"canvas-replacing\":\n case \"suspending\":\n listener({ type: eventType, done: resolve } as RendererEvent);\n break;\n case \"canvas-replaced\":\n listener({ type: eventType, canvas: this.getCanvas() } as RendererEvent);\n break;\n default:\n listener({ type: eventType } as RendererEvent);\n }\n })\n );\n\n await Promise.race([\n Promise.all(acks),\n new Promise<void>(resolve => window.setTimeout(resolve, 5_000))\n ]);\n }\n}\n"],"names":[],"mappings":"AA4CO,SAAA,yBAAA;AAAA,SAAA,iBAAA;AAAA,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBvB,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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"}
|