@wasm-gaming/rsdkv3-wasm 0.1.4 → 0.2.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.
@@ -1,226 +1,397 @@
1
- // @wasm-gaming/rsdkv3-wasm — SDK entry point.
2
- //
3
- // Conforms to the wasm-gaming engine contract (github.com/wasm-gaming/engine-specs):
4
- // exports `manifest` (declarative) and `load(config)` (imperative).
5
- //
6
- // The engine binary is game-agnostic for RSDKv3. Sonic CD is selected by
7
- // `Data.rsdk`, mounted at runtime into the Emscripten filesystem.
8
- import { manifest } from './rsdkv3.manifest.js';
9
- import { DEFAULT_RSDKV3_OPTIONS } from './rsdkv3.options.js';
10
- export { manifest };
11
- const WORK_DIR = '/data';
1
+ /**
2
+ * The engine package's entry point: an `EngineSDK` for RSDKv3 (Sonic CD).
3
+ *
4
+ * ```js
5
+ * import Rsdkv3SDK from '@wasm-gaming/rsdkv3-wasm';
6
+ *
7
+ * const play = await new Rsdkv3SDK({ config: { soundtrack: 1 } })
8
+ * .assets({ data: () => readDataRsdk() }) // bytes, or a thunk
9
+ * .storage({ namespace: 'sonic-cd' }) // → OPFS rsdkv3/sonic-cd/
10
+ * .mount(document.querySelector('#stage'))
11
+ * .start();
12
+ *
13
+ * play.pause('menu'); play.resume('menu');
14
+ * play.devMenu.getStageList(); // the host draws its own stage select
15
+ * await play.destroy(); // save flushed, loop stopped, audio closed
16
+ * ```
17
+ *
18
+ * One game-agnostic `rsdkv3.wasm`: `Data.rsdk` is written into the filesystem at
19
+ * runtime, never baked in. The working dir `/data/rsdkv3/<namespace>` is in memory;
20
+ * the SDK seeds `SData.bin` from OPFS `rsdkv3/<namespace>/` before boot and mirrors it
21
+ * back when it changes (every 10 s, on pause, on page hide and on destroy).
22
+ */
23
+ import { EnginePlayBase, EngineSDKBase, EventEmitter, } from './engine-specs.js';
24
+ import { RSDKV3_SPEC, RSDKV3_VIDEO, } from './rsdkv3.options.js';
25
+ export { RSDKV3_SPEC, RSDKV3_VIDEO } from './rsdkv3.options.js';
26
+ const ENGINE_ID = 'rsdkv3';
12
27
  const DEFAULT_STORAGE_NAMESPACE = 'default';
13
- /** Serialize engine options into RSDKv3's settings.ini format. */
14
- function buildSettingsIni(options = {}) {
15
- const o = { ...DEFAULT_RSDKV3_OPTIONS, ...options };
28
+ const WORK_ROOT = '/data';
29
+ const SAVE_FILE = 'SData.bin';
30
+ const SAVE_INTERVAL_MS = 10_000;
31
+ /**
32
+ * Where an engine keeps one namespace: `<engineId>/<namespace>`, relative to the OPFS
33
+ * root. Identical in every wasm-gaming engine, written to move verbatim into
34
+ * engine-specs: segments cleaned, `.` and `..` dropped, anything outside
35
+ * `[A-Za-z0-9._-]` → `_`, nothing usable → `default`; a leading `<engineId>/` is
36
+ * stripped once.
37
+ */
38
+ export function storagePath(engineId, namespace) {
39
+ const segments = typeof namespace === 'string'
40
+ ? namespace
41
+ .split('/')
42
+ .map((segment) => segment.trim())
43
+ .filter((segment) => segment && segment !== '.' && segment !== '..')
44
+ .map((segment) => segment.replace(/[^A-Za-z0-9._-]/g, '_'))
45
+ : [];
46
+ const prefixed = segments.length > 1 && segments[0] === engineId;
47
+ if (prefixed)
48
+ segments.shift();
49
+ const cleaned = segments.join('/') || DEFAULT_STORAGE_NAMESPACE;
50
+ return { namespace: cleaned, path: `${engineId}/${cleaned}`, prefixed };
51
+ }
52
+ /** Serialise the engine config into RSDKv3's settings.ini. */
53
+ export function buildSettingsIni(config) {
16
54
  return [
17
55
  '[Dev]',
18
- `EngineDebugMode=${o.engineDebugMode ? 'true' : 'false'}`,
19
- `DevMenu=${o.devMenu ? 'true' : 'false'}`,
56
+ `EngineDebugMode=${config.engineDebugMode ? 'true' : 'false'}`,
57
+ `DevMenu=${config.devMenu ? 'true' : 'false'}`,
20
58
  '',
21
59
  '[Game]',
22
- `Language=${o.language | 0}`,
23
- `DisableTouchControls=${o.disableTouchControls ? 'true' : 'false'}`,
60
+ `Language=${(config.language ?? 0) | 0}`,
61
+ `DisableTouchControls=${config.disableTouchControls === false ? 'false' : 'true'}`,
24
62
  '',
25
63
  '[Video]',
26
64
  'Windowed=true',
27
65
  'Borderless=false',
28
66
  'ExclusiveFS=false',
29
- `VSync=${o.vsync ? 'true' : 'false'}`,
67
+ `VSync=${config.vsync ? 'true' : 'false'}`,
30
68
  'WindowScale=2',
31
- 'ScreenWidth=426',
32
- 'ScreenHeight=240',
69
+ `ScreenWidth=${RSDKV3_VIDEO.width}`,
70
+ `ScreenHeight=${RSDKV3_VIDEO.height}`,
33
71
  'RefreshRate=60',
34
72
  '',
35
73
  '[Audio]',
36
74
  'BGMVolume=1.000000',
37
75
  'SFXVolume=1.000000',
38
- `Soundtrack=${o.soundtrack | 0}`,
76
+ `Soundtrack=${(config.soundtrack ?? 0) | 0}`,
39
77
  '',
40
78
  ].join('\n');
41
79
  }
42
- function toUint8(x) {
43
- if (x == null)
80
+ async function opfsDir(path, create) {
81
+ if (typeof navigator === 'undefined' || !navigator.storage?.getDirectory)
44
82
  return null;
45
- if (typeof x === 'string')
46
- return new TextEncoder().encode(x);
47
- if (x instanceof Uint8Array)
48
- return x;
49
- if (x instanceof ArrayBuffer)
50
- return new Uint8Array(x);
51
- if (ArrayBuffer.isView(x))
52
- return new Uint8Array(x.buffer, x.byteOffset, x.byteLength);
53
- throw new TypeError('asset must be Uint8Array | ArrayBuffer | string');
83
+ try {
84
+ let dir = await navigator.storage.getDirectory();
85
+ for (const segment of path.split('/').filter(Boolean)) {
86
+ dir = await dir.getDirectoryHandle(segment, { create });
87
+ }
88
+ return dir;
89
+ }
90
+ catch {
91
+ return null;
92
+ }
54
93
  }
55
- /** Normalize a user-provided storage namespace into a safe relative path. */
56
- function normalizeStorageNamespace(namespace) {
57
- if (typeof namespace !== 'string' || !namespace.trim())
58
- return DEFAULT_STORAGE_NAMESPACE;
59
- const cleaned = namespace
60
- .split('/')
61
- .map((segment) => segment.trim())
62
- .filter(Boolean)
63
- .map((segment) => segment.replace(/[^A-Za-z0-9._-]/g, '_'))
64
- .filter(Boolean)
65
- .join('/');
66
- return cleaned || DEFAULT_STORAGE_NAMESPACE;
94
+ async function resolveAsset(asset) {
95
+ const value = typeof asset === 'function' ? await asset() : asset;
96
+ if (value == null)
97
+ return null;
98
+ if (value instanceof Uint8Array)
99
+ return value;
100
+ if (value instanceof ArrayBuffer)
101
+ return new Uint8Array(value);
102
+ throw new TypeError('rsdkv3: an asset must be a Uint8Array, an ArrayBuffer or a thunk returning one');
67
103
  }
68
- /** Best-effort mkdir -p for the Emscripten FS layer. */
69
- function ensureDir(Module, path) {
70
- const parts = path.split('/').filter(Boolean);
104
+ function sameBytes(a, b) {
105
+ if (!a || a.length !== b.length)
106
+ return false;
107
+ for (let i = 0; i < a.length; i++)
108
+ if (a[i] !== b[i])
109
+ return false;
110
+ return true;
111
+ }
112
+ function mkdirp(Module, path) {
71
113
  let current = '';
72
- for (const part of parts) {
114
+ for (const part of path.split('/').filter(Boolean)) {
73
115
  current += `/${part}`;
74
116
  try {
75
117
  Module.FS.mkdir(current);
76
118
  }
77
119
  catch {
78
- /* already exists */
120
+ /* exists */
79
121
  }
80
122
  }
81
123
  }
82
- /** Ensure the game working directory exists in the in-memory filesystem. */
83
- function mountWorkingDir(Module, storageNamespace) {
84
- const workDir = `${WORK_DIR}/${storageNamespace}`;
85
- ensureDir(Module, workDir);
86
- return { persistent: false, workDir };
87
- }
88
- /** True if `path` exists in the (mounted) filesystem. */
89
- function fileExists(Module, path) {
90
- try {
91
- Module.FS.stat(path);
92
- return true;
124
+ /** The live engine: one booted RSDKv3 and its session. */
125
+ export class Rsdkv3Play extends EnginePlayBase {
126
+ #module = null;
127
+ #destroyed = false;
128
+ #pauseOwner = null;
129
+ #canvas = null;
130
+ #ownsCanvas = false;
131
+ #box = null;
132
+ #boxObserver = null;
133
+ #namespace = DEFAULT_STORAGE_NAMESPACE;
134
+ #storagePath = `${ENGINE_ID}/${DEFAULT_STORAGE_NAMESPACE}`;
135
+ #workDir = `${WORK_ROOT}/${ENGINE_ID}/${DEFAULT_STORAGE_NAMESPACE}`;
136
+ #persist = true;
137
+ #saveTimer = null;
138
+ #lastSave = null;
139
+ #flushing = null;
140
+ #onHidden = () => {
141
+ if (document.visibilityState === 'hidden')
142
+ void this.flushSaves();
143
+ };
144
+ constructor(init, events) {
145
+ super(RSDKV3_SPEC, init, events);
93
146
  }
94
- catch {
95
- return false;
147
+ get namespace() {
148
+ return this.#namespace;
96
149
  }
97
- }
98
- /** Boot the RSDKv3 engine. */
99
- export async function load(config) {
100
- const { canvas, assets, onEvent } = config;
101
- const options = config.options;
102
- if (!canvas)
103
- throw new Error('rsdkv3: config.canvas is required');
104
- // Emscripten's SDL2 port locates the canvas via document.querySelector('#canvas').
105
- if (canvas.id !== 'canvas')
106
- canvas.id = 'canvas';
107
- const emit = (e) => {
108
- try {
109
- onEvent?.(e);
150
+ /** Where this session's files live, relative to the OPFS root: `rsdkv3/<namespace>`. */
151
+ get storagePath() {
152
+ return this.#storagePath;
153
+ }
154
+ get pausedBy() {
155
+ return this.#pauseOwner;
156
+ }
157
+ /** RSDKv3's stage list, for a host that draws its own stage select. */
158
+ get devMenu() {
159
+ const Module = () => this.#module;
160
+ return {
161
+ getStageList() {
162
+ try {
163
+ return JSON.parse(Module()?.web_devmenu_get_stage_list?.() ?? '[]');
164
+ }
165
+ catch {
166
+ return [];
167
+ }
168
+ },
169
+ loadStage(category, stage) {
170
+ Module()?.web_devmenu_load_stage?.(category | 0, stage | 0);
171
+ },
172
+ };
173
+ }
174
+ /**
175
+ * Freeze the game and its sound. The first caller owns the pause; only that
176
+ * owner's {@link resume} lifts it. The save is flushed.
177
+ */
178
+ pause(owner = 'host') {
179
+ const Module = this.#module;
180
+ if (!Module || this.#pauseOwner)
181
+ return;
182
+ this.#pauseOwner = owner;
183
+ Module.web_devmenu_set_paused?.(true);
184
+ void Module.SDL2?.audioContext?.suspend();
185
+ void this.flushSaves();
186
+ this.emit('pause', { owner });
187
+ }
188
+ resume(owner = 'host') {
189
+ const Module = this.#module;
190
+ if (!Module || this.#pauseOwner !== owner)
191
+ return;
192
+ this.#pauseOwner = null;
193
+ void Module.SDL2?.audioContext?.resume();
194
+ Module.web_devmenu_set_paused?.(false);
195
+ this.emit('resume', { owner });
196
+ }
197
+ /** Copy `SData.bin` to OPFS `rsdkv3/<namespace>/` if it changed; emits `saves`. */
198
+ flushSaves() {
199
+ this.#flushing ??= this.#flush().finally(() => {
200
+ this.#flushing = null;
201
+ });
202
+ return this.#flushing;
203
+ }
204
+ // ---- Contract hooks ----
205
+ mounted(target) {
206
+ if (target instanceof HTMLCanvasElement) {
207
+ this.#canvas = target;
208
+ this.#ownsCanvas = false;
209
+ this.#box = target.parentElement;
110
210
  }
111
- catch { /* host handler must not break us */ }
112
- };
113
- const jsUrl = config.jsUrl ?? new URL('./rsdkv3.js', import.meta.url).href;
114
- const wasmUrl = config.wasmUrl ?? new URL('./rsdkv3.wasm', import.meta.url).href;
115
- // RSDKv3 uses the same key map preset used by the shared launcher script.
116
- if (typeof window !== 'undefined')
117
- window.__gamepadKeyMap = manifest.input;
118
- const mod = await import(/* @vite-ignore */ jsUrl);
119
- const createRSDKv3 = mod.default;
120
- const Module = await createRSDKv3({
121
- canvas,
122
- noInitialRun: true, // built with -sINVOKE_RUN=0; we mount data before main()
123
- locateFile: (path) => (path.endsWith('.wasm') ? wasmUrl : path),
124
- print: (...a) => console.log('[rsdkv3]', ...a),
125
- printErr: (...a) => console.error('[rsdkv3]', ...a),
126
- onAbort: (reason) => emit({ type: 'error', error: new Error(`rsdkv3 aborted: ${reason}`) }),
127
- });
128
- const storageNamespace = normalizeStorageNamespace(config.storageNamespace);
129
- const { persistent, workDir } = mountWorkingDir(Module, storageNamespace);
130
- const dataPath = `${workDir}/Data.rsdk`;
131
- const settingsPath = `${workDir}/settings.ini`;
132
- // Data.rsdk — precedence: explicit asset > lazy provider > existing file.
133
- let dataBytes = toUint8(assets?.data);
134
- if (!dataBytes && config.dataProvider) {
135
- dataBytes = toUint8(await config.dataProvider());
136
- }
137
- if (dataBytes) {
138
- Module.FS.writeFile(dataPath, dataBytes);
139
- }
140
- else if (!fileExists(Module, dataPath)) {
141
- throw new Error('rsdkv3: no Data.rsdk — provide assets.data or dataProvider');
142
- }
143
- // settings.ini — explicit asset > lazy provider > generated from options.
144
- let settingsBytes = toUint8(assets?.settings);
145
- if (!settingsBytes && config.settingsProvider) {
146
- settingsBytes = toUint8(await config.settingsProvider());
147
- }
148
- if (settingsBytes) {
149
- Module.FS.writeFile(settingsPath, settingsBytes);
150
- }
151
- else if (!fileExists(Module, settingsPath)) {
152
- Module.FS.writeFile(settingsPath, new TextEncoder().encode(buildSettingsIni(options)));
153
- }
154
- // else: keep existing settings.ini in memory FS
155
- Module.FS.chdir(workDir);
156
- const setPaused = (paused) => {
157
- if (typeof Module.web_devmenu_set_paused === 'function')
158
- Module.web_devmenu_set_paused(paused);
159
- };
160
- const devMenu = {
161
- getStageList() {
162
- if (typeof Module.web_devmenu_get_stage_list !== 'function')
163
- return [];
211
+ else {
212
+ this.#canvas = document.createElement('canvas');
213
+ this.#ownsCanvas = true;
214
+ this.#box = target;
215
+ target.appendChild(this.#canvas);
216
+ }
217
+ // Emscripten's SDL2 port finds its window with querySelector('#canvas').
218
+ this.#canvas.id = 'canvas';
219
+ this.#canvas.tabIndex = 0;
220
+ this.#canvas.style.display = 'block';
221
+ this.#canvas.style.imageRendering = 'pixelated';
222
+ this.#canvas.addEventListener('contextmenu', (event) => event.preventDefault());
223
+ if (this.#ownsCanvas && this.#box) {
224
+ this.#boxObserver?.disconnect();
225
+ this.#boxObserver = new ResizeObserver(() => this.#fit());
226
+ this.#boxObserver.observe(this.#box);
227
+ }
228
+ }
229
+ async open(_options) {
230
+ if (this.#destroyed || this.#module) {
231
+ // RSDKv3 cannot restart in process: main() runs once and owns the loop.
232
+ throw new Error('rsdkv3: the engine cannot be restarted in process — destroy() and start a new page (or iframe)');
233
+ }
234
+ await this.#boot();
235
+ }
236
+ patched(_kind, _patch) {
237
+ // Nothing in RSDKV3_SPEC is live: settings.ini is read once, at boot.
238
+ }
239
+ async close() {
240
+ if (this.#saveTimer)
241
+ clearInterval(this.#saveTimer);
242
+ this.#saveTimer = null;
243
+ document.removeEventListener('visibilitychange', this.#onHidden);
244
+ window.removeEventListener('pagehide', this.#onHidden);
245
+ const Module = this.#module;
246
+ if (Module) {
247
+ await this.flushSaves();
164
248
  try {
165
- return JSON.parse(Module.web_devmenu_get_stage_list());
166
- }
167
- catch (e) {
168
- console.error('[rsdkv3] getStageList failed', e);
169
- return [];
170
- }
171
- },
172
- loadStage(categoryIdx, stageIdx) {
173
- if (typeof Module.web_devmenu_load_stage === 'function') {
174
- Module.web_devmenu_load_stage(categoryIdx | 0, stageIdx | 0);
249
+ Module.web_devmenu_set_paused?.(true);
250
+ Module.pauseMainLoop?.();
175
251
  }
176
- },
177
- setPaused,
178
- };
179
- // Run main() from the mounted working dir. simulate_infinite_loop schedules
180
- // the rAF loop and returns via a benign unwind Emscripten swallows.
181
- Module.callMain(['UsingCWD']);
182
- emit({ type: 'ready' });
183
- return {
184
- start() { },
185
- pause() { setPaused(true); },
186
- resume() { setPaused(false); },
187
- reset() {
188
- throw new Error('rsdkv3: reset() is not supported — destroy() and load() again');
189
- },
190
- setInput(map) {
191
- if (typeof window !== 'undefined') {
192
- window.__gamepadKeyMap = map;
252
+ catch {
253
+ /* already stopped */
193
254
  }
194
- },
195
- destroy() {
196
255
  try {
197
- Module.pauseMainLoop?.();
256
+ await Module.SDL2?.audioContext?.close();
198
257
  }
199
- catch { /* noop */ }
200
- try {
201
- setPaused(true);
258
+ catch {
259
+ /* already closed */
202
260
  }
203
- catch { /* noop */ }
204
- },
205
- devMenu,
206
- persistent,
207
- storageNamespace,
208
- purgeStorage() {
209
- const deleteFileIfExists = (path) => {
210
- try {
211
- Module.FS.unlink(path);
212
- return true;
213
- }
214
- catch {
215
- return false;
216
- }
217
- };
218
- return {
219
- data: deleteFileIfExists(dataPath),
220
- settings: deleteFileIfExists(settingsPath),
221
- };
222
- },
223
- };
261
+ }
262
+ this.#boxObserver?.disconnect();
263
+ this.#boxObserver = null;
264
+ if (this.#ownsCanvas)
265
+ this.#canvas?.remove();
266
+ this.#canvas = null;
267
+ this.#module = null;
268
+ this.#pauseOwner = null;
269
+ this.#destroyed = true;
270
+ }
271
+ // ---- Boot ----
272
+ async #boot() {
273
+ const config = await this.#values('config');
274
+ const assets = await this.#values('assets');
275
+ const storage = await this.#values('storage');
276
+ if (!this.#canvas)
277
+ throw new Error('rsdkv3: mount() an element (or a canvas) before start()');
278
+ const data = await resolveAsset(assets.data);
279
+ if (!data)
280
+ throw new Error('rsdkv3: no Data.rsdk — hand one over as assets.data (bytes or a thunk)');
281
+ const settings = await resolveAsset(assets.settings);
282
+ const resolved = storagePath(ENGINE_ID, storage.namespace);
283
+ if (resolved.prefixed) {
284
+ console.warn(`[rsdkv3] storage.namespace no longer needs the "${ENGINE_ID}/" prefix. Pass "${resolved.namespace}".`);
285
+ }
286
+ this.#namespace = resolved.namespace;
287
+ this.#storagePath = resolved.path;
288
+ this.#workDir = `${WORK_ROOT}/${resolved.path}`;
289
+ this.#persist = storage.persist !== null;
290
+ const jsUrl = config.jsUrl ?? new URL('./rsdkv3.js', import.meta.url).href;
291
+ const wasmUrl = config.wasmUrl ?? new URL('./rsdkv3.wasm', import.meta.url).href;
292
+ const { default: createRSDKv3 } = (await import(/* @vite-ignore */ jsUrl));
293
+ let failed = null;
294
+ const Module = await createRSDKv3({
295
+ canvas: this.#canvas,
296
+ noInitialRun: true,
297
+ locateFile: (path) => (path.endsWith('.wasm') ? wasmUrl : new URL(path, jsUrl).href),
298
+ print: (text) => console.log('[rsdkv3]', text),
299
+ printErr: (text) => console.warn('[rsdkv3]', text),
300
+ onAbort: (what) => failed?.(new Error(`rsdkv3: aborted — ${String(what)}`)),
301
+ });
302
+ this.#module = Module;
303
+ failed = (error) => this.emit('error', error);
304
+ mkdirp(Module, this.#workDir);
305
+ Module.FS.writeFile(`${this.#workDir}/Data.rsdk`, data);
306
+ Module.FS.writeFile(`${this.#workDir}/settings.ini`, settings ?? new TextEncoder().encode(buildSettingsIni(config)));
307
+ if (this.#persist)
308
+ await this.#restoreSave();
309
+ Module.FS.chdir(this.#workDir);
310
+ Module.callMain(['UsingCWD']);
311
+ if (this.#persist) {
312
+ this.#saveTimer = setInterval(() => void this.flushSaves(), SAVE_INTERVAL_MS);
313
+ document.addEventListener('visibilitychange', this.#onHidden);
314
+ window.addEventListener('pagehide', this.#onHidden);
315
+ }
316
+ this.#fit();
317
+ }
318
+ async #values(kind) {
319
+ const described = (await this[kind]());
320
+ const out = {};
321
+ for (const [key, property] of Object.entries(described))
322
+ out[key] = property.value;
323
+ return out;
324
+ }
325
+ // ---- Save mirror ----
326
+ async #restoreSave() {
327
+ const dir = await opfsDir(this.#storagePath, false);
328
+ if (!dir || !this.#module)
329
+ return;
330
+ try {
331
+ const file = await (await dir.getFileHandle(SAVE_FILE)).getFile();
332
+ if (file.size === 0)
333
+ return;
334
+ const bytes = new Uint8Array(await file.arrayBuffer());
335
+ this.#module.FS.writeFile(`${this.#workDir}/${SAVE_FILE}`, bytes);
336
+ this.#lastSave = bytes;
337
+ }
338
+ catch {
339
+ /* no save yet */
340
+ }
341
+ }
342
+ async #flush() {
343
+ const Module = this.#module;
344
+ if (!Module || !this.#persist)
345
+ return;
346
+ let bytes;
347
+ try {
348
+ bytes = new Uint8Array(Module.FS.readFile(`${this.#workDir}/${SAVE_FILE}`));
349
+ }
350
+ catch {
351
+ return; // the game has not saved yet
352
+ }
353
+ if (sameBytes(this.#lastSave, bytes))
354
+ return;
355
+ const dir = await opfsDir(this.#storagePath, true);
356
+ if (!dir)
357
+ return;
358
+ try {
359
+ const writable = await (await dir.getFileHandle(SAVE_FILE, { create: true })).createWritable();
360
+ await writable.write(bytes);
361
+ await writable.close();
362
+ this.#lastSave = bytes;
363
+ this.emit('saves', { files: [SAVE_FILE] });
364
+ }
365
+ catch (e) {
366
+ console.warn('[rsdkv3] could not persist the save', e);
367
+ }
368
+ }
369
+ // ---- Picture ----
370
+ #fit() {
371
+ const canvas = this.#canvas;
372
+ const box = this.#box;
373
+ if (!canvas || !box || !this.#ownsCanvas)
374
+ return;
375
+ const { width, height } = box.getBoundingClientRect();
376
+ if (!width || !height)
377
+ return;
378
+ const scale = Math.min(width / RSDKV3_VIDEO.width, height / RSDKV3_VIDEO.height);
379
+ canvas.style.width = `${Math.floor(RSDKV3_VIDEO.width * scale)}px`;
380
+ canvas.style.height = `${Math.floor(RSDKV3_VIDEO.height * scale)}px`;
381
+ }
382
+ }
383
+ /** The factory a host constructs: static identity, the configuration chain, `start()`. */
384
+ export class Rsdkv3SDK extends EngineSDKBase {
385
+ static id = ENGINE_ID;
386
+ /** Kept in step with package.json by `node scripts/sync-version.mjs`. */
387
+ static version = '0.2.0';
388
+ static name = 'Retro Software Development Kit v3';
389
+ static description = 'RSDKv3 (Sonic CD 2011 decompilation) compiled to WebAssembly. Ships none of the game: the player provides Data.rsdk, and it never leaves their browser.';
390
+ createPlay(init, events) {
391
+ return new Rsdkv3Play(init, events);
392
+ }
224
393
  }
225
- export default { manifest, load };
394
+ /** CI's conformance line: if this class stops satisfying the contract, `make test` fails. */
395
+ export const RSDKV3_ENGINE = Rsdkv3SDK;
396
+ export default Rsdkv3SDK;
226
397
  //# sourceMappingURL=rsdkv3.sdk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rsdkv3.sdk.js","sourceRoot":"","sources":["../../src/rsdkv3.sdk.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rsdkv3.sdk.js","sourceRoot":"","sources":["../../src/rsdkv3.sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EACL,cAAc,EACd,aAAa,EACb,YAAY,GAKb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,WAAW,EACX,YAAY,GAKb,MAAM,qBAAqB,CAAC;AAW7B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEhE,MAAM,SAAS,GAAG,QAAQ,CAAC;AAC3B,MAAM,yBAAyB,GAAG,SAAS,CAAC;AAC5C,MAAM,SAAS,GAAG,OAAO,CAAC;AAC1B,MAAM,SAAS,GAAG,WAAW,CAAC;AAC9B,MAAM,gBAAgB,GAAG,MAAM,CAAC;AA0BhC;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,QAAgB,EAChB,SAAkB;IAElB,MAAM,QAAQ,GACZ,OAAO,SAAS,KAAK,QAAQ;QAC3B,CAAC,CAAC,SAAS;aACN,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;aAChC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC;aACnE,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QAC/D,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;IACjE,IAAI,QAAQ;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,yBAAyB,CAAC;IAChE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,QAAQ,IAAI,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC;AAC1E,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,OAAO;QACL,OAAO;QACP,mBAAmB,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE;QAC9D,WAAW,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE;QAC9C,EAAE;QACF,QAAQ;QACR,YAAY,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE;QACxC,wBAAwB,MAAM,CAAC,oBAAoB,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE;QAClF,EAAE;QACF,SAAS;QACT,eAAe;QACf,kBAAkB;QAClB,mBAAmB;QACnB,SAAS,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE;QAC1C,eAAe;QACf,eAAe,YAAY,CAAC,KAAK,EAAE;QACnC,gBAAgB,YAAY,CAAC,MAAM,EAAE;QACrC,gBAAgB;QAChB,EAAE;QACF,SAAS;QACT,oBAAoB;QACpB,oBAAoB;QACpB,cAAc,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE;QAC5C,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,MAAe;IAClD,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,YAAY;QAAE,OAAO,IAAI,CAAC;IACtF,IAAI,CAAC;QACH,IAAI,GAAG,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QACjD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,GAAG,GAAG,MAAM,GAAG,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,KAA8B;IACxD,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,IAAI,KAAK,YAAY,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,KAAK,YAAY,WAAW;QAAE,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,IAAI,SAAS,CAAC,gFAAgF,CAAC,CAAC;AACxG,CAAC;AAED,SAAS,SAAS,CAAC,CAAoB,EAAE,CAAa;IACpD,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IACnE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,MAAM,CAAC,MAAoB,EAAE,IAAY;IAChD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,OAAO,IAAI,IAAI,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,0DAA0D;AAC1D,MAAM,OAAO,UAAW,SAAQ,cAA8B;IAC5D,OAAO,GAAwB,IAAI,CAAC;IACpC,UAAU,GAAG,KAAK,CAAC;IACnB,WAAW,GAAkB,IAAI,CAAC;IAElC,OAAO,GAA6B,IAAI,CAAC;IACzC,WAAW,GAAG,KAAK,CAAC;IACpB,IAAI,GAAuB,IAAI,CAAC;IAChC,YAAY,GAA0B,IAAI,CAAC;IAE3C,UAAU,GAAG,yBAAyB,CAAC;IACvC,YAAY,GAAG,GAAG,SAAS,IAAI,yBAAyB,EAAE,CAAC;IAC3D,QAAQ,GAAG,GAAG,SAAS,IAAI,SAAS,IAAI,yBAAyB,EAAE,CAAC;IACpE,QAAQ,GAAG,IAAI,CAAC;IAChB,UAAU,GAA0C,IAAI,CAAC;IACzD,SAAS,GAAsB,IAAI,CAAC;IACpC,SAAS,GAAyB,IAAI,CAAC;IACvC,SAAS,GAAG,GAAS,EAAE;QACrB,IAAI,QAAQ,CAAC,eAAe,KAAK,QAAQ;YAAE,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;IACpE,CAAC,CAAC;IAEF,YAAY,IAAiC,EAAE,MAA+C;QAC5F,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,wFAAwF;IACxF,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,uEAAuE;IACvE,IAAI,OAAO;QACT,MAAM,MAAM,GAAG,GAAwB,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;QACvD,OAAO;YACL,YAAY;gBACV,IAAI,CAAC;oBACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,0BAA0B,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC;gBACtE,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC;YACD,SAAS,CAAC,QAAgB,EAAE,KAAa;gBACvC,MAAM,EAAE,EAAE,sBAAsB,EAAE,CAAC,QAAQ,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAC9D,CAAC;SACF,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,GAAG,MAAM;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QACxC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,MAAM,CAAC,sBAAsB,EAAE,CAAC,IAAI,CAAC,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;QAC1C,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,CAAC,KAAK,GAAG,MAAM;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,KAAK,KAAK;YAAE,OAAO;QAClD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,KAAK,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;QACzC,MAAM,CAAC,sBAAsB,EAAE,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,mFAAmF;IACnF,UAAU;QACR,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;YAC5C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,2BAA2B;IAER,OAAO,CAAC,MAAmB;QAC5C,IAAI,MAAM,YAAY,iBAAiB,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAChD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;YACnB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;QACD,yEAAyE;QACzE,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,QAAQ,CAAC;QAC3B,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QACrC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,WAAW,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;QAChF,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,CAAC;YAChC,IAAI,CAAC,YAAY,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAEkB,KAAK,CAAC,IAAI,CAAC,QAAuB;QACnD,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACpC,wEAAwE;YACxE,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;QACpH,CAAC;QACD,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEkB,OAAO,CAAC,KAAkB,EAAE,MAAc;QAC3D,sEAAsE;IACxE,CAAC;IAEkB,KAAK,CAAC,KAAK;QAC5B,IAAI,IAAI,CAAC,UAAU;YAAE,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACjE,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,CAAC,sBAAsB,EAAE,CAAC,IAAI,CAAC,CAAC;gBACtC,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC;YAC3B,CAAC;YAAC,MAAM,CAAC;gBACP,qBAAqB;YACvB,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;YAC3C,CAAC;YAAC,MAAM,CAAC;gBACP,oBAAoB;YACtB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,CAAC;QAChC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,IAAI,CAAC,WAAW;YAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAC7C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,iBAAiB;IAEjB,KAAK,CAAC,KAAK;QACT,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAe,QAAQ,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAiD,QAAQ,CAAC,CAAC;QAC5F,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAkD,SAAS,CAAC,CAAC;QAC/F,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAE9F,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;QACrG,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAErD,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAC3D,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,mDAAmD,SAAS,oBAAoB,QAAQ,CAAC,SAAS,IAAI,CAAC,CAAC;QACvH,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC;QACrC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,QAAQ,GAAG,GAAG,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC;QAEzC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACjF,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAA+B,CAAC;QAEzG,IAAI,MAAM,GAAoC,IAAI,CAAC;QACnD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;YAChC,MAAM,EAAE,IAAI,CAAC,OAAO;YACpB,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC;YAC5F,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC;YACtD,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC;YAC1D,OAAO,EAAE,CAAC,IAAa,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SACrF,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,MAAM,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAE9C,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,QAAQ,YAAY,EAAE,IAAI,CAAC,CAAC;QACxD,MAAM,CAAC,EAAE,CAAC,SAAS,CACjB,GAAG,IAAI,CAAC,QAAQ,eAAe,EAC/B,QAAQ,IAAI,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAC/D,CAAC;QACF,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAE7C,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAE9B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,UAAU,EAAE,EAAE,gBAAgB,CAAC,CAAC;YAC9E,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9D,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,KAAK,CAAC,OAAO,CAAI,IAAqC;QACpD,MAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,CAAuC,CAAC;QAC7E,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;QACnF,OAAO,GAAQ,CAAC;IAClB,CAAC;IAED,wBAAwB;IAExB,KAAK,CAAC,YAAY;QAChB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAClC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAClE,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO;YAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACvD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,EAAE,KAAK,CAAC,CAAC;YAClE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,iBAAiB;QACnB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtC,IAAI,KAA8B,CAAC;QACnC,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;QAC9E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,6BAA6B;QACvC,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC;YAAE,OAAO;QAC7C,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;YAC/F,MAAM,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,qCAAqC,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,oBAAoB;IAEpB,IAAI;QACF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QACjD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACtD,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM;YAAE,OAAO;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACjF,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;QACnE,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;IACvE,CAAC;CACF;AAED,0FAA0F;AAC1F,MAAM,OAAO,SAAU,SAAQ,aAA6B;IAC1D,MAAM,CAAU,EAAE,GAAG,SAAS,CAAC;IAC/B,yEAAyE;IACzE,MAAM,CAAU,OAAO,GAAG,OAAO,CAAC;IAClC,MAAM,CAAU,IAAI,GAAG,mCAAmC,CAAC;IAC3D,MAAM,CAAU,WAAW,GACzB,yJAAyJ,CAAC;IAEzI,UAAU,CAC3B,IAAgC,EAChC,MAA8C;QAE9C,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;;AAGH,6FAA6F;AAC7F,MAAM,CAAC,MAAM,aAAa,GAAyC,SAAS,CAAC;AAE7E,eAAe,SAAS,CAAC"}
Binary file