zx-kit 0.35.0 → 0.37.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/dist/aydump.js ADDED
@@ -0,0 +1,650 @@
1
+ /**
2
+ * @module aydump
3
+ *
4
+ * **Sample-accurate AY register-dump player** — the "sample-accurate
5
+ * AudioWorklet backend" that {@link "ay" | ay.ts} promises on its roadmap.
6
+ * Where `ay.ts` *synthesises* notes (`AYNote[]` → band-limited oscillators),
7
+ * this module *reproduces the hardware*: it feeds a cycle-level emulation of
8
+ * the AY-3-8910 / YM2149 chip a stream of register writes (a **PSG dump**) and
9
+ * renders real PCM — so you can play **actual ZX-scene tunes** in a game.
10
+ *
11
+ * The pipeline is data-driven, exactly like a bitmap font:
12
+ *
13
+ * ```
14
+ * .psg file (register dump, bundled as data)
15
+ * │ parsePSG()
16
+ * ▼
17
+ * AYDump (flat typed-array frames: who-writes-what-when)
18
+ * │ AYDumpPlayer (applies each frame's writes every sampleRate/50 samples)
19
+ * ▼
20
+ * AYChipCore (16 registers → L/R PCM, HW logic from the datasheet)
21
+ * │ playAYDump() (realtime AudioWorklet) or renderAYDump() (offline)
22
+ * ▼
23
+ * master GainNode (shared with audio.ts / ay.ts — global M mute works for free)
24
+ * ```
25
+ *
26
+ * **Scope:** v1 is the **PSG** format (a raw register dump — HW-level, unambiguous,
27
+ * dependency-free). Anything from zxart.ee (PT3, STC…) is converted to `.psg`
28
+ * **offline** on a PC (Ay_Emul "save as PSG", `zxtune123 --convert`, Vortex
29
+ * Tracker II). The dump is *data*, not a code dependency — Zero Dependencies stays
30
+ * clean. A native PT3 replay routine over the same {@link AYChipCore} is a future
31
+ * (v2) module.
32
+ *
33
+ * **Authorship:** a PSG dump is a derivative of the original tune. zxart hosting is
34
+ * not a licence — ship a track only with the composer's permission (credit + link).
35
+ *
36
+ * @see {@link "ay" | ay.ts} for note-based music, {@link "audio" | audio.ts} for the beeper.
37
+ */
38
+ import { AY_CLOCK, AY_VOL } from './ay.js';
39
+ import { initAudio, getAudioContext, getMasterGain } from './audio.js';
40
+ /** Ready-made presets for real machines. */
41
+ export const AY_MACHINE = {
42
+ /** ZX Spectrum 128K / +2 / +3 — TV speaker, mono. */
43
+ zx128: { clockHz: 1_773_400, variant: 'ay', stereo: 'mono' },
44
+ /** Didaktik + Melodik add-on — 1.75 MHz, ACB stereo jack. */
45
+ melodik: { clockHz: 1_750_000, variant: 'ay', stereo: 'acb' },
46
+ /** Pentagon clone — 1.75 MHz, ACB. */
47
+ pentagon: { clockHz: 1_750_000, variant: 'ay', stereo: 'acb' },
48
+ /** Atari ST — YM2149 at 2 MHz, mono. */
49
+ atariST: { clockHz: 2_000_000, variant: 'ym', stereo: 'mono' },
50
+ };
51
+ // ─── AYChipCore — the chip emulator (§4.2) ───────────────────────────────────────
52
+ //
53
+ // WORKLET-SAFE INVARIANT: this class must not import or reference anything outside
54
+ // itself — its source is stringified via Function.prototype.toString() and injected
55
+ // into an AudioWorklet. It receives every constant (clock, DAC table, …) through the
56
+ // constructor. It uses only worklet globals: Math, Uint8Array, Array. Do not add a
57
+ // module-scope reference here or the worklet will break after minification.
58
+ /**
59
+ * Cycle-level AY-3-8910 / YM2149 emulator: register writes in, PCM samples out.
60
+ * Three square-wave tone channels, a shared 17-bit LFSR noise generator, and the
61
+ * hardware envelope generator (16 or 32 steps). Pure and self-contained so it runs
62
+ * inside an AudioWorklet **and** in a headless test with no `AudioContext`.
63
+ *
64
+ * Named `AYChipCore` (not `AYChip`) so it does not collide with the real-time
65
+ * {@link "ay".AYChip} handle interface exported from `ay.ts`.
66
+ */
67
+ export class AYChipCore {
68
+ envSteps;
69
+ dac;
70
+ regs = new Uint8Array(16);
71
+ // Tone: per-channel down-counter + square phase.
72
+ toneCnt = [0, 0, 0];
73
+ toneOut = [0, 0, 0];
74
+ // Noise: 17-bit LFSR (seed 1) + counter + current output bit.
75
+ noiseCnt = 0;
76
+ lfsr = 1;
77
+ noiseOut = 1;
78
+ // Envelope generator state.
79
+ envCnt = 0;
80
+ envPos = 0;
81
+ envAttack = false;
82
+ envHolding = false;
83
+ envCont = 0;
84
+ envAlt = 0;
85
+ envHold = 0;
86
+ // Fractional accumulator: chip ticks (clock/8) per output sample.
87
+ cycleAcc = 0;
88
+ cyclesPerSample;
89
+ // Per-channel L/R mix gains (0..1), derived from the stereo preset.
90
+ panL = [0.5, 0.5, 0.5];
91
+ panR = [0.5, 0.5, 0.5];
92
+ // DC-blocker state per output channel (the chip output is unipolar).
93
+ dcxL = 0;
94
+ dcyL = 0;
95
+ dcxR = 0;
96
+ dcyR = 0;
97
+ /**
98
+ * @param sampleRate Output sample rate (Hz).
99
+ * @param clockHz Chip master clock (Hz).
100
+ * @param envSteps Envelope resolution: 16 (AY) or 32 (YM).
101
+ * @param dac 16-entry DAC amplitude table (level → 0..1).
102
+ * @param stereo Stereo preset (mono / abc / acb).
103
+ */
104
+ constructor(sampleRate, clockHz, envSteps, dac, stereo) {
105
+ this.envSteps = envSteps;
106
+ this.dac = dac;
107
+ // Internal chip tick = 8 master clocks → tone f = clock / (16·TP).
108
+ this.cyclesPerSample = clockHz / 8 / sampleRate;
109
+ this.setStereo(stereo);
110
+ this.reset();
111
+ }
112
+ /** Clears counters, registers, LFSR, envelope and DC state. Call at start / seek. */
113
+ reset() {
114
+ this.regs.fill(0);
115
+ this.toneCnt[0] = this.toneCnt[1] = this.toneCnt[2] = 0;
116
+ this.toneOut[0] = this.toneOut[1] = this.toneOut[2] = 0;
117
+ this.noiseCnt = 0;
118
+ this.lfsr = 1;
119
+ this.noiseOut = 1;
120
+ this.envCnt = 0;
121
+ this.envPos = 0;
122
+ this.envAttack = false;
123
+ this.envHolding = false;
124
+ this.envCont = this.envAlt = this.envHold = 0;
125
+ this.cycleAcc = 0;
126
+ this.dcxL = this.dcyL = this.dcxR = this.dcyR = 0;
127
+ }
128
+ /**
129
+ * Applies a demoscene stereo preset. Soft panning (0.75/0.25), so headphones
130
+ * don't get a hard 1/0 split; L+R gain per channel always sums to 1.
131
+ */
132
+ setStereo(mode) {
133
+ const L = [0.5, 0.5, 0.5];
134
+ const R = [0.5, 0.5, 0.5];
135
+ const left = (ch) => { L[ch] = 0.75; R[ch] = 0.25; };
136
+ const right = (ch) => { L[ch] = 0.25; R[ch] = 0.75; };
137
+ if (mode === 'abc') {
138
+ left(0);
139
+ right(2);
140
+ } // A left, B centre, C right
141
+ else if (mode === 'acb') {
142
+ left(0);
143
+ right(1);
144
+ } // A left, C centre, B right
145
+ // 'mono' leaves all three centred.
146
+ this.panL = L;
147
+ this.panR = R;
148
+ }
149
+ /**
150
+ * Writes a chip register (0..15), masking to the hardware register width.
151
+ * Writing R13 (envelope shape) always restarts the envelope.
152
+ */
153
+ setRegister(r, v) {
154
+ r &= 0x0F;
155
+ switch (r) {
156
+ case 1:
157
+ case 3:
158
+ case 5:
159
+ v &= 0x0F;
160
+ break; // tone coarse (12-bit period)
161
+ case 6:
162
+ v &= 0x1F;
163
+ break; // noise period (5-bit)
164
+ case 8:
165
+ case 9:
166
+ case 10:
167
+ v &= 0x1F;
168
+ break; // volume (bit4 = use envelope)
169
+ case 13:
170
+ v &= 0x0F;
171
+ break; // envelope shape
172
+ default:
173
+ v &= 0xFF;
174
+ break;
175
+ }
176
+ this.regs[r] = v;
177
+ if (r === 13) {
178
+ // Decode R13: bit3=CONT bit2=ATT bit1=ALT bit0=HOLD.
179
+ this.envCont = (v >> 3) & 1;
180
+ this.envAlt = (v >> 1) & 1;
181
+ this.envHold = v & 1;
182
+ this.envAttack = ((v >> 2) & 1) === 1; // ATT sets the initial ramp direction
183
+ this.envHolding = false;
184
+ this.envPos = 0;
185
+ this.envCnt = 0;
186
+ }
187
+ }
188
+ /** Steps the 17-bit LFSR once (feedback = bit0 XOR bit3) and latches the output bit. */
189
+ stepNoise() {
190
+ const bit = (this.lfsr ^ (this.lfsr >> 3)) & 1;
191
+ this.lfsr = (this.lfsr >> 1) | (bit << 16);
192
+ this.noiseOut = this.lfsr & 1;
193
+ }
194
+ /** Advances the envelope generator by one step (called when its counter elapses). */
195
+ envStep() {
196
+ if (this.envHolding)
197
+ return;
198
+ this.envPos++;
199
+ if (this.envPos >= this.envSteps) {
200
+ if (this.envCont === 0 || this.envHold === 1) {
201
+ if (this.envCont === 1 && this.envHold === 1 && this.envAlt === 1) {
202
+ this.envAttack = !this.envAttack;
203
+ }
204
+ else if (this.envCont === 0) {
205
+ this.envAttack = false; // one-shot shapes always settle at 0
206
+ }
207
+ this.envHolding = true;
208
+ this.envPos = this.envSteps - 1;
209
+ }
210
+ else {
211
+ if (this.envAlt === 1)
212
+ this.envAttack = !this.envAttack;
213
+ this.envPos = 0;
214
+ }
215
+ }
216
+ }
217
+ /** Current envelope amplitude as a DAC index (0..15). */
218
+ envLevel() {
219
+ const lvl = this.envAttack ? this.envPos : (this.envSteps - 1 - this.envPos);
220
+ return this.envSteps === 32 ? (lvl >> 1) : lvl;
221
+ }
222
+ /**
223
+ * Renders `count` stereo samples into `left`/`right` starting at `offset`.
224
+ * Box-filters the chip's raw ticks within each output sample (a cheap
225
+ * anti-alias), then DC-blocks each output channel.
226
+ */
227
+ renderInto(left, right, offset, count) {
228
+ const r = this.regs;
229
+ const dac = this.dac;
230
+ const HEADROOM = 0.5; // three channels + soft pan must not clip the bus
231
+ for (let i = 0; i < count; i++) {
232
+ this.cycleAcc += this.cyclesPerSample;
233
+ let ticks = Math.floor(this.cycleAcc);
234
+ this.cycleAcc -= ticks;
235
+ if (ticks < 1)
236
+ ticks = 1;
237
+ let sumL = 0;
238
+ let sumR = 0;
239
+ for (let t = 0; t < ticks; t++) {
240
+ // ── Tone counters ──
241
+ for (let ch = 0; ch < 3; ch++) {
242
+ let tp = ((r[ch * 2 + 1] & 0x0F) << 8) | r[ch * 2];
243
+ if (tp === 0)
244
+ tp = 1;
245
+ if (++this.toneCnt[ch] >= tp) {
246
+ this.toneCnt[ch] = 0;
247
+ this.toneOut[ch] ^= 1;
248
+ }
249
+ }
250
+ // ── Noise (17-bit LFSR) ──
251
+ let np = r[6] & 0x1F;
252
+ if (np === 0)
253
+ np = 1;
254
+ if (++this.noiseCnt >= (np << 1)) {
255
+ this.noiseCnt = 0;
256
+ this.stepNoise();
257
+ }
258
+ // ── Envelope ──
259
+ let ep = (r[12] << 8) | r[11];
260
+ if (ep === 0)
261
+ ep = 1;
262
+ const envStepTicks = this.envSteps === 32 ? ep : (ep << 1);
263
+ if (++this.envCnt >= envStepTicks) {
264
+ this.envCnt = 0;
265
+ this.envStep();
266
+ }
267
+ const envDac = this.envLevel();
268
+ // ── Mixer + amplitude ──
269
+ const dis = r[7];
270
+ for (let ch = 0; ch < 3; ch++) {
271
+ // R7 is active-low: a set bit disables (forces high) that source.
272
+ const toneBit = (this.toneOut[ch] | ((dis >> ch) & 1)) & 1;
273
+ const noiseBit = (this.noiseOut | ((dis >> (ch + 3)) & 1)) & 1;
274
+ const on = toneBit & noiseBit;
275
+ const vreg = r[8 + ch];
276
+ const lvl = (vreg & 0x10) ? envDac : (vreg & 0x0F);
277
+ const s = dac[lvl] * on;
278
+ sumL += s * this.panL[ch];
279
+ sumR += s * this.panR[ch];
280
+ }
281
+ }
282
+ const invT = HEADROOM / ticks;
283
+ const rawL = sumL * invT;
284
+ const rawR = sumR * invT;
285
+ // DC-blocker: y = x - x1 + 0.995·y1 (centre the unipolar output).
286
+ const yL = rawL - this.dcxL + 0.995 * this.dcyL;
287
+ this.dcxL = rawL;
288
+ this.dcyL = yL;
289
+ const yR = rawR - this.dcxR + 0.995 * this.dcyR;
290
+ this.dcxR = rawR;
291
+ this.dcyR = yR;
292
+ left[offset + i] = yL;
293
+ right[offset + i] = yR;
294
+ }
295
+ }
296
+ /**
297
+ * @internal Test hook — steps the LFSR `n` times, returning each output bit.
298
+ * Locks the noise sequence against a tap/shift typo (see stepNoise).
299
+ */
300
+ _stepNoiseForTest(n) {
301
+ const out = [];
302
+ for (let i = 0; i < n; i++) {
303
+ this.stepNoise();
304
+ out.push(this.noiseOut);
305
+ }
306
+ return out;
307
+ }
308
+ /**
309
+ * @internal Test hook — advances the envelope generator `n` times (after an R13
310
+ * write), returning the amplitude level (0..15) after each step.
311
+ */
312
+ _stepEnvelopeForTest(n) {
313
+ const out = [];
314
+ for (let i = 0; i < n; i++) {
315
+ this.envStep();
316
+ out.push(this.envLevel());
317
+ }
318
+ return out;
319
+ }
320
+ }
321
+ // ─── parsePSG (§4.4) ─────────────────────────────────────────────────────────────
322
+ /**
323
+ * Parses a PSG register dump (the format Ay_Emul / zxtune produce) into an
324
+ * {@link AYDump}. A PSG file is a `"PSG\x1a"` header then a byte stream:
325
+ *
326
+ * - `0xFF` — start a new frame
327
+ * - `0xFE n` — `n × 4` empty frames (chip holds its state)
328
+ * - `0xFD` — end of song (often absent: end-of-data ends the song)
329
+ * - `0x00..0x0F` — register index; the next byte is its value
330
+ * - `0x10..0xFC` — foreign device (MSX / 2nd chip) → skip this byte and the next
331
+ *
332
+ * @throws if the header is wrong or a register/`0xFE` pair is truncated.
333
+ */
334
+ export function parsePSG(bytes) {
335
+ if (bytes.length < 16
336
+ || bytes[0] !== 0x50 || bytes[1] !== 0x53 || bytes[2] !== 0x47 || bytes[3] !== 0x1A) {
337
+ throw new Error('parsePSG: bad header (expected "PSG\\x1a")');
338
+ }
339
+ const regs = [];
340
+ const vals = [];
341
+ const offsets = []; // start index (into regs/vals) of each frame
342
+ const openFrame = () => { offsets.push(regs.length); };
343
+ let i = 16;
344
+ let ended = false;
345
+ while (i < bytes.length && !ended) {
346
+ const b = bytes[i++];
347
+ if (b === 0xFF) {
348
+ openFrame(); // first 0xFF opens frame 0 — no spurious empty frame
349
+ }
350
+ else if (b === 0xFE) {
351
+ if (i >= bytes.length)
352
+ throw new Error('parsePSG: truncated 0xFE run (missing count)');
353
+ const n = bytes[i++];
354
+ for (let k = 0; k < n * 4; k++)
355
+ openFrame();
356
+ }
357
+ else if (b === 0xFD) {
358
+ ended = true;
359
+ }
360
+ else if (b <= 0x0F) {
361
+ if (i >= bytes.length)
362
+ throw new Error('parsePSG: truncated register pair (missing value)');
363
+ if (offsets.length === 0)
364
+ openFrame(); // tolerate a register write before the first 0xFF
365
+ regs.push(b);
366
+ vals.push(bytes[i++]);
367
+ }
368
+ else {
369
+ // Foreign device (0x10..0xFC): skip this command byte and its value byte.
370
+ i++;
371
+ }
372
+ }
373
+ const frameCount = offsets.length;
374
+ const frameOffsets = new Uint32Array(frameCount + 1);
375
+ frameOffsets.set(offsets);
376
+ frameOffsets[frameCount] = regs.length;
377
+ return {
378
+ frameRateHz: 50,
379
+ frameCount,
380
+ writeRegs: Uint8Array.from(regs),
381
+ writeVals: Uint8Array.from(vals),
382
+ frameOffsets,
383
+ };
384
+ }
385
+ // ─── AYDumpPlayer — pure playback, no Web Audio (§4.5) ────────────────────────────
386
+ //
387
+ // WORKLET-SAFE INVARIANT: like AYChipCore, no imports / no module references.
388
+ /**
389
+ * Drives an {@link AYChipCore} from an {@link AYDump}: applies each frame's
390
+ * register writes on the right sample and fills PCM buffers. Uses a *fractional*
391
+ * samples-per-frame accumulator so a 3-minute tune doesn't drift at exotic rates.
392
+ * Pure — testable with a spy chip, runnable inside the worklet.
393
+ */
394
+ export class AYDumpPlayer {
395
+ chip;
396
+ writeRegs;
397
+ writeVals;
398
+ frameOffsets;
399
+ loop;
400
+ loopFrame;
401
+ frameCount;
402
+ samplesPerFrame;
403
+ frame = 0;
404
+ frameAcc = 0;
405
+ ended = false;
406
+ /**
407
+ * @param chip The chip to drive.
408
+ * @param writeRegs Concatenated register indices (see {@link AYDump}).
409
+ * @param writeVals Concatenated values.
410
+ * @param frameOffsets Frame boundaries (length `frameCount + 1`).
411
+ * @param frameRateHz Frames per second (PSG = 50).
412
+ * @param sampleRate Output sample rate (Hz).
413
+ * @param loop Restart at `loopFrame` after the last frame.
414
+ * @param loopFrame Frame to jump to when looping.
415
+ */
416
+ constructor(chip, writeRegs, writeVals, frameOffsets, frameRateHz, sampleRate, loop, loopFrame) {
417
+ this.chip = chip;
418
+ this.writeRegs = writeRegs;
419
+ this.writeVals = writeVals;
420
+ this.frameOffsets = frameOffsets;
421
+ this.loop = loop;
422
+ this.loopFrame = loopFrame;
423
+ this.frameCount = frameOffsets.length - 1;
424
+ this.samplesPerFrame = sampleRate / frameRateHz;
425
+ }
426
+ applyFrame(f) {
427
+ const start = this.frameOffsets[f];
428
+ const end = this.frameOffsets[f + 1];
429
+ for (let k = start; k < end; k++) {
430
+ this.chip.setRegister(this.writeRegs[k], this.writeVals[k]);
431
+ }
432
+ }
433
+ /** Fills `left`/`right` completely. Returns `true` once the (non-looping) song has ended. */
434
+ render(left, right) {
435
+ const N = left.length;
436
+ let i = 0;
437
+ while (i < N) {
438
+ if (this.frameAcc <= 0) {
439
+ if (this.frame >= this.frameCount) {
440
+ if (this.loop)
441
+ this.frame = this.loopFrame;
442
+ else
443
+ this.ended = true;
444
+ }
445
+ if (this.ended) {
446
+ for (; i < N; i++) {
447
+ left[i] = 0;
448
+ right[i] = 0;
449
+ }
450
+ break;
451
+ }
452
+ this.applyFrame(this.frame);
453
+ this.frame++;
454
+ this.frameAcc += this.samplesPerFrame;
455
+ }
456
+ let n = Math.min(N - i, Math.ceil(this.frameAcc));
457
+ if (n < 1)
458
+ n = 1;
459
+ this.chip.renderInto(left, right, i, n);
460
+ this.frameAcc -= n;
461
+ i += n;
462
+ }
463
+ return this.ended;
464
+ }
465
+ /** Fast-forwards to frame `f` by replaying its register writes without rendering. */
466
+ seekToFrame(f) {
467
+ this.chip.reset();
468
+ const target = Math.max(0, Math.min(f, this.frameCount));
469
+ for (let k = 0; k < target; k++)
470
+ this.applyFrame(k);
471
+ this.frame = target;
472
+ this.frameAcc = 0;
473
+ this.ended = false;
474
+ }
475
+ }
476
+ function resolveConfig(opts) {
477
+ const variant = opts.variant ?? 'ay';
478
+ return {
479
+ clockHz: opts.clockHz ?? AY_CLOCK,
480
+ variant,
481
+ envSteps: variant === 'ym' ? 32 : 16,
482
+ dac: Array.from(opts.dacTable ?? AY_VOL),
483
+ stereo: opts.stereo ?? 'acb',
484
+ };
485
+ }
486
+ function clamp01(v) {
487
+ return Math.max(0, Math.min(1, v));
488
+ }
489
+ /** Name the worklet processor is registered under. */
490
+ const AYDUMP_PROCESSOR = 'zxkit-aydump';
491
+ /**
492
+ * Assembles the AudioWorklet source: the two worklet-safe classes stringified,
493
+ * plus a processor that loads a dump and renders it. The class names are read via
494
+ * `.name` (not hardcoded) so the glue stays consistent even if a bundler mangles
495
+ * them — {@link AYChipCore}.name and its `toString()` agree under minification.
496
+ *
497
+ * Internal; exported only so a test can assert the source is self-contained.
498
+ */
499
+ export function _buildAYDumpWorkletSource() {
500
+ const chipName = AYChipCore.name;
501
+ const playerName = AYDumpPlayer.name;
502
+ return `${AYChipCore.toString()}
503
+ ${AYDumpPlayer.toString()}
504
+ registerProcessor(${JSON.stringify(AYDUMP_PROCESSOR)}, class extends AudioWorkletProcessor {
505
+ constructor() {
506
+ super()
507
+ this.player = null
508
+ this.chip = null
509
+ this.endedPosted = false
510
+ this.port.onmessage = (e) => {
511
+ const d = e.data
512
+ if (d.type === 'load') {
513
+ const chip = new ${chipName}(sampleRate, d.clockHz, d.envSteps, d.dac, d.stereo)
514
+ this.chip = chip
515
+ this.player = new ${playerName}(chip,
516
+ new Uint8Array(d.writeRegs), new Uint8Array(d.writeVals),
517
+ new Uint32Array(d.frameOffsets), d.frameRateHz, sampleRate, d.loop, d.loopFrame)
518
+ this.endedPosted = false
519
+ } else if (d.type === 'stereo' && this.chip) {
520
+ this.chip.setStereo(d.mode)
521
+ }
522
+ }
523
+ }
524
+ process(_inputs, outputs) {
525
+ const out = outputs[0]
526
+ if (!this.player) return true
527
+ const ended = this.player.render(out[0], out[1])
528
+ if (ended && !this.endedPosted) { this.endedPosted = true; this.port.postMessage({ type: 'ended' }) }
529
+ return true
530
+ }
531
+ })`;
532
+ }
533
+ // One-time worklet registration per AudioContext.
534
+ const _workletReady = new WeakSet();
535
+ async function ensureAYDumpWorklet(ctx) {
536
+ if (_workletReady.has(ctx))
537
+ return;
538
+ const src = _buildAYDumpWorkletSource();
539
+ const url = URL.createObjectURL(new Blob([src], { type: 'text/javascript' }));
540
+ try {
541
+ await ctx.audioWorklet.addModule(url);
542
+ }
543
+ finally {
544
+ URL.revokeObjectURL(url);
545
+ }
546
+ _workletReady.add(ctx);
547
+ }
548
+ /**
549
+ * Plays a parsed {@link AYDump} in real time through an AudioWorklet, routed to the
550
+ * shared master gain (so global `M` mute / `setMasterVolume` apply for free).
551
+ * Call after {@link initAudio} inside a user gesture — same contract as `playAY`.
552
+ *
553
+ * @example
554
+ * const dump = await loadPSG('./music/tune.psg')
555
+ * const track = await playAYDump(dump, { loop: true, ...AY_MACHINE.melodik })
556
+ * // later: track.setVolume(0.6); track.stop()
557
+ */
558
+ export async function playAYDump(dump, opts = {}) {
559
+ initAudio();
560
+ const ctx = getAudioContext();
561
+ const master = getMasterGain();
562
+ if (!ctx || !master) {
563
+ throw new Error('playAYDump: call initAudio() inside a user gesture first');
564
+ }
565
+ await ensureAYDumpWorklet(ctx);
566
+ const cfg = resolveConfig(opts);
567
+ const node = new AudioWorkletNode(ctx, AYDUMP_PROCESSOR, { outputChannelCount: [2] });
568
+ const gain = ctx.createGain();
569
+ let volume = clamp01(opts.volume ?? 1);
570
+ gain.gain.value = volume;
571
+ node.connect(gain);
572
+ gain.connect(master);
573
+ // Copy the arrays before transferring their buffers, so the caller's dump stays
574
+ // usable (e.g. to play it again) — the copy is cheap next to zero-copy on the audio thread.
575
+ const wr = dump.writeRegs.slice();
576
+ const wv = dump.writeVals.slice();
577
+ const fo = dump.frameOffsets.slice();
578
+ node.port.postMessage({
579
+ type: 'load',
580
+ clockHz: cfg.clockHz, envSteps: cfg.envSteps, dac: cfg.dac, stereo: cfg.stereo,
581
+ writeRegs: wr, writeVals: wv, frameOffsets: fo,
582
+ frameRateHz: dump.frameRateHz, loop: !!opts.loop, loopFrame: opts.loopFrame ?? 0,
583
+ }, [wr.buffer, wv.buffer, fo.buffer]);
584
+ let playing = true;
585
+ const handle = {
586
+ get playing() { return playing; },
587
+ stop() {
588
+ playing = false;
589
+ try {
590
+ node.disconnect();
591
+ }
592
+ catch { /* already gone */ }
593
+ try {
594
+ gain.disconnect();
595
+ }
596
+ catch { /* already gone */ }
597
+ },
598
+ pause() { gain.gain.value = 0; },
599
+ resume() { gain.gain.value = volume; },
600
+ setVolume(v) { volume = clamp01(v); gain.gain.value = volume; },
601
+ setStereo(mode) { node.port.postMessage({ type: 'stereo', mode }); },
602
+ };
603
+ node.port.onmessage = (e) => {
604
+ if (e.data?.type === 'ended') {
605
+ playing = false;
606
+ handle.onEnded?.();
607
+ }
608
+ };
609
+ return handle;
610
+ }
611
+ /**
612
+ * Renders a dump to stereo PCM **without an AudioContext** — deterministic, for
613
+ * unit tests, `AudioWorklet`-less fallbacks, and offline tooling (e.g. PSG → WAV).
614
+ * Beware RAM: a full 3-minute stereo render at 44.1 kHz is ≈ 64 MB — pass
615
+ * `maxSeconds` to bound it.
616
+ */
617
+ export function renderAYDump(dump, opts = {}) {
618
+ const sampleRate = opts.sampleRate ?? 44100;
619
+ const cfg = resolveConfig(opts);
620
+ const chip = new AYChipCore(sampleRate, cfg.clockHz, cfg.envSteps, cfg.dac, cfg.stereo);
621
+ const player = new AYDumpPlayer(chip, dump.writeRegs, dump.writeVals, dump.frameOffsets, dump.frameRateHz, sampleRate, false, 0);
622
+ const songSeconds = dump.frameCount / dump.frameRateHz + 0.1;
623
+ const seconds = opts.maxSeconds !== undefined ? Math.min(opts.maxSeconds, songSeconds) : songSeconds;
624
+ const total = Math.max(0, Math.ceil(seconds * sampleRate));
625
+ const left = new Float32Array(total);
626
+ const right = new Float32Array(total);
627
+ const CHUNK = 4096;
628
+ for (let i = 0; i < total;) {
629
+ const n = Math.min(CHUNK, total - i);
630
+ const ended = player.render(left.subarray(i, i + n), right.subarray(i, i + n));
631
+ i += n;
632
+ if (ended)
633
+ break;
634
+ }
635
+ return { left, right };
636
+ }
637
+ /**
638
+ * Fetches a `.psg` file and parses it into an {@link AYDump}. Network / parse
639
+ * errors propagate so the game decides how to handle them.
640
+ *
641
+ * @example
642
+ * const dump = await loadPSG('./music/tune.psg')
643
+ */
644
+ export async function loadPSG(url) {
645
+ const res = await fetch(url);
646
+ if (!res.ok)
647
+ throw new Error(`loadPSG: HTTP ${res.status} for ${url}`);
648
+ return parsePSG(new Uint8Array(await res.arrayBuffer()));
649
+ }
650
+ //# sourceMappingURL=aydump.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aydump.js","sourceRoot":"","sources":["../src/aydump.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAE1C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAmBtE,4CAA4C;AAC5C,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,qDAAqD;IACrD,KAAK,EAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE;IAC/D,6DAA6D;IAC7D,OAAO,EAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAC9D,sCAAsC;IACtC,QAAQ,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IAC9D,wCAAwC;IACxC,OAAO,EAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE;CAChB,CAAA;AAEjD,oFAAoF;AACpF,EAAE;AACF,mFAAmF;AACnF,oFAAoF;AACpF,qFAAqF;AACrF,mFAAmF;AACnF,4EAA4E;AAE5E;;;;;;;;GAQG;AACH,MAAM,OAAO,UAAU;IA6CF;IACA;IA7CF,IAAI,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAA;IAE1C,iDAAiD;IAChC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACnB,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAEpC,8DAA8D;IACtD,QAAQ,GAAG,CAAC,CAAA;IACZ,IAAI,GAAG,CAAC,CAAA;IACR,QAAQ,GAAG,CAAC,CAAA;IAEpB,4BAA4B;IACpB,MAAM,GAAG,CAAC,CAAA;IACV,MAAM,GAAG,CAAC,CAAA;IACV,SAAS,GAAG,KAAK,CAAA;IACjB,UAAU,GAAG,KAAK,CAAA;IAClB,OAAO,GAAG,CAAC,CAAA;IACX,MAAM,GAAG,CAAC,CAAA;IACV,OAAO,GAAG,CAAC,CAAA;IAEnB,kEAAkE;IAC1D,QAAQ,GAAG,CAAC,CAAA;IACH,eAAe,CAAQ;IAExC,oEAAoE;IAC5D,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IACtB,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAE9B,qEAAqE;IAC7D,IAAI,GAAG,CAAC,CAAA;IACR,IAAI,GAAG,CAAC,CAAA;IACR,IAAI,GAAG,CAAC,CAAA;IACR,IAAI,GAAG,CAAC,CAAA;IAEhB;;;;;;OAMG;IACH,YACE,UAAkB,EAClB,OAAe,EACE,QAAgB,EAChB,GAAsB,EACvC,MAAoB;QAFH,aAAQ,GAAR,QAAQ,CAAQ;QAChB,QAAG,GAAH,GAAG,CAAmB;QAGvC,mEAAmE;QACnE,IAAI,CAAC,eAAe,GAAG,OAAO,GAAG,CAAC,GAAG,UAAU,CAAA;QAC/C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QACtB,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,qFAAqF;IACrF,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACvD,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACvD,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACjB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAA;QACb,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACjB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAA;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;QAC7C,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,CAAA;IACnD,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,IAAkB;QAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;QACzB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;QACzB,MAAM,IAAI,GAAI,CAAC,EAAU,EAAQ,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAA,CAAC,CAAC,CAAA;QAClE,MAAM,KAAK,GAAG,CAAC,EAAU,EAAQ,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAA,CAAC,CAAC,CAAA;QAClE,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAAC,CAAC,CAAU,4BAA4B;aAC1E,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAAC,CAAC,CAAK,4BAA4B;QAC/E,mCAAmC;QACnC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAA;QACb,IAAI,CAAC,IAAI,GAAG,CAAC,CAAA;IACf,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,CAAS,EAAE,CAAS;QAC9B,CAAC,IAAI,IAAI,CAAA;QACT,QAAQ,CAAC,EAAE,CAAC;YACV,KAAK,CAAC,CAAC;YAAC,KAAK,CAAC,CAAC;YAAC,KAAK,CAAC;gBAAE,CAAC,IAAI,IAAI,CAAC;gBAAC,MAAK,CAAE,8BAA8B;YACxE,KAAK,CAAC;gBAAkB,CAAC,IAAI,IAAI,CAAC;gBAAC,MAAK,CAAE,uBAAuB;YACjE,KAAK,CAAC,CAAC;YAAC,KAAK,CAAC,CAAC;YAAC,KAAK,EAAE;gBAAE,CAAC,IAAI,IAAI,CAAC;gBAAC,MAAK,CAAC,+BAA+B;YACzE,KAAK,EAAE;gBAAiB,CAAC,IAAI,IAAI,CAAC;gBAAC,MAAK,CAAE,iBAAiB;YAC3D;gBAAwB,CAAC,IAAI,IAAI,CAAC;gBAAC,MAAK;QAC1C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAChB,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACb,qDAAqD;YACrD,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YAC3B,IAAI,CAAC,MAAM,GAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YAC3B,IAAI,CAAC,OAAO,GAAI,CAAC,GAAS,CAAC,CAAA;YAC3B,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA,CAAG,sCAAsC;YAC9E,IAAI,CAAC,UAAU,GAAG,KAAK,CAAA;YACvB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;YACf,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,wFAAwF;IAChF,SAAS;QACf,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QAC9C,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAA;QAC1C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,CAAA;IAC/B,CAAC;IAED,qFAAqF;IAC7E,OAAO;QACb,IAAI,IAAI,CAAC,UAAU;YAAE,OAAM;QAC3B,IAAI,CAAC,MAAM,EAAE,CAAA;QACb,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;gBAC7C,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAClE,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,SAAS,CAAA;gBAClC,CAAC;qBAAM,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;oBAC9B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA,CAAU,qCAAqC;gBACvE,CAAC;gBACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;gBACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;YACjC,CAAC;iBAAM,CAAC;gBACN,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,SAAS,CAAA;gBACvD,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IAED,yDAAyD;IACjD,QAAQ;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;QAC5E,OAAO,IAAI,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;IAChD,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAC,IAAkB,EAAE,KAAmB,EAAE,MAAc,EAAE,KAAa;QAC/E,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAA;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;QACpB,MAAM,QAAQ,GAAG,GAAG,CAAA,CAAG,kDAAkD;QAEzE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,eAAe,CAAA;YACrC,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YACrC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAA;YACtB,IAAI,KAAK,GAAG,CAAC;gBAAE,KAAK,GAAG,CAAC,CAAA;YAExB,IAAI,IAAI,GAAG,CAAC,CAAA;YACZ,IAAI,IAAI,GAAG,CAAC,CAAA;YAEZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/B,sBAAsB;gBACtB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;oBAC9B,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;oBAClD,IAAI,EAAE,KAAK,CAAC;wBAAE,EAAE,GAAG,CAAC,CAAA;oBACpB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;wBAC7B,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;wBACpB,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;oBACvB,CAAC;gBACH,CAAC;gBAED,4BAA4B;gBAC5B,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;gBACpB,IAAI,EAAE,KAAK,CAAC;oBAAE,EAAE,GAAG,CAAC,CAAA;gBACpB,IAAI,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;oBACjC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;oBACjB,IAAI,CAAC,SAAS,EAAE,CAAA;gBAClB,CAAC;gBAED,iBAAiB;gBACjB,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAA;gBAC7B,IAAI,EAAE,KAAK,CAAC;oBAAE,EAAE,GAAG,CAAC,CAAA;gBACpB,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;gBAC1D,IAAI,EAAE,IAAI,CAAC,MAAM,IAAI,YAAY,EAAE,CAAC;oBAClC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;oBACf,IAAI,CAAC,OAAO,EAAE,CAAA;gBAChB,CAAC;gBACD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;gBAE9B,0BAA0B;gBAC1B,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;gBAChB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;oBAC9B,kEAAkE;oBAClE,MAAM,OAAO,GAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;oBAC3D,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;oBAC/D,MAAM,EAAE,GAAG,OAAO,GAAG,QAAQ,CAAA;oBAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;oBACtB,MAAM,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;oBAClD,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAA;oBACvB,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;oBACzB,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBAC3B,CAAC;YACH,CAAC;YAED,MAAM,IAAI,GAAG,QAAQ,GAAG,KAAK,CAAA;YAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;YACxB,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;YAExB,kEAAkE;YAClE,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,IAAI,CAAA;YAC/C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YAAC,IAAI,CAAC,IAAI,GAAG,EAAE,CAAA;YAChC,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,IAAI,CAAA;YAC/C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YAAC,IAAI,CAAC,IAAI,GAAG,EAAE,CAAA;YAEhC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAI,EAAE,CAAA;YACtB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,CAAA;QACxB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,iBAAiB,CAAC,CAAS;QACzB,MAAM,GAAG,GAAa,EAAE,CAAA;QACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAAC,CAAC;QACzE,OAAO,GAAG,CAAA;IACZ,CAAC;IAED;;;OAGG;IACH,oBAAoB,CAAC,CAAS;QAC5B,MAAM,GAAG,GAAa,EAAE,CAAA;QACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;QAAC,CAAC;QACzE,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AAsBD,oFAAoF;AAEpF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAiB;IACxC,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;WAChB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACtF,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,MAAM,OAAO,GAAa,EAAE,CAAA,CAAG,6CAA6C;IAE5E,MAAM,SAAS,GAAG,GAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA,CAAC,CAAC,CAAA;IAE3D,IAAI,CAAC,GAAG,EAAE,CAAA;IACV,IAAI,KAAK,GAAG,KAAK,CAAA;IACjB,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;QACpB,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACf,SAAS,EAAE,CAAA,CAA8B,qDAAqD;QAChG,CAAC;aAAM,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;YACtF,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;YACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAAE,SAAS,EAAE,CAAA;QAC7C,CAAC;aAAM,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACtB,KAAK,GAAG,IAAI,CAAA;QACd,CAAC;aAAM,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;YAC3F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS,EAAE,CAAA,CAAI,kDAAkD;YAC3F,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACZ,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACvB,CAAC;aAAM,CAAC;YACN,0EAA0E;YAC1E,CAAC,EAAE,CAAA;QACL,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAA;IACjC,MAAM,YAAY,GAAG,IAAI,WAAW,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;IACpD,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACzB,YAAY,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,MAAM,CAAA;IAEtC,OAAO;QACL,WAAW,EAAE,EAAE;QACf,UAAU;QACV,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAChC,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAChC,YAAY;KACb,CAAA;AACH,CAAC;AAED,qFAAqF;AACrF,EAAE;AACF,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IAkBJ;IACA;IACA;IACA;IAGA;IACA;IAxBF,UAAU,CAAQ;IAClB,eAAe,CAAQ;IAChC,KAAK,GAAG,CAAC,CAAA;IACT,QAAQ,GAAG,CAAC,CAAA;IACZ,KAAK,GAAG,KAAK,CAAA;IAErB;;;;;;;;;OASG;IACH,YACmB,IAAgB,EAChB,SAAqB,EACrB,SAAqB,EACrB,YAAyB,EAC1C,WAAmB,EACnB,UAAkB,EACD,IAAa,EACb,SAAiB;QAPjB,SAAI,GAAJ,IAAI,CAAY;QAChB,cAAS,GAAT,SAAS,CAAY;QACrB,cAAS,GAAT,SAAS,CAAY;QACrB,iBAAY,GAAZ,YAAY,CAAa;QAGzB,SAAI,GAAJ,IAAI,CAAS;QACb,cAAS,GAAT,SAAS,CAAQ;QAElC,IAAI,CAAC,UAAU,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAA;QACzC,IAAI,CAAC,eAAe,GAAG,UAAU,GAAG,WAAW,CAAA;IACjD,CAAC;IAEO,UAAU,CAAC,CAAS;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACpC,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;IAED,6FAA6F;IAC7F,MAAM,CAAC,IAAkB,EAAE,KAAmB;QAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAA;QACrB,IAAI,CAAC,GAAG,CAAC,CAAA;QACT,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC;gBACvB,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBAClC,IAAI,IAAI,CAAC,IAAI;wBAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS,CAAA;;wBACrC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;gBACxB,CAAC;gBACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;wBAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;wBAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;oBAAC,CAAC;oBAChD,MAAK;gBACP,CAAC;gBACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC3B,IAAI,CAAC,KAAK,EAAE,CAAA;gBACZ,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,eAAe,CAAA;YACvC,CAAC;YACD,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;YACjD,IAAI,CAAC,GAAG,CAAC;gBAAE,CAAC,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACvC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAA;YAClB,CAAC,IAAI,CAAC,CAAA;QACR,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,qFAAqF;IACrF,WAAW,CAAC,CAAS;QACnB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;QACjB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAA;QACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE;YAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QACnD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QACnB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;CACF;AAYD,SAAS,aAAa,CAAC,IAAkB;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAA;IACpC,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,QAAQ;QACjC,OAAO;QACP,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;QACpC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC;QACxC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;KAC7B,CAAA;AACH,CAAC;AAED,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AACpC,CAAC;AAgCD,sDAAsD;AACtD,MAAM,gBAAgB,GAAG,cAAc,CAAA;AAEvC;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAA;IAChC,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAA;IACpC,OAAO,GAAG,UAAU,CAAC,QAAQ,EAAE;EAC/B,YAAY,CAAC,QAAQ,EAAE;oBACL,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;;;;;;;;;2BASzB,QAAQ;;4BAEP,UAAU;;;;;;;;;;;;;;;;GAgBnC,CAAA;AACH,CAAC;AAED,kDAAkD;AAClD,MAAM,aAAa,GAAG,IAAI,OAAO,EAAoB,CAAA;AAErD,KAAK,UAAU,mBAAmB,CAAC,GAAqB;IACtD,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAM;IAClC,MAAM,GAAG,GAAG,yBAAyB,EAAE,CAAA;IACvC,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAA;IAC7E,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IACvC,CAAC;YAAS,CAAC;QACT,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IACD,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,OAA0B,EAAE;IACzE,SAAS,EAAE,CAAA;IACX,MAAM,GAAG,GAAG,eAAe,EAAE,CAAA;IAC7B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;IAC9B,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAC7E,CAAC;IACD,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAA;IAE9B,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IAC/B,MAAM,IAAI,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,EAAE,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACrF,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,EAAE,CAAA;IAC7B,IAAI,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;IACtC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;IACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAEpB,gFAAgF;IAChF,4FAA4F;IAC5F,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAA;IACjC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAA;IACjC,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAA;IACpC,IAAI,CAAC,IAAI,CAAC,WAAW,CACnB;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM;QAC9E,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE;QAC9C,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC;KACjF,EACD,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAClC,CAAA;IAED,IAAI,OAAO,GAAG,IAAI,CAAA;IAClB,MAAM,MAAM,GAAiB;QAC3B,IAAI,OAAO,KAAK,OAAO,OAAO,CAAA,CAAC,CAAC;QAChC,IAAI;YACF,OAAO,GAAG,KAAK,CAAA;YACf,IAAI,CAAC;gBAAC,IAAI,CAAC,UAAU,EAAE,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;YACtD,IAAI,CAAC;gBAAC,IAAI,CAAC,UAAU,EAAE,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;QACxD,CAAC;QACD,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA,CAAC,CAAC;QAC/B,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA,CAAC,CAAC;QACrC,SAAS,CAAC,CAAS,IAAI,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA,CAAC,CAAC;QACtE,SAAS,CAAC,IAAkB,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA,CAAC,CAAC;KAClF,CAAA;IACD,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAe,EAAE,EAAE;QACxC,IAAK,CAAC,CAAC,IAA0B,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;YACpD,OAAO,GAAG,KAAK,CAAA;YACf,MAAM,CAAC,OAAO,EAAE,EAAE,CAAA;QACpB,CAAC;IACH,CAAC,CAAA;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAYD;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,OAA4B,EAAE;IAE9B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,KAAK,CAAA;IAC3C,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IAC/B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACvF,MAAM,MAAM,GAAG,IAAI,YAAY,CAC7B,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,EACvD,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CACvC,CAAA;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,GAAG,GAAG,CAAA;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAA;IACpG,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,CAAC,CAAA;IAC1D,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAA;IACpC,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAA;IAErC,MAAM,KAAK,GAAG,IAAI,CAAA;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC;QAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAC9E,CAAC,IAAI,CAAC,CAAA;QACN,IAAI,KAAK;YAAE,MAAK;IAClB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;AACxB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW;IACvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAA;IACtE,OAAO,QAAQ,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;AAC1D,CAAC"}