From b4331488437c612fdfb9f79c74459b1f9c1e0d41 Mon Sep 17 00:00:00 2001 From: Matthew Pomes Date: Fri, 27 Mar 2026 00:27:34 -0500 Subject: [PATCH] Split WASM and native versions, and move iced support code to native --- .helix/languages.toml | 3 + Cargo.lock | 1279 +++++++++++++----------- Cargo.toml | 54 +- index.html | 13 + src/apu.rs | 122 ++- src/{ => bin/native}/audio.rs | 0 src/{ => bin/native}/debugger.rs | 33 +- src/{ => bin/native}/header_menu.rs | 0 src/{ => bin/native}/hex_view.rs | 87 +- src/{ => bin/native}/main.rs | 23 +- src/{ => bin/native}/resize_watcher.rs | 0 src/bin/wasm/main.rs | 300 ++++++ src/debug.rs | 36 +- src/lib.rs | 28 +- src/mem.rs | 8 +- src/ppu.rs | 497 ++++----- src/test_roms/apu_pulse_1.s | 102 +- wasm.fish | 6 + wasm/wasm.d.ts | 41 + wasm/wasm.html | 47 + wasm/wasm.js | 649 ++++++++++++ wasm/wasm_bg.wasm | Bin 0 -> 325607 bytes wasm/wasm_bg.wasm.d.ts | 14 + 23 files changed, 2330 insertions(+), 1012 deletions(-) create mode 100644 .helix/languages.toml create mode 100644 index.html rename src/{ => bin/native}/audio.rs (100%) rename src/{ => bin/native}/debugger.rs (96%) rename src/{ => bin/native}/header_menu.rs (100%) rename src/{ => bin/native}/hex_view.rs (90%) rename src/{ => bin/native}/main.rs (97%) rename src/{ => bin/native}/resize_watcher.rs (100%) create mode 100644 src/bin/wasm/main.rs create mode 100755 wasm.fish create mode 100644 wasm/wasm.d.ts create mode 100644 wasm/wasm.html create mode 100644 wasm/wasm.js create mode 100644 wasm/wasm_bg.wasm create mode 100644 wasm/wasm_bg.wasm.d.ts diff --git a/.helix/languages.toml b/.helix/languages.toml new file mode 100644 index 0000000..aa8f63c --- /dev/null +++ b/.helix/languages.toml @@ -0,0 +1,3 @@ +[language-server.rust-analyzer] +config = { cargo = { features = "all" } } + diff --git a/Cargo.lock b/Cargo.lock index 5906449..3e45c02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -54,9 +54,9 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "aligned" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" dependencies = [ "as-slice", ] @@ -72,21 +72,21 @@ dependencies = [ [[package]] name = "alsa" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c88dbbce13b232b26250e1e2e6ac18b6a891a646b8148285036ebce260ac5c3" +checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d" dependencies = [ "alsa-sys", - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "libc", ] [[package]] name = "alsa-sys" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +checksum = "ad7569085a265dd3f607ebecce7458eaab2132a84393534c95b18dcbc3f31e04" dependencies = [ "libc", "pkg-config", @@ -99,7 +99,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.10.0", + "bitflags 2.11.0", "cc", "cesu8", "jni", @@ -139,9 +139,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arbitrary" @@ -222,9 +222,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", @@ -247,16 +247,16 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.1.2", + "rustix 1.1.4", "slab", "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener", "event-listener-strategy", @@ -278,7 +278,7 @@ dependencies = [ "cfg-if", "event-listener", "futures-lite", - "rustix 1.1.2", + "rustix 1.1.4", ] [[package]] @@ -304,7 +304,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.1.2", + "rustix 1.1.4", "signal-hook-registry", "slab", "windows-sys 0.61.2", @@ -354,7 +354,7 @@ dependencies = [ "num-traits", "pastey", "rayon", - "thiserror 2.0.17", + "thiserror 2.0.18", "v_frame", "y4m", ] @@ -375,9 +375,9 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" +checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" dependencies = [ "arrayvec", ] @@ -414,18 +414,18 @@ checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitfield" -version = "0.19.3" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf79f42d21f18b5926a959280215903e659760da994835d27c3a0c5ff4f898f" +checksum = "21ba6517c6b0f2bf08be60e187ab64b038438f22dd755614d8fe4d4098c46419" dependencies = [ "bitfield-macros", ] [[package]] name = "bitfield-macros" -version = "0.19.3" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6115af052c7914c0cbb97195e5c72cb61c511527250074f5c041d1048b0d8b16" +checksum = "f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97" dependencies = [ "proc-macro2", "quote", @@ -440,9 +440,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "bitstream-io" @@ -474,7 +474,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -498,15 +498,15 @@ checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] @@ -530,9 +530,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "calloop" @@ -540,7 +540,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "log", "polling", "rustix 0.38.44", @@ -550,13 +550,13 @@ dependencies = [ [[package]] name = "calloop" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "polling", - "rustix 1.1.2", + "rustix 1.1.4", "slab", "tracing", ] @@ -579,17 +579,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" dependencies = [ - "calloop 0.14.3", - "rustix 1.1.2", + "calloop 0.14.4", + "rustix 1.1.4", "wayland-backend", "wayland-client", ] [[package]] name = "cc" -version = "1.2.41" +version = "1.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ "find-msvc-tools", "jobserver", @@ -617,9 +617,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "num-traits", @@ -657,11 +657,11 @@ dependencies = [ [[package]] name = "clipboard_x11" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4274ea815e013e0f9f04a2633423e14194e408a0576c943ce3d14ca56c50031c" +checksum = "bd63e33452ffdafd39924c4f05a5dd1e94db646c779c6bd59148a3d95fff5ad4" dependencies = [ - "thiserror 1.0.69", + "thiserror 2.0.18", "x11rb", ] @@ -701,6 +701,26 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" +dependencies = [ + "log", + "web-sys", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -740,19 +760,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-graphics" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.10.1", - "core-graphics-types 0.2.0", - "foreign-types", - "libc", -] - [[package]] name = "core-graphics-types" version = "0.1.3" @@ -770,7 +777,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "libc", ] @@ -795,11 +802,11 @@ dependencies = [ [[package]] name = "coreaudio-rs" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aae284fbaf7d27aa0e292f7677dfbe26503b0d555026f702940805a630eac17" +checksum = "d15c3c3cee7c087938f7ad1c3098840b3ef1f1bdc7f6e496336c3b1e7a6f3914" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.0", "libc", "objc2-audio-toolbox", "objc2-core-audio", @@ -812,7 +819,7 @@ name = "cosmic-text" version = "0.15.0" source = "git+https://github.com/pop-os/cosmic-text.git?rev=a07a6190548c8e40a55f6b7761387047ff1bf6ff#a07a6190548c8e40a55f6b7761387047ff1bf6ff" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "fontdb", "harfrust", "linebender_resource_handle", @@ -832,9 +839,9 @@ dependencies = [ [[package]] name = "cpal" -version = "0.17.1" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1f9c7312f19fc2fa12fd7acaf38de54e8320ba10d1a02dcbe21038def51ccb" +checksum = "d8942da362c0f0d895d7cac616263f2f9424edc5687364dfd1d25ef7eba506d7" dependencies = [ "alsa", "coreaudio-rs", @@ -847,7 +854,7 @@ dependencies = [ "ndk-context", "num-derive", "num-traits", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-audio-toolbox", "objc2-avf-audio", "objc2-core-audio", @@ -914,9 +921,9 @@ dependencies = [ [[package]] name = "ctor-lite" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f791803201ab277ace03903de1594460708d2d54df6053f2d9e82f592b19e3b" +checksum = "e162d0c2e2068eb736b71e5597eff0b9944e6b973cd9f37b6a288ab9bf20e300" [[package]] name = "cursor-icon" @@ -938,21 +945,21 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.6.2", "libc", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] name = "dlib" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" dependencies = [ "libloading", ] @@ -985,9 +992,9 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "endi" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" [[package]] name = "enumflags2" @@ -1064,9 +1071,9 @@ dependencies = [ [[package]] name = "euclid" -version = "0.22.11" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" dependencies = [ "num-traits", ] @@ -1144,15 +1151,15 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.4" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1237,9 +1244,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1252,9 +1259,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1262,27 +1269,26 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", "futures-util", - "num_cpus", ] [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -1299,9 +1305,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", @@ -1310,21 +1316,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1334,7 +1340,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -1344,7 +1349,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "rustix 1.1.2", + "rustix 1.1.4", "windows-link", ] @@ -1356,10 +1361,23 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + [[package]] name = "gif" version = "0.14.1" @@ -1414,7 +1432,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "gpu-alloc-types", ] @@ -1424,7 +1442,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -1445,7 +1463,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "gpu-descriptor-types", "hashbrown 0.15.5", ] @@ -1456,7 +1474,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -1487,7 +1505,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92c020db12c71d8a12a3fe7607873cade3a01a6287e29d540c8723276221b9d8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytemuck", "core_maths", "read-fonts", @@ -1505,9 +1523,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "foldhash 0.2.0", ] @@ -1518,6 +1536,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.5.2" @@ -1538,9 +1562,9 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1573,7 +1597,7 @@ dependencies = [ "iced_widget", "iced_winit", "image", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1586,7 +1610,7 @@ dependencies = [ "log", "semver", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -1594,7 +1618,7 @@ dependencies = [ name = "iced_core" version = "0.15.0-dev" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "glam", "lilt", @@ -1603,7 +1627,7 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "smol_str", - "thiserror 2.0.17", + "thiserror 2.0.18", "web-time", ] @@ -1644,7 +1668,7 @@ dependencies = [ name = "iced_graphics" version = "0.15.0-dev" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytemuck", "cosmic-text", "half", @@ -1656,7 +1680,7 @@ dependencies = [ "lyon_path", "raw-window-handle", "rustc-hash 2.1.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "unicode-segmentation", ] @@ -1676,7 +1700,7 @@ dependencies = [ "iced_tiny_skia", "iced_wgpu", "log", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1687,7 +1711,7 @@ dependencies = [ "iced_core", "iced_futures", "raw-window-handle", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1709,7 +1733,7 @@ dependencies = [ name = "iced_wgpu" version = "0.15.0-dev" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytemuck", "cryoglyph", "futures", @@ -1720,7 +1744,7 @@ dependencies = [ "log", "lyon", "rustc-hash 2.1.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "wgpu", ] @@ -1733,7 +1757,7 @@ dependencies = [ "num-traits", "ouroboros", "rustc-hash 2.1.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "unicode-segmentation", ] @@ -1746,7 +1770,7 @@ dependencies = [ "log", "mundy", "rustc-hash 2.1.1", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", "wasm-bindgen-futures", "web-sys", @@ -1755,10 +1779,16 @@ dependencies = [ ] [[package]] -name = "image" -version = "0.25.9" +name = "id-arena" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", @@ -1774,8 +1804,8 @@ dependencies = [ "rayon", "rgb", "tiff", - "zune-core 0.5.0", - "zune-jpeg 0.5.6", + "zune-core", + "zune-jpeg", ] [[package]] @@ -1796,12 +1826,14 @@ checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" [[package]] name = "indexmap" -version = "2.12.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown 0.16.0", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] @@ -1826,9 +1858,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jni" @@ -1858,15 +1890,15 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -1914,6 +1946,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "lebe" version = "0.5.3" @@ -1922,15 +1960,15 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.177" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libfuzzer-sys" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" dependencies = [ "arbitrary", "cc", @@ -1948,19 +1986,20 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", - "redox_syscall 0.5.18", + "plain", + "redox_syscall 0.7.3", ] [[package]] @@ -1986,9 +2025,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litrs" @@ -2007,9 +2046,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "loop9" @@ -2022,15 +2061,15 @@ dependencies = [ [[package]] name = "lru" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" [[package]] name = "lyon" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbcb7d54d54c8937364c9d41902d066656817dce1e03a44e5533afebd1ef4352" +checksum = "bd0578bdecb7d6d88987b8b2b1e3a4e2f81df9d0ece1078623324a567904e7b7" dependencies = [ "lyon_algorithms", "lyon_tessellation", @@ -2038,9 +2077,9 @@ dependencies = [ [[package]] name = "lyon_algorithms" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c0829e28c4f336396f250d850c3987e16ce6db057ffe047ce0dd54aab6b647" +checksum = "9815fac08e6fd96733a11dce4f9d15a3f338e96a2e2311ee21e1b738efc2bc0f" dependencies = [ "lyon_path", "num-traits", @@ -2048,9 +2087,9 @@ dependencies = [ [[package]] name = "lyon_geom" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e16770d760c7848b0c1c2d209101e408207a65168109509f8483837a36cf2e7" +checksum = "4336502e29e32af93cf2dad2214ed6003c17ceb5bd499df77b1de663b9042b92" dependencies = [ "arrayvec", "euclid", @@ -2059,9 +2098,9 @@ dependencies = [ [[package]] name = "lyon_path" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeca86bcfd632a15984ba029b539ffb811e0a70bf55e814ef8b0f54f506fdeb" +checksum = "5c463f9c428b7fc5ec885dcd39ce4aa61e29111d0e33483f6f98c74e89d8621e" dependencies = [ "lyon_geom", "num-traits", @@ -2069,9 +2108,9 @@ dependencies = [ [[package]] name = "lyon_tessellation" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f586142e1280335b1bc89539f7c97dd80f08fc43e9ab1b74ef0a42b04aa353" +checksum = "05a35a7dd71b845ff317ce1834c4185506b79790294bde397df8d5c23031e357" dependencies = [ "float_next_after", "lyon_path", @@ -2117,15 +2156,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmap2" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" dependencies = [ "libc", ] @@ -2145,7 +2184,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block", "core-graphics-types 0.2.0", "foreign-types", @@ -2166,9 +2205,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "wasi", @@ -2177,9 +2216,9 @@ dependencies = [ [[package]] name = "moxcms" -version = "0.7.10" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80986bbbcf925ebd3be54c26613d861255284584501595cf418320c078945608" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" dependencies = [ "num-traits", "pxfm", @@ -2199,7 +2238,7 @@ dependencies = [ "futures-lite", "jni", "ndk-context", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-app-kit 0.3.2", "objc2-foundation 0.3.2", "pin-project-lite", @@ -2224,12 +2263,12 @@ checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "codespan-reporting", "half", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "hexf-parse", "indexmap", "libm", @@ -2238,7 +2277,7 @@ dependencies = [ "once_cell", "rustc-hash 1.1.0", "spirv", - "thiserror 2.0.17", + "thiserror 2.0.18", "unicode-ident", ] @@ -2248,7 +2287,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "jni-sys", "log", "ndk-sys", @@ -2278,15 +2317,18 @@ version = "0.1.0" dependencies = [ "bitfield", "bytes", + "console_error_panic_hook", + "console_log", "cpal", "iced", - "iced_core", + "log", "rfd", "ringbuf", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "tracing-subscriber", + "web-sys", ] [[package]] @@ -2295,19 +2337,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - [[package]] name = "nom" version = "8.0.0" @@ -2383,21 +2412,11 @@ dependencies = [ "libm", ] -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "num_enum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -2405,9 +2424,9 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2442,9 +2461,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -2455,7 +2474,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -2471,10 +2490,10 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.6.2", "libc", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-cloud-kit 0.3.2", "objc2-core-data 0.3.2", "objc2-core-foundation", @@ -2492,9 +2511,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-audio", "objc2-core-audio-types", "objc2-core-foundation", @@ -2507,7 +2526,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be" dependencies = [ - "objc2 0.6.3", + "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -2517,7 +2536,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -2530,8 +2549,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.10.0", - "objc2 0.6.3", + "bitflags 2.11.0", + "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -2553,7 +2572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2" dependencies = [ "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-audio-types", "objc2-core-foundation", "objc2-foundation 0.3.2", @@ -2565,8 +2584,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" dependencies = [ - "bitflags 2.10.0", - "objc2 0.6.3", + "bitflags 2.11.0", + "objc2 0.6.4", ] [[package]] @@ -2575,7 +2594,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -2587,8 +2606,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "bitflags 2.10.0", - "objc2 0.6.3", + "bitflags 2.11.0", + "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -2598,11 +2617,11 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.6.2", "dispatch2", "libc", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -2611,9 +2630,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-io-surface", ] @@ -2636,7 +2655,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" dependencies = [ - "objc2 0.6.3", + "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -2658,8 +2677,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.10.0", - "objc2 0.6.3", + "bitflags 2.11.0", + "objc2 0.6.4", "objc2-core-foundation", "objc2-core-graphics", ] @@ -2670,8 +2689,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" dependencies = [ - "bitflags 2.10.0", - "objc2 0.6.3", + "bitflags 2.11.0", + "objc2 0.6.4", "objc2-core-foundation", "objc2-core-graphics", "objc2-io-surface", @@ -2689,7 +2708,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "dispatch", "libc", @@ -2702,10 +2721,10 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.6.2", "libc", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -2715,8 +2734,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.10.0", - "objc2 0.6.3", + "bitflags 2.11.0", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -2738,7 +2757,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -2750,7 +2769,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -2763,8 +2782,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.10.0", - "objc2 0.6.3", + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", "objc2-foundation 0.3.2", ] @@ -2784,7 +2804,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-cloud-kit 0.2.2", @@ -2816,7 +2836,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -2825,16 +2845,17 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "orbclient" -version = "0.3.49" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "247ad146e19b9437f8604c21f8652423595cf710ad108af40e77d3ae6e96b827" +checksum = "59aed3b33578edcfa1bc96a321d590d31832b6ad55a26f0313362ce687e9abd6" dependencies = [ + "libc", "libredox", ] @@ -2874,7 +2895,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "proc-macro2-diagnostics", "quote", @@ -2939,18 +2960,18 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", @@ -2959,9 +2980,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -2971,9 +2992,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", @@ -2987,12 +3008,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] -name = "png" -version = "0.18.0" +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "crc32fast", "fdeflate", "flate2", @@ -3009,7 +3036,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.1.2", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -3021,15 +3048,15 @@ checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ "portable-atomic", ] @@ -3050,19 +3077,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" [[package]] -name = "proc-macro-crate" -version = "3.4.0" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -3101,12 +3138,9 @@ dependencies = [ [[package]] name = "pxfm" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" -dependencies = [ - "num-traits", -] +checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" [[package]] name = "qoi" @@ -3125,18 +3159,18 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.37.5" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.41" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -3147,6 +3181,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.9.2" @@ -3169,24 +3209,24 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom", + "getrandom 0.3.4", ] [[package]] name = "range-alloc" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" [[package]] name = "rangemap" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223" +checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" [[package]] name = "rav1e" @@ -3218,16 +3258,16 @@ dependencies = [ "rand", "rand_chacha", "simd_helpers", - "thiserror 2.0.17", + "thiserror 2.0.18", "v_frame", "wasm-bindgen", ] [[package]] name = "ravif" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" dependencies = [ "avif-serialize", "imgref", @@ -3290,14 +3330,23 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +dependencies = [ + "bitflags 2.11.0", ] [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -3306,9 +3355,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "renderdoc-sys" @@ -3327,7 +3376,7 @@ dependencies = [ "js-sys", "libc", "log", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-foundation 0.3.2", @@ -3345,9 +3394,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.52" +version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" [[package]] name = "ringbuf" @@ -3384,7 +3433,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3393,14 +3442,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -3410,12 +3459,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "same-file" version = "1.0.6" @@ -3452,9 +3495,9 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" [[package]] name = "semver" @@ -3498,15 +3541,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -3537,18 +3580,19 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "simd_helpers" @@ -3571,15 +3615,15 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "version_check", ] @@ -3596,7 +3640,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "calloop 0.13.0", "calloop-wayland-source 0.3.0", "cursor-icon", @@ -3621,15 +3665,15 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" dependencies = [ - "bitflags 2.10.0", - "calloop 0.14.3", + "bitflags 2.11.0", + "calloop 0.14.4", "calloop-wayland-source 0.4.1", "cursor-icon", "libc", "log", "memmap2", - "rustix 1.1.2", - "thiserror 2.0.17", + "rustix 1.1.4", + "thiserror 2.0.18", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -3664,42 +3708,42 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "softbuffer" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" dependencies = [ "as-raw-xcb-connection", "bytemuck", - "cfg_aliases", - "core-graphics 0.24.0", "fastrand", - "foreign-types", "js-sys", - "log", "memmap2", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-quartz-core 0.2.2", + "ndk", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", "raw-window-handle", "redox_syscall 0.5.18", - "rustix 0.38.44", + "rustix 1.1.4", "tiny-xlib", + "tracing", "wasm-bindgen", "wayland-backend", "wayland-client", "wayland-sys", "web-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", "x11rb", ] @@ -3709,7 +3753,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -3749,9 +3793,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.108" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -3769,14 +3813,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.23.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.2", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -3800,11 +3844,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -3820,9 +3864,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -3840,16 +3884,16 @@ dependencies = [ [[package]] name = "tiff" -version = "0.10.3" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" dependencies = [ "fax", "flate2", "half", "quick-error", "weezl", - "zune-jpeg 0.4.21", + "zune-jpeg", ] [[package]] @@ -3892,9 +3936,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -3907,16 +3951,14 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", "mio", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.61.2", @@ -3924,9 +3966,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", @@ -3935,39 +3977,39 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.3" +version = "1.0.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.7" +version = "0.25.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +checksum = "8ca1a40644a28bce036923f6a431df0b34236949d111cc07cb6dca830c9ef2e1" dependencies = [ "indexmap", "toml_datetime", "toml_parser", - "winnow", + "winnow 1.0.0", ] [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.0.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420" dependencies = [ - "winnow", + "winnow 1.0.0", ] [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -3977,9 +4019,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -3988,9 +4030,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -4019,9 +4061,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "chrono", "matchers", @@ -4050,13 +4092,13 @@ dependencies = [ [[package]] name = "uds_windows" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" dependencies = [ "memoffset", "tempfile", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -4067,9 +4109,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.20" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-linebreak" @@ -4079,9 +4121,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-script" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" [[package]] name = "unicode-segmentation" @@ -4091,15 +4133,21 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.14" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "uuid" -version = "1.19.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ "js-sys", "serde_core", @@ -4147,18 +4195,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", @@ -4167,25 +4224,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -4196,9 +4239,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4206,26 +4249,60 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "wasmtimer" version = "0.4.3" @@ -4242,13 +4319,13 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.11" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +checksum = "aa75f400b7f719bcd68b3f47cd939ba654cedeef690f486db71331eec4c6a406" dependencies = [ "cc", "downcast-rs", - "rustix 1.1.2", + "rustix 1.1.4", "scoped-tls", "smallvec", "wayland-sys", @@ -4256,12 +4333,12 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.11" +version = "0.31.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +checksum = "ab51d9f7c071abeee76007e2b742499e535148035bb835f97aaed1338cf516c3" dependencies = [ - "bitflags 2.10.0", - "rustix 1.1.2", + "bitflags 2.11.0", + "rustix 1.1.4", "wayland-backend", "wayland-scanner", ] @@ -4272,29 +4349,29 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.11" +version = "0.31.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" +checksum = "4b3298683470fbdc6ca40151dfc48c8f2fd4c41a26e13042f801f85002384091" dependencies = [ - "rustix 1.1.2", + "rustix 1.1.4", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.32.9" +version = "0.32.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +checksum = "b23b5df31ceff1328f06ac607591d5ba360cf58f90c8fad4ac8d3a55a3c4aec7" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -4306,7 +4383,7 @@ version = "20250721.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4315,11 +4392,11 @@ dependencies = [ [[package]] name = "wayland-protocols-misc" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c" +checksum = "429b99200febaf95d4f4e46deff6fe4382bcff3280ee16a41cf887b3c3364984" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4328,11 +4405,11 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" +checksum = "d392fc283a87774afc9beefcd6f931582bb97fe0e6ced0b306a62cb1d026527c" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4341,11 +4418,11 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" +checksum = "78248e4cc0eff8163370ba5c158630dcae1f3497a586b826eca2ef5f348d6235" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4354,9 +4431,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.7" +version = "0.31.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +checksum = "c86287151a309799b821ca709b7345a048a2956af05957c89cb824ab919fa4e3" dependencies = [ "proc-macro2", "quick-xml", @@ -4365,9 +4442,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.7" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +checksum = "374f6b70e8e0d6bf9461a32988fd553b59ff630964924dad6e4a4eb6bd538d17" dependencies = [ "dlib", "log", @@ -4377,9 +4454,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -4408,11 +4485,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" dependencies = [ "arrayvec", - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "document-features", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "js-sys", "log", "naga", @@ -4439,11 +4516,11 @@ dependencies = [ "arrayvec", "bit-set", "bit-vec", - "bitflags 2.10.0", + "bitflags 2.11.0", "bytemuck", "cfg_aliases", "document-features", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "indexmap", "log", "naga", @@ -4454,7 +4531,7 @@ dependencies = [ "raw-window-handle", "rustc-hash 1.1.0", "smallvec", - "thiserror 2.0.17", + "thiserror 2.0.18", "wgpu-core-deps-apple", "wgpu-core-deps-emscripten", "wgpu-core-deps-windows-linux-android", @@ -4499,7 +4576,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.10.0", + "bitflags 2.11.0", "block", "bytemuck", "cfg-if", @@ -4510,7 +4587,7 @@ dependencies = [ "gpu-alloc", "gpu-allocator", "gpu-descriptor", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "js-sys", "khronos-egl", "libc", @@ -4530,7 +4607,7 @@ dependencies = [ "raw-window-handle", "renderdoc-sys", "smallvec", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", "web-sys", "wgpu-types", @@ -4544,30 +4621,14 @@ version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytemuck", "js-sys", "log", - "thiserror 2.0.17", + "thiserror 2.0.18", "web-sys", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.11" @@ -4577,12 +4638,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "window_clipboard" version = "0.5.1" @@ -4594,7 +4649,7 @@ dependencies = [ "clipboard_wayland", "clipboard_x11", "raw-window-handle", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -4789,15 +4844,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -4831,30 +4877,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - [[package]] name = "windows-threading" version = "0.2.1" @@ -4876,12 +4905,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -4894,12 +4917,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -4912,24 +4929,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -4942,12 +4947,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -4960,12 +4959,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -4978,12 +4971,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -4996,12 +4983,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winit" version = "0.30.8" @@ -5010,14 +4991,14 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.10.0", + "bitflags 2.11.0", "block2 0.5.1", "bytemuck", "calloop 0.13.0", "cfg_aliases", "concurrent-queue", "core-foundation 0.9.4", - "core-graphics 0.23.2", + "core-graphics", "cursor-icon", "dpi", "js-sys", @@ -5055,18 +5036,109 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "x11-dl" @@ -5090,7 +5162,7 @@ dependencies = [ "libc", "libloading", "once_cell", - "rustix 1.1.2", + "rustix 1.1.4", "x11rb-protocol", ] @@ -5112,7 +5184,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "dlib", "log", "once_cell", @@ -5151,9 +5223,9 @@ checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" [[package]] name = "zbus" -version = "5.12.0" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" dependencies = [ "async-broadcast", "async-executor", @@ -5169,15 +5241,16 @@ dependencies = [ "futures-core", "futures-lite", "hex", - "nix", + "libc", "ordered-stream", + "rustix 1.1.4", "serde", "serde_repr", "tracing", "uds_windows", "uuid", "windows-sys 0.61.2", - "winnow", + "winnow 0.7.15", "zbus_macros", "zbus_names", "zvariant", @@ -5185,9 +5258,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.12.0" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb94821ca8a87ca9c298b5d1cbd80e2a8b67115d99f6e4551ac49e42b6a314" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5200,13 +5273,12 @@ dependencies = [ [[package]] name = "zbus_names" -version = "4.2.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" dependencies = [ "serde", - "static_assertions", - "winnow", + "winnow 0.7.15", "zvariant", ] @@ -5218,18 +5290,18 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", @@ -5237,16 +5309,16 @@ dependencies = [ ] [[package]] -name = "zune-core" -version = "0.4.12" +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zune-core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-inflate" @@ -5259,41 +5331,32 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.21" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +checksum = "ec5f41c76397b7da451efd19915684f727d7e1d516384ca6bd0ec43ec94de23c" dependencies = [ - "zune-core 0.4.12", -] - -[[package]] -name = "zune-jpeg" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f520eebad972262a1dde0ec455bce4f8b298b1e5154513de58c114c4c54303e8" -dependencies = [ - "zune-core 0.5.0", + "zune-core", ] [[package]] name = "zvariant" -version = "5.8.0" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" dependencies = [ "endi", "enumflags2", "serde", - "winnow", + "winnow 0.7.15", "zvariant_derive", "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "5.8.0" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5304,13 +5367,13 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" dependencies = [ "proc-macro2", "quote", "serde", "syn", - "winnow", + "winnow 0.7.15", ] diff --git a/Cargo.toml b/Cargo.toml index 5dbfc4e..123da16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,18 +3,52 @@ name = "nes-emu" version = "0.1.0" edition = "2024" +[features] +default = [] +iced = [ + "dep:iced", "iced/debug", "iced/canvas", "iced/lazy", "iced/image", "iced/advanced", "tokio", "fs" +] +fs = [] +tokio = ["iced/tokio", "dep:tokio", "tokio/time", "tokio/fs"] +iced_wasm = ["dep:iced"] +audio = ["dep:cpal", "dep:ringbuf"] +web = ["dep:web-sys", "dep:web-sys"] + [dependencies] bitfield = "0.19.3" -# iced = { version = "0.14.0", features = ["debug", "canvas", "tokio", "lazy", "image", "advanced"] } -iced = { path = "../iced", features = ["debug", "canvas", "tokio", "lazy", "image", "advanced"] } -iced_core = { path = "../iced/core", features = ["advanced"] } -rfd = "0.17.2" -# iced_graphics = { version = "0.14.0", features = ["geometry", "image"] } -# iced_widget = { version = "0.13.4", features = ["canvas", "image"] } -thiserror = "2.0.17" -tokio = { version = "1.48.0", features = ["full"] } +thiserror = "2.0.18" tracing = "0.1.41" tracing-subscriber = { version = "0.3.20", features = ["ansi", "chrono", "env-filter", "json", "serde"] } bytes = "*" -cpal = "0.17.1" -ringbuf = "0.4.8" + +# yew = { version = "0.23", features = ["csr"], optional = true } +web-sys = { version = "*", features = [ + "HtmlCanvasElement", "CanvasRenderingContext2d", + "Window", "Document", "KeyboardEvent", + "DocumentTimeline", "AudioContextState", + "HtmlButtonElement", + "HtmlInputElement", "FileList", "File", "Blob", + "ImageBitmap", "ImageData", + "AudioContext", "AudioContextOptions", + "AudioBuffer", "AudioBufferOptions", "AudioDestinationNode", "AudioBufferSourceNode", + "GainNode", "AudioParam", "DelayNode" +], optional = true } +cpal = { version = "0.17.1", optional = true} +ringbuf = { version = "0.4.8", optional = true} +iced = { path = "../iced", features = [], optional = true } +# iced_core = { path = "../iced/core", features = ["advanced"], optional = true } +rfd = { version = "0.17.2", optional = true } +tokio = { version = "1.48.0", features = [], optional = true } +log = "*" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +console_error_panic_hook = "0.1" +console_log = "1.0" + +[[bin]] +name = "native" +required-features = ["iced", "rfd", "audio"] + +[[bin]] +name = "wasm" +required-features = ["web"] diff --git a/index.html b/index.html new file mode 100644 index 0000000..c54a31c --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + Yew App + + + + diff --git a/src/apu.rs b/src/apu.rs index c474050..f96ba61 100644 --- a/src/apu.rs +++ b/src/apu.rs @@ -1,9 +1,5 @@ use std::iter::repeat_n; -use iced::{ - Element, Font, - widget::{column, text}, -}; use tracing::debug; macro_rules! lut { @@ -89,8 +85,10 @@ bitfield::bitfield! { struct PulseChannel { enabled: bool, duty_vol: DutyVol, + sweep: Sweep, sweep_reload: bool, + sweep_counter: u8, counter: LengthCounter, @@ -102,15 +100,17 @@ struct PulseChannel { envelope_start: bool, envelope_counter: u8, envelope_divider: u8, + extra: u16, } impl PulseChannel { - pub fn new() -> Self { + pub fn new(extra: u16) -> Self { Self { enabled: false, duty_vol: DutyVol(0), sweep: Sweep(0), sweep_reload: false, + sweep_counter: 0, counter: LengthCounter::new(), period: 0, period_timer: 0, @@ -119,6 +119,7 @@ impl PulseChannel { envelope_start: false, envelope_counter: 0, envelope_divider: 0, + extra, } } @@ -131,7 +132,7 @@ impl PulseChannel { 0x01 => { self.sweep.0 = val; self.sweep_reload = true; - }, + } 0x02 => self.period = self.period & 0x700 | (val as u16), 0x03 => { let reg = LengthTimerHigh(val); @@ -143,7 +144,7 @@ impl PulseChannel { _ => unreachable!(), } } - + fn volume(&self) -> u8 { if self.duty_vol.const_vol() { self.duty_vol.volume() @@ -151,7 +152,7 @@ impl PulseChannel { self.envelope_counter } } - + pub fn clock(&mut self) { if !self.enabled { self.sample = 0; @@ -177,7 +178,7 @@ impl PulseChannel { // TODO } pub fn cur_sample(&self) -> u8 { - if self.enabled && !self.counter.silenced() { + if self.enabled && !self.counter.silenced() && !self.sweep_silenced() { self.sample } else { 0 @@ -205,30 +206,54 @@ impl PulseChannel { } } } + fn target_period(&self) -> u16 { + let amt = self.period >> self.sweep.shift(); + if self.sweep.negate() { + self.period.saturating_sub(amt + self.extra) + } else { + self.period + amt + } + } + fn sweep_silenced(&self) -> bool { + self.period < 8 || self.target_period() > 0x7FF + } pub fn h_frame_clock(&mut self) { self.q_frame_clock(); + if self.sweep.enable() { + if self.sweep_reload { + self.sweep_counter = self.sweep.period(); + self.sweep_reload = false; + } else if self.sweep_counter == 0 { + self.sweep_counter = self.sweep.period(); + if self.period < 8 || self.target_period() < 0x7FF { + self.period = self.target_period(); + } + } else { + self.sweep_counter -= 1; + } + } } - pub fn view(&self) -> Element<'_, T> { - text!( + pub fn view(&self) -> String { + format!( "Square Channel -Evelope Volume: {0:>3} ${0:02X} +Evelope Volume: {0:>4} ${0:02X} Constant Volume: {1} Length Counter - Halted: {2} -Duty: {3:>3} ${3:02X} -Sweep - Shift: {4:>3} ${4:02X} +Duty: {3:>4} ${3:02X} +Sweep - Shift: {4:>4} ${4:02X} Sweep - Negate: {5} -Sweep - Period: {6:>3} ${6:02X} +Sweep - Period: {6:>4} ${6:02X} Sweep - Enabled: {7} -Period: {8:>3} ${8:04X} -Length Counter - Reload Value: {9:>3} ${9:04X} +Period: {8:>4} ${8:04X} +Length Counter - Reload Value: {9:>4} ${9:04X} Enabled: {10} -Timer: {11:>3} ${11:04X} -Duty Position: {12:>3} ${12:02X} -Length Counter - Counter: {13:>3} ${13:02X} -Envelope - Counter: {14:>3} ${14:02X} -Envelope - Divider: {15:>3} ${15:02X} -Output: {16:>3} ${16:02X} +Timer: {11:>4} ${11:04X} +Duty Position: {12:>4} ${12:02X} +Length Counter - Counter: {13:>4} ${13:02X} +Envelope - Counter: {14:>4} ${14:02X} +Envelope - Divider: {15:>4} ${15:02X} +Output: {16:>4} ${16:02X} ", self.duty_vol.volume(), self.duty_vol.const_vol(), @@ -242,14 +267,12 @@ Output: {16:>3} ${16:02X} 0, self.enabled, self.period_timer, - self.cur, // ? + self.cur, // ? self.counter.current, self.envelope_counter, self.envelope_divider, self.cur_sample(), ) - .font(Font::MONOSPACE) - .into() } } @@ -344,8 +367,8 @@ impl TriangleChannel { self.q_frame_clock(); } - pub fn view(&self) -> Element<'_, T> { - text!( + pub fn view(&self) -> String { + format!( "Triangle Channel Linear Counter - Reload: {0:>3} ${0:02X} Linear Counter - Halted: {1} @@ -372,8 +395,6 @@ Output: {10:>3} ${10:02X} self.reload, self.cur_sample(), ) - .font(Font::MONOSPACE) - .into() } } @@ -465,8 +486,8 @@ impl NoiseChannel { self.q_frame_clock(); } - pub fn view(&self) -> Element<'_, T> { - text!("").font(Font::MONOSPACE).into() + pub fn view(&self) -> String { + format!("") } } @@ -505,8 +526,8 @@ impl DeltaChannel { false } - pub fn view(&self) -> Element<'_, T> { - text!("").font(Font::MONOSPACE).into() + pub fn view(&self) -> String { + format!("") } } @@ -544,8 +565,8 @@ impl std::fmt::Debug for APU { impl APU { pub fn init() -> Self { Self { - pulse_1: PulseChannel::new(), - pulse_2: PulseChannel::new(), + pulse_1: PulseChannel::new(1), + pulse_2: PulseChannel::new(0), triangle: TriangleChannel::new(), noise: NoiseChannel::new(), dmc: DeltaChannel::new(), @@ -695,15 +716,26 @@ impl APU { pub fn irq_waiting(&mut self) -> bool { self.frame_counter.irq } +} - pub fn view<'s, T: 's>(&'s self) -> Element<'s, T> { - column![ - self.pulse_1.view(), - self.pulse_2.view(), - self.triangle.view(), - self.noise.view(), - self.dmc.view(), - ] - .into() +#[cfg(feature = "iced")] +mod apu_iced { + use super::*; + use iced::{ + Element, Font, + widget::{column, text}, + }; + + impl APU { + pub fn view<'s, T: 's>(&'s self) -> Element<'s, T> { + column![ + text(self.pulse_1.view()).font(Font::MONOSPACE), + text(self.pulse_2.view()).font(Font::MONOSPACE), + text(self.triangle.view()).font(Font::MONOSPACE), + text(self.noise.view()).font(Font::MONOSPACE), + text(self.dmc.view()).font(Font::MONOSPACE), + ] + .into() + } } } diff --git a/src/audio.rs b/src/bin/native/audio.rs similarity index 100% rename from src/audio.rs rename to src/bin/native/audio.rs diff --git a/src/debugger.rs b/src/bin/native/debugger.rs similarity index 96% rename from src/debugger.rs rename to src/bin/native/debugger.rs index 96b9c57..c8517f3 100644 --- a/src/debugger.rs +++ b/src/bin/native/debugger.rs @@ -23,8 +23,7 @@ use iced::{ scrollable, text, }, }; - -use crate::{Break, CycleResult, NES, PPU, mem::Mapped}; +use nes_emu::{Break, CycleResult, Mapped, NES, PPU}; #[derive(Debug, Clone)] pub struct DebuggerState { @@ -86,6 +85,8 @@ where text(format!("{val:032b}")) } +type Type = NES; + impl DebuggerState { pub fn new() -> Self { Self { @@ -106,23 +107,23 @@ impl DebuggerState { row![column![ text("Status"), row![ - labelled("A:", text(format!("{:02X}", nes.cpu.a))), - labelled("X:", text(format!("{:02X}", nes.cpu.x))), - labelled("Y:", text(format!("{:02X}", nes.cpu.y))), - labelled("PC:", text(format!("{:04X}", nes.cpu.pc))), + labelled("A:", text(format!("{:02X}", nes.cpu().a))), + labelled("X:", text(format!("{:02X}", nes.cpu().x))), + labelled("Y:", text(format!("{:02X}", nes.cpu().y))), + labelled("PC:", text(format!("{:04X}", nes.cpu().pc))), labelled("Cycle:", text(format!("{}", nes.cpu_cycle()))), - labelled("SP:", text(format!("{:02X}", nes.cpu.sp))), + labelled("SP:", text(format!("{:02X}", nes.cpu().sp))), ] .spacing(5.), row![ - labelled("P:", text(format!("{:02X}", nes.cpu.status.0))), - labelled_box("Carry", nes.cpu.status.carry()), - labelled_box("Zero", nes.cpu.status.zero()), - labelled_box("Interrupt", nes.cpu.status.interrupt_disable()), + labelled("P:", text(format!("{:02X}", nes.cpu().status.0))), + labelled_box("Carry", nes.cpu().status.carry()), + labelled_box("Zero", nes.cpu().status.zero()), + labelled_box("Interrupt", nes.cpu().status.interrupt_disable()), labelled_box("--", false), labelled_box("--", false), - labelled_box("Overflow", nes.cpu.status.overflow()), - labelled_box("Negative", nes.cpu.status.negative()), + labelled_box("Overflow", nes.cpu().status.overflow()), + labelled_box("Negative", nes.cpu().status.negative()), ] .spacing(5.), row![ @@ -246,7 +247,7 @@ impl DebuggerState { .into() } - fn run_n_clock_cycles(nes: &mut NES, n: usize) { + fn run_n_clock_cycles(nes: &mut Type, n: usize) { for _ in 0..n { if nes.run_one_clock_cycle(&Break::default()).dbg_int || nes.halted() { break; @@ -321,7 +322,7 @@ impl DebuggerState { ppu_scanline: true, ..Break::default() }, - |_, n| n.ppu.scanline == self.to_scan_line, + |_, n| n.ppu().scanline == self.to_scan_line, ), DebuggerMessage::RunFrames => Self::run_n_clock_cycles(nes, self.frames * 341 * 262), DebuggerMessage::RunBreakpoint => Self::run_until( @@ -330,7 +331,7 @@ impl DebuggerState { break_points: vec![self.breakpoint as u16], ..Break::default() }, - |_, nes| nes.cpu.pc as usize == self.breakpoint, + |_, nes| nes.cpu().pc as usize == self.breakpoint, ), // DebuggerMessage::Run => { // Self::run_until(nes, &Break { ..Break::default() }, |_, nes| nes.halted()) diff --git a/src/header_menu.rs b/src/bin/native/header_menu.rs similarity index 100% rename from src/header_menu.rs rename to src/bin/native/header_menu.rs diff --git a/src/hex_view.rs b/src/bin/native/hex_view.rs similarity index 90% rename from src/hex_view.rs rename to src/bin/native/hex_view.rs index 6e6854f..2019eb7 100644 --- a/src/hex_view.rs +++ b/src/bin/native/hex_view.rs @@ -1,42 +1,25 @@ use std::{ - fmt::{self, Display}, - sync::Arc, + fmt::{self, Display}, ops::Deref }; use iced::{ - Element, Fill, Font, Padding, Task, - advanced::graphics::text::{ - FontSystem, - cosmic_text::{ - Attrs, Family, Metrics, - fontdb::{ID, Query}, - }, - font_system, - }, - keyboard::{Key, key::Named}, - mouse::{Button, ScrollDelta}, - widget::{column, lazy, row, text}, -}; -use iced_core::{ - Clipboard, Color, Event, Layout, Length, Pixels, Point, Rectangle, Shell, Size, Text, Vector, - Widget, - layout::{Limits, Node}, - mouse::{Cursor, Interaction}, - overlay, - renderer::{Quad, Style}, - widget::{ - Operation, Tree, - tree::{State, Tag}, - }, + advanced::{layout::{Limits, Node}, overlay, renderer::{Quad, Style}, text::Renderer, widget::{tree::{State, Tag}, Operation, Tree}, Clipboard, Layout, Shell, Text, Widget}, alignment::Vertical, keyboard::{key::Named, Key}, mouse::{Button, Cursor, Interaction, ScrollDelta}, widget::{column, lazy, text}, Color, Element, Event, Fill, Font, Length, Padding, Pixels, Point, Rectangle, Size, Task, Vector }; +// use iced_core::{ +// Clipboard, Color, Event, Layout, Length, Pixels, Point, Rectangle, Shell, Size, Text, Vector, +// Widget, +// layout::{Limits, Node}, +// mouse::{Cursor, Interaction}, +// overlay, +// renderer::{Quad, Style}, +// widget::{ +// Operation, Tree, +// tree::{State, Tag}, +// }, +// }; +use nes_emu::Memory; -use crate::{PPU, mem::Mapped, ppu::PPUMMRegisters}; - -pub trait Memory { - fn peek(&self, val: usize) -> Option; - fn len(&self) -> usize; - fn edit_ver(&self) -> usize; -} +use nes_emu::{PPU, Mapped, PPUMMRegisters}; #[derive(Debug, Clone, Copy)] struct Cpu<'a>(&'a Mapped); @@ -169,12 +152,22 @@ impl HexView { } } +pub struct BufferSlice<'a>(pub &'a [u8]); + +impl Deref for BufferSlice<'_> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + self.0 + } +} + pub trait Buffer { fn peek(&self, val: usize) -> Option; fn len(&self) -> usize; } -impl Buffer for &[u8] { +impl Buffer for BufferSlice<'_> { fn peek(&self, val: usize) -> Option { self.get(val).copied() } @@ -193,7 +186,7 @@ impl Buffer for M { } } -pub fn hex_editor(raw: B) -> HexEditor { +pub fn hex_editor(raw: B) -> HexEditor { HexEditor { val: raw, on_edit: None, @@ -209,7 +202,7 @@ pub struct HexEdit { new_value: u8, } -pub struct HexEditor { +pub struct HexEditor { val: B, font_size: Option, font: Option, @@ -218,7 +211,7 @@ pub struct HexEditor { impl HexEditor where - R: iced_core::text::Renderer, + R: Renderer, { pub fn font(mut self, font: R::Font) -> Self { self.font = Some(font); @@ -228,7 +221,7 @@ where impl HexEditor where - R: iced_core::text::Renderer, + R: Renderer, { fn value_bounds(&self, renderer: &R, layout: Layout<'_>) -> Rectangle { let size = self.font_size.unwrap_or(renderer.default_size()); @@ -296,7 +289,7 @@ const LINE_HEIGHT: f32 = 1.3; impl Widget for HexEditor where - R: iced_core::text::Renderer, + R: Renderer, { fn tag(&self) -> Tag { Tag::of::() @@ -354,10 +347,10 @@ where size, line_height: size.into(), font, - align_x: iced_core::text::Alignment::Left, - align_y: iced_core::alignment::Vertical::Top, - shaping: iced_core::text::Shaping::Basic, - wrapping: iced_core::text::Wrapping::None, + align_x: iced::advanced::text::Alignment::Left, + align_y: Vertical::Top, + shaping: iced::advanced::text::Shaping::Basic, + wrapping: iced::advanced::text::Wrapping::None, hint_factor: None, }, pos, @@ -444,10 +437,10 @@ where size, line_height: size.into(), font, - align_x: iced_core::text::Alignment::Left, - align_y: iced_core::alignment::Vertical::Top, - shaping: iced_core::text::Shaping::Basic, - wrapping: iced_core::text::Wrapping::None, + align_x: iced::advanced::text::Alignment::Left, + align_y: Vertical::Top, + shaping: iced::advanced::text::Shaping::Basic, + wrapping: iced::advanced::text::Wrapping::None, hint_factor: None, }, pos, diff --git a/src/main.rs b/src/bin/native/main.rs similarity index 97% rename from src/main.rs rename to src/bin/native/main.rs index dd1bb91..349c256 100644 --- a/src/main.rs +++ b/src/bin/native/main.rs @@ -19,14 +19,19 @@ use iced::{ }; use nes_emu::{ Break, NES, - audio::Audio, - debugger::{DbgImage, DebuggerMessage, DebuggerState, dbg_image}, - header_menu::header_menu, - hex_view::{HexEvent, HexView}, - resize_watcher::resize_watcher, }; use tokio::{io::AsyncWriteExt, runtime::Runtime}; use tracing_subscriber::EnvFilter; +mod debugger; +use debugger::{DbgImage, DebuggerMessage, DebuggerState, dbg_image}; +mod resize_watcher; +use resize_watcher::resize_watcher; +mod header_menu; +use header_menu::header_menu; +mod hex_view; +use hex_view::{HexEvent, HexView}; +mod audio; +use audio::Audio; // const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "even_odd.nes"); // const ROM_FILE: &str = concat!(env!("ROM_DIR"), "/", "crc_check.nes"); @@ -151,6 +156,7 @@ impl Emulator { fn new() -> (Self, Task) { let mut nes = nes_emu::NES::load_nes_file(ROM_FILE).expect("Failed to load nes file"); nes.reset(); + nes.debug_log_mut().enable(); let (win, task) = iced::window::open(Settings { min_size: None, ..Settings::default() @@ -234,7 +240,10 @@ impl Emulator { .and_then(|p| { Task::future(async move { // println!("Opening: {}", p.path().display()); - NES::async_load_nes_file(p.path()).await.ok() + NES::async_load_nes_file(p.path()).await.ok().map(|mut nes| { + nes.debug_log_mut().enable(); + nes + }) }) }) .and_then(|n| Task::done(Message::OpenRom(n))); @@ -375,7 +384,7 @@ impl Emulator { && !self.nes.halted() { count += 1; - if count > 100000 { + if count > 90_000 { println!("Loop overran..."); break; } diff --git a/src/resize_watcher.rs b/src/bin/native/resize_watcher.rs similarity index 100% rename from src/resize_watcher.rs rename to src/bin/native/resize_watcher.rs diff --git a/src/bin/wasm/main.rs b/src/bin/wasm/main.rs new file mode 100644 index 0000000..d54480a --- /dev/null +++ b/src/bin/wasm/main.rs @@ -0,0 +1,300 @@ +use std::sync::{ + Arc, Mutex, + atomic::{AtomicBool, Ordering}, +}; + +use log::info; +use nes_emu::{Break, NES}; +#[cfg(not(target_arch = "wasm32"))] +use tracing_subscriber::EnvFilter; +use web_sys::{ + js_sys::{Function, Uint8Array}, wasm_bindgen::{closure::Closure, Clamped, JsValue, UnwrapThrowExt}, window, AudioBuffer, AudioBufferOptions, AudioContext, AudioContextOptions, AudioContextState, CanvasRenderingContext2d, HtmlButtonElement, HtmlCanvasElement, HtmlInputElement, ImageBitmap, ImageData, KeyboardEvent +}; + +const DEFAULT_ROM: &[u8] = include_bytes!(concat!( + env!("ROM_DIR"), + "/input_test.nes" // TODO: select default rom +)); + +pub fn main() { + #[cfg(target_arch = "wasm32")] + { + console_log::init().expect("Initialize logger"); + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + } + #[cfg(not(target_arch = "wasm32"))] + tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .init(); + + let win = window().expect_throw("Window is undefined"); + let doc = win.document().expect_throw("Document is undefined"); + let canvas = doc + .get_element_by_id("main_view") + .expect_throw("Failed to get canvas element"); + let canvas = HtmlCanvasElement::from(JsValue::from(canvas)); + + let ctx = + CanvasRenderingContext2d::from(JsValue::from(canvas.get_context("2d").unwrap().unwrap())); + let cl = Arc::new(Closure::new(move |image| { + ctx.reset(); + ctx.draw_image_with_image_bitmap(&ImageBitmap::from(image), 0., 0.) + .expect_throw("Failed to draw image"); + })); + let audio_ctx_opts = AudioContextOptions::new(); + audio_ctx_opts.set_sample_rate(60. * 3723.); + // audio_ctx_opts.set_ + let audio = AudioContext::new_with_context_options(&audio_ctx_opts) + .expect_throw("Failed to create audio context"); + let _ = audio.suspend().expect_throw("Failed to suspend AudioCtx"); + + const BUFFER_SIZE: usize = 1 << 10; + const SAMPLE_RATE: f64 = 60. * 3723.; + let audio_buffer_opts = AudioBufferOptions::new(BUFFER_SIZE as u32, SAMPLE_RATE as f32); + audio_buffer_opts.set_number_of_channels(1); + // let audio_buffer = + // AudioBuffer::new(&audio_buffer_opts).expect_throw("Failed to create audio buffer"); + // let mut raw_buf = [0.; BUFFER_SIZE]; + // for i in 0..raw_buf.len() { + // raw_buf[i] = (i as f32 / 200.).sin() + // } + // audio_buffer + // .copy_to_channel(&raw_buf, 0) + // .expect_throw("Failed to copy audio data"); + let gain_node = audio + .create_gain() + .expect_throw("Failed to create gain node"); + gain_node.set_channel_count(1); + gain_node.gain().set_value(0.01); + gain_node + .connect_with_audio_node_and_output(&audio.destination(), 0) + .expect_throw("Failed to connect to audio destination"); + // gain_node + // .connect_with_audio_node_and_output(&audio.destination(), 1) + // .expect_throw("Failed to connect to audio destination 2"); + let delay_node = audio + .create_delay() + .expect_throw("Failed to create delay node"); + delay_node.set_channel_count(1); + delay_node.delay_time().set_value(0.); + delay_node + .connect_with_audio_node(&gain_node) + .expect_throw("Failed to connect to audio destination"); + // source_node.start_with_when(when) + + let nes = Arc::new(Mutex::new({ + let mut n = NES::load_nes_file_mem(DEFAULT_ROM).unwrap(); + n.reset(); + + n + })); + // let timeout = Arc::new(Mutex::new(None as Option)); + let poisoned = Arc::new(AtomicBool::new(false)); + // let timeout_cpy = timeout.clone(); + + { + let audio = audio.clone(); + let el = doc.get_element_by_id("pause").unwrap(); + let element = HtmlButtonElement::from(JsValue::from(el.clone())); + let f: Closure = Closure::new(move |_e| { + if audio.state() == AudioContextState::Suspended { + let _ = audio.resume(); + element.set_inner_text("Pause"); + } else { + let _ = audio.suspend(); + element.set_inner_text("Play"); + } + }); + el.add_event_listener_with_callback("click", &Function::from(f.into_js_value())) + .expect_throw("Failed to setup pause callback"); + } + { + let nes = nes.clone(); + let poisoned = poisoned.clone(); + let element = HtmlInputElement::from(JsValue::from(doc.get_element_by_id("file").unwrap())); + element.set_accept(".nes"); + let load: Closure = Closure::new(move |v| { + let v = Uint8Array::from(v); + // info!("{v:?}"); + let new_emu = NES::load_nes_file_mem(&v.to_vec()).expect("Failed to load nes file"); + if poisoned.swap(true, Ordering::AcqRel) == false { + let mut nes = nes.lock().unwrap(); + *nes = new_emu; + nes.power_cycle(); + if poisoned.swap(false, Ordering::AcqRel) == true {} + } + }); + let f: Closure = Closure::new(move |_e| { + if let Some(file) = element.files().and_then(|l| l.get(0)) { + let _ = file.bytes().then(&load); + } + }); + doc.get_element_by_id("load") + .unwrap() + .add_event_listener_with_callback("click", &Function::from(f.into_js_value())) + .expect_throw("Failed to setup pause callback"); + } + { + let nes = nes.clone(); + let poisoned = poisoned.clone(); + let f: Closure = Closure::new(move |e| { + if poisoned.swap(true, Ordering::AcqRel) == false { + let e = KeyboardEvent::from(e); + let key = e.key(); + // info!("{}", key); + if key == "ArrowLeft" { + nes.lock().unwrap().controller_1().set_left(true); + } else if key == "ArrowRight" { + nes.lock().unwrap().controller_1().set_right(true); + } else if key == "ArrowUp" { + nes.lock().unwrap().controller_1().set_up(true); + } else if key == "ArrowDown" { + nes.lock().unwrap().controller_1().set_down(true); + } else if key == "a" || key == "A" { + nes.lock().unwrap().controller_1().set_a(true); + } else if key == "s" || key == "S" { + nes.lock().unwrap().controller_1().set_b(true); + } else if key == "q" || key == "Q" { + nes.lock().unwrap().controller_1().set_start(true); + } else if key == "w" || key == "W" { + nes.lock().unwrap().controller_1().set_select(true); + } + if poisoned.swap(false, Ordering::AcqRel) == true {} + } + }); + win.set_onkeydown(Some(&Function::from(f.into_js_value()))); + } + { + let nes = nes.clone(); + let poisoned = poisoned.clone(); + let f: Closure = Closure::new(move |e| { + if poisoned.swap(true, Ordering::AcqRel) == false { + let e = KeyboardEvent::from(e); + let key = e.key(); + // info!("{}", key); + if key == "ArrowLeft" { + nes.lock().unwrap().controller_1().set_left(false); + } else if key == "ArrowRight" { + nes.lock().unwrap().controller_1().set_right(false); + } else if key == "ArrowUp" { + nes.lock().unwrap().controller_1().set_up(false); + } else if key == "ArrowDown" { + nes.lock().unwrap().controller_1().set_down(false); + } else if key == "a" || key == "A" { + nes.lock().unwrap().controller_1().set_a(false); + } else if key == "s" || key == "S" { + nes.lock().unwrap().controller_1().set_b(false); + } else if key == "q" || key == "Q" { + nes.lock().unwrap().controller_1().set_start(false); + } else if key == "w" || key == "W" { + nes.lock().unwrap().controller_1().set_select(false); + } + if poisoned.swap(false, Ordering::AcqRel) == true {} + } + }); + win.set_onkeyup(Some(&Function::from(f.into_js_value()))); + } + + // let timeline = win.document().unwrap().timeline(); + let mut last_frame = audio.current_time(); + let mut raw_audio_buffer = [0f32; BUFFER_SIZE]; + let mut cur_pos = 0; + let mut cur_total = BUFFER_SIZE; // Start time in samples, set to buffer size... + let period = Arc::new(Mutex::new(None as Option)); + let period_cl = period.clone(); + let periodic: Closure = Closure::new(move |_v| { + let win = window().expect_throw("Window is undefined"); + const FRAME_TIME: f64 = 1. / 60.; + let mut cancel = false; + if last_frame + FRAME_TIME > audio.current_time() { + last_frame += FRAME_TIME; + if audio.state() == AudioContextState::Running { + if poisoned.swap(true, Ordering::AcqRel) { + cancel = true; + // if let Some(_id) = timeout_cpy.lock().ok().and_then(|v| *v) { + // win.clear_interval_with_handle(id); + // win.cancel_animation_frame(id); + info!("Cleared interval due to poison"); + // } else { + // info!("Not yet set id"); + // } + } else { + let mut n = nes.lock().unwrap(); + // info!("Running frame"); + let mut count = 0; + while !n.halted() && !n.run_one_clock_cycle(&Break::default()).ppu_frame { + count += 1; + if count > 90_000 { + info!("Loop overran"); + break; + } + } + info!("New samples: {}", n.apu().get_frame_samples().len()); + // for s in n.apu().get_frame_samples() { + // // raw_audio_buffer[cur_pos] = ((*s as f32) - 127.5) / 128.; + // raw_audio_buffer[cur_pos] = (*s as f32) / 256.; + // cur_pos += 1; + // if cur_pos == BUFFER_SIZE { + // cur_pos = 0; + // cur_total += BUFFER_SIZE; + // let audio_buffer = AudioBuffer::new(&audio_buffer_opts) + // .expect_throw("Failed to create audio buffer"); + // audio_buffer + // .copy_to_channel(&raw_audio_buffer, 0) + // .expect_throw("Failed to copy audio data"); + // // info!("S: {:?}", audio_buffer.get_channel_data(0)); + + // let source_node = audio + // .create_buffer_source() + // .expect_throw("Failed to create buffer source"); + // source_node.set_loop(true); + // source_node.set_buffer(Some(&audio_buffer)); + // source_node + // .connect_with_audio_node(&gain_node) + // .expect_throw("Failed to connect to gain node"); + // source_node + // .start_with_when((cur_total as f64) / SAMPLE_RATE) + // .expect_throw("Failed to start source_node"); + // info!( + // "At {cur_total} samples, {:02.04}s ahead", + // (cur_total as f64) / SAMPLE_RATE - audio.current_time() + // ); + // // TODO: create and play audio node + // } + // } + n.apu_mut().reset_frame_samples(); // Discard audio samples + // info!("Completed Frame in {} cycles", count); + let data = Clamped(n.ppu().render_buffer.raw_image()); + // info!("Creating bitmap"); + let image = ImageData::new_with_u8_clamped_array(data, 256) + .expect_throw("Image data could not be created"); + + let data = win + .create_image_bitmap_with_image_data(&image) + .expect_throw("Bitmap could not be created"); + + let _ = data.then(&cl); + drop(n); + if !poisoned.swap(false, Ordering::AcqRel) { + panic!("Poisoned logic invalid"); + } + } + } + } + if !cancel { + win.request_animation_frame(period_cl.lock().unwrap().as_ref().unwrap()) + .expect_throw("Failed to setup animation frame"); + } + }); + let js = Function::from(periodic.into_js_value()); + let win = window().expect_throw("Window is undefined"); + // let timeout_id = win + // .set_interval_with_callback_and_timeout_and_arguments_0(&Function::from(js), 16) + // .expect_throw("Failed to setup timeout"); + // let timeout_id = + win + .request_animation_frame(&js) + .expect_throw("Failed to setup animation frame"); + *period.lock().unwrap() = Some(js); + // *timeout.lock().unwrap() = Some(timeout_id); +} diff --git a/src/debug.rs b/src/debug.rs index f2786c3..5fc55e1 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -2,6 +2,7 @@ use std::num::NonZeroUsize; #[derive(Debug, Clone)] pub struct DebugLog { + enabled: bool, current: String, history: Vec, max_history: Option, @@ -11,6 +12,7 @@ pub struct DebugLog { impl DebugLog { pub fn new() -> Self { Self { + enabled: false, current: String::new(), history: vec![], max_history: None, @@ -47,25 +49,41 @@ impl DebugLog { pub fn pop(&mut self) -> Option { self.history.pop() } + + pub fn enable(&mut self) { + self.enabled = true; + } } impl std::fmt::Write for DebugLog { fn write_str(&mut self, s: &str) -> std::fmt::Result { - let tmp = self.current.write_str(s); - self.rotate(); - tmp + if self.enabled { + let tmp = self.current.write_str(s); + self.rotate(); + tmp + } else { + Ok(()) + } } fn write_char(&mut self, c: char) -> std::fmt::Result { - let tmp = self.current.write_char(c); - self.rotate(); - tmp + if self.enabled { + let tmp = self.current.write_char(c); + self.rotate(); + tmp + } else { + Ok(()) + } } fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::fmt::Result { - let tmp = self.current.write_fmt(args); - self.rotate(); - tmp + if self.enabled { + let tmp = self.current.write_fmt(args); + self.rotate(); + tmp + } else { + Ok(()) + } } } diff --git a/src/lib.rs b/src/lib.rs index 3687480..a8c99ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,18 +2,19 @@ mod apu; mod controllers; mod cpu; pub mod debug; -pub mod debugger; -pub mod header_menu; -pub mod hex_view; +// pub mod debugger; +// pub mod header_menu; +// pub mod hex_view; mod mem; mod ppu; -pub mod resize_watcher; #[cfg(test)] mod test_roms; -pub mod audio; +pub use mem::{Memory, Mapped}; -pub use ppu::{Color, PPU, RenderBuffer}; -use tokio::io::AsyncReadExt as _; +pub use ppu::{Color, PPU, RenderBuffer, PPUMMRegisters}; +pub use cpu::{Cpu, CycleResult, CPUMMRegisters}; +// #[cfg(not(target_arch = "wasm32"))] +// use tokio::io::AsyncReadExt as _; use std::{fs::File, io::Read, path::Path}; @@ -22,9 +23,9 @@ use thiserror::Error; use crate::{ apu::APU, controllers::{ControllerState, Controllers}, - cpu::{CPUMMRegisters, ClockState, Cpu, CycleResult, DmaState}, + cpu::{ClockState, DmaState}, debug::DebugLog, - mem::{CpuMem, Mapped, PpuMem}, + mem::{CpuMem, PpuMem}, }; #[derive(Error, Debug)] @@ -115,13 +116,18 @@ impl std::fmt::Debug for NES { } impl NES { + #[cfg(feature = "fs")] pub fn load_nes_file(file: impl AsRef) -> Result { let mut raw = Vec::new(); File::open(file)?.read_to_end(&mut raw)?; Self::load_nes_file_mem(&raw) } + // #[cfg(not(target_arch = "wasm32"))] + #[cfg(all(feature = "fs", feature = "tokio"))] pub async fn async_load_nes_file(file: impl AsRef) -> Result { + use tokio::io::AsyncReadExt as _; + let mut raw = Vec::new(); tokio::fs::File::open(file) .await? @@ -342,6 +348,10 @@ impl NES { &self.ppu.render_buffer } + pub fn cpu(&self) -> &Cpu { + &self.cpu + } + pub fn ppu(&self) -> &PPU { &self.ppu } diff --git a/src/mem.rs b/src/mem.rs index b0b3482..4aa4f94 100644 --- a/src/mem.rs +++ b/src/mem.rs @@ -1,10 +1,16 @@ use std::{fmt, sync::Arc}; use crate::{ - CPUMMRegisters, PPU, apu::APU, controllers::Controllers, cpu::DmaState, hex_view::Memory, + CPUMMRegisters, PPU, apu::APU, controllers::Controllers, cpu::DmaState, ppu::PPUMMRegisters, }; +pub trait Memory { + fn peek(&self, val: usize) -> Option; + fn len(&self) -> usize; + fn edit_ver(&self) -> usize; +} + #[derive(Debug, Clone)] pub enum Value { Value(u8), diff --git a/src/ppu.rs b/src/ppu.rs index ecd17f1..8c76e66 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -1,11 +1,6 @@ use std::fmt; use bytes::{Bytes, BytesMut}; -use iced::{ - Point, Size, - advanced::graphics::geometry::Renderer, - widget::canvas::{Fill, Frame}, -}; use crate::mem::{Mapped, PpuMem, Value}; @@ -16,12 +11,6 @@ pub struct Color { pub b: u8, } -impl Into for Color { - fn into(self) -> Fill { - iced::Color::from_rgb8(self.r, self.g, self.b).into() - } -} - impl fmt::Display for Color { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "#{:02X}{:02X}{:02X}", self.r, self.g, self.b) @@ -66,6 +55,10 @@ impl RenderBuffer { Bytes::copy_from_slice(&self.raw_rgba) } + pub fn raw_image(&self) -> &[u8] { + &self.raw_rgba + } + pub fn assert_eq(&self, other: &Self) { // if self.buffer != other.buffer { for y in 0..H { @@ -1126,238 +1119,6 @@ impl PPU { pub fn oam_edit_ver(&self) -> usize { self.oam.edit_ver } - - pub fn render_name_table(&self, mem: &Mapped, frame: &mut Frame) { - for y in 0..60 { - for x in 0..64 { - let row = y % 30; - let col = x % 32; - let off = 0x2000 + 0x400 * (y / 30 * 2 + x / 32); - let name = mem.peek_ppu((off + col + row * 32) as u16).unwrap() as u16 * 16 - + if self.background.second_pattern { - 0x1000 - } else { - 0 - }; - let attr = mem - .peek_ppu((col / 4 + row / 4 * 8 + 0x3C0 + off) as u16) - .unwrap(); - // attr << (((col & 1) << 1) | ((row & 1) << 0)) * 2 - // let h_off = ((self.pixel - 1) / 16) % 2; - // let v_off = (self.scanline / 16) % 2; - // let off = v_off * 4 + h_off * 2; - let palette = (attr >> (((col & 2) << 0) | ((row & 2) << 1))) & 0x3; - for y_off in 0..8 { - let low = mem.peek_ppu(name + y_off).unwrap(); - let high = mem.peek_ppu(name + y_off + 8).unwrap(); - for bit in 0..8 { - frame.fill_rectangle( - Point::new( - x as f32 * 8. + 8. - bit as f32, - y as f32 * 8. + y_off as f32, - ), - Size::new(1., 1.), - match (low & (1 << bit) != 0, high & (1 << bit) != 0) { - (false, false) => self.palette.color(0), - (true, false) => self.palette.color(1 + 4 * palette), - (false, true) => self.palette.color(2 + 4 * palette), - (true, true) => self.palette.color(3 + 4 * palette), - // (false, false) => Color { r: 0, g: 0, b: 0 }, - // (true, false) => Color { - // r: 64, - // g: 64, - // b: 64, - // }, - // (false, true) => Color { - // r: 128, - // g: 128, - // b: 128, - // }, - // (true, true) => Color { - // r: 255, - // g: 255, - // b: 255, - // }, - }, - ); - } - } - // for - // let pat = mem.peek(); - } - } - } - pub fn name_cursor_info(&self, mem: &Mapped, cursor: Point) -> Option { - let x = (cursor.x / 8.) as usize; - let y = (cursor.y / 8.) as usize; - if x < 64 && y < 60 { - let row = y % 30; - let col = x % 32; - let off = 0x2000 + 0x400 * (y / 30 * 2 + x / 32); - let name = mem.peek_ppu((off + col + row * 32) as u16).unwrap() as usize; - let attr = mem - .peek_ppu((col / 4 + row / 4 * 8 + 0x3C0 + off) as u16) - .unwrap(); - Some(format!( - "Row, Column: {}, {} -X, Y: {}, {} -Tilemap address: ${:04X} - -Tile Index: ${:02X} -Tile Address (PPU): ${:04X} -Tile Address (CHR): ${:04X} - -Palette Index {} -Palette Address ${:04X} - -Attribute Address ${:04X} -Attribute data: ${:02X} -", - row, - col, - col * 8, - row * 8, - off + col + row * 32, - name, - name * 16 - + if self.background.second_pattern { - 0x1000 - } else { - 0 - }, - name * 16 - + if self.background.second_pattern { - 0x1000 - } else { - 0 - }, - (attr >> (((col & 1) << 1) | ((row & 1) << 2))) & 0x3, - ((attr >> (((col & 1) << 1) | ((row & 1) << 2))) & 0x3) as usize * 4 + 0x3F00, - col / 4 + row / 4 * 8 + 0x3C0 + off, - attr, - )) - } else { - None - } - } - - pub fn render_pattern_tables(&self, mem: &Mapped, frame: &mut Frame) { - for y in 0..16 { - for x in 0..16 { - let name = (y * 16 + x) * 16; - for y_off in 0..8 { - let low = mem.peek_ppu(name + y_off).unwrap(); - let high = mem.peek_ppu(name + y_off + 8).unwrap(); - for bit in 0..8 { - frame.fill_rectangle( - Point::new( - x as f32 * 8. + 8. - bit as f32, - y as f32 * 8. + y_off as f32, - ), - Size::new(1., 1.), - match (low & (1 << bit) != 0, high & (1 << bit) != 0) { - (false, false) => Color { r: 0, g: 0, b: 0 }, - (true, false) => Color { - r: 64, - g: 64, - b: 64, - }, - (false, true) => Color { - r: 128, - g: 128, - b: 128, - }, - (true, true) => Color { - r: 255, - g: 255, - b: 255, - }, - }, - ); - } - } - } - } - - for y in 0..16 { - for x in 0..16 { - let name = (y * 16 + x) * 16; - for y_off in 0..8 { - let low = mem.peek_ppu(name + y_off + 0x1000).unwrap(); - let high = mem.peek_ppu(name + y_off + 8 + 0x1000).unwrap(); - for bit in 0..8 { - frame.fill_rectangle( - Point::new( - x as f32 * 8. + 8. - bit as f32, - y as f32 * 8. + y_off as f32 + 130., - ), - Size::new(1., 1.), - match (low & (1 << bit) != 0, high & (1 << bit) != 0) { - (false, false) => Color { r: 0, g: 0, b: 0 }, - (true, false) => Color { - r: 64, - g: 64, - b: 64, - }, - (false, true) => Color { - r: 128, - g: 128, - b: 128, - }, - (true, true) => Color { - r: 255, - g: 255, - b: 255, - }, - }, - ); - } - } - // for - // let pat = mem.peek(); - } - } - } - pub fn pattern_cursor_info(&self, cursor: Point) -> Option { - let x = (cursor.x / 8.) as usize; - let y = (cursor.y / 8.) as usize; - if x < 16 && y < 32 { - Some(format!( - "Tile address (PPU): {:04X}\nTile address (CHR): {:04X}\nIndex: {:02X}", - (y * 16 + x) * 16, - (y * 16 + x) * 16, - ((y % 16) * 16 + x), - )) - } else { - None - } - } - - pub fn render_palette(&self, frame: &mut Frame) { - for y in 0..8 { - for x in 0..4 { - frame.fill_rectangle( - Point::new(x as f32 * 10., y as f32 * 10.), - Size::new(10., 10.), - self.palette.colors[(self.palette.ram[x + y * 4] & 0x3F) as usize], - ); - } - } - } - pub fn palette_cursor_info(&self, cursor: Point) -> Option { - let x = (cursor.x / 10.) as usize; - let y = (cursor.y / 10.) as usize; - if x < 4 && y < 8 { - Some(format!( - "Index: {:02X}\nValue: {:02X}\nColor code: {}", - x + y * 4, - self.palette.ram[x + y * 4] & 0x3F, - self.palette.colors[(self.palette.ram[x + y * 4] & 0x3F) as usize], - )) - } else { - None - } - } } #[cfg(test)] @@ -1414,3 +1175,253 @@ mod tests { assert_eq!(ppu.background.w, false); } } + +#[cfg(feature = "iced")] +mod ppu_iced { + use super::*; + use iced::{ + Point, Size, + advanced::graphics::geometry::Renderer, + widget::canvas::{Fill, Frame}, + }; + + impl Into for Color { + fn into(self) -> Fill { + iced::Color::from_rgb8(self.r, self.g, self.b).into() + } + } + + impl PPU { + pub fn render_name_table(&self, mem: &Mapped, frame: &mut Frame) { + for y in 0..60 { + for x in 0..64 { + let row = y % 30; + let col = x % 32; + let off = 0x2000 + 0x400 * (y / 30 * 2 + x / 32); + let name = mem.peek_ppu((off + col + row * 32) as u16).unwrap() as u16 * 16 + + if self.background.second_pattern { + 0x1000 + } else { + 0 + }; + let attr = mem + .peek_ppu((col / 4 + row / 4 * 8 + 0x3C0 + off) as u16) + .unwrap(); + // attr << (((col & 1) << 1) | ((row & 1) << 0)) * 2 + // let h_off = ((self.pixel - 1) / 16) % 2; + // let v_off = (self.scanline / 16) % 2; + // let off = v_off * 4 + h_off * 2; + let palette = (attr >> (((col & 2) << 0) | ((row & 2) << 1))) & 0x3; + for y_off in 0..8 { + let low = mem.peek_ppu(name + y_off).unwrap(); + let high = mem.peek_ppu(name + y_off + 8).unwrap(); + for bit in 0..8 { + frame.fill_rectangle( + Point::new( + x as f32 * 8. + 8. - bit as f32, + y as f32 * 8. + y_off as f32, + ), + Size::new(1., 1.), + match (low & (1 << bit) != 0, high & (1 << bit) != 0) { + (false, false) => self.palette.color(0), + (true, false) => self.palette.color(1 + 4 * palette), + (false, true) => self.palette.color(2 + 4 * palette), + (true, true) => self.palette.color(3 + 4 * palette), + // (false, false) => Color { r: 0, g: 0, b: 0 }, + // (true, false) => Color { + // r: 64, + // g: 64, + // b: 64, + // }, + // (false, true) => Color { + // r: 128, + // g: 128, + // b: 128, + // }, + // (true, true) => Color { + // r: 255, + // g: 255, + // b: 255, + // }, + }, + ); + } + } + // for + // let pat = mem.peek(); + } + } + } + pub fn name_cursor_info(&self, mem: &Mapped, cursor: Point) -> Option { + let x = (cursor.x / 8.) as usize; + let y = (cursor.y / 8.) as usize; + if x < 64 && y < 60 { + let row = y % 30; + let col = x % 32; + let off = 0x2000 + 0x400 * (y / 30 * 2 + x / 32); + let name = mem.peek_ppu((off + col + row * 32) as u16).unwrap() as usize; + let attr = mem + .peek_ppu((col / 4 + row / 4 * 8 + 0x3C0 + off) as u16) + .unwrap(); + Some(format!( + "Row, Column: {}, {} +X, Y: {}, {} +Tilemap address: ${:04X} + +Tile Index: ${:02X} +Tile Address (PPU): ${:04X} +Tile Address (CHR): ${:04X} + +Palette Index {} +Palette Address ${:04X} + +Attribute Address ${:04X} +Attribute data: ${:02X} +", + row, + col, + col * 8, + row * 8, + off + col + row * 32, + name, + name * 16 + + if self.background.second_pattern { + 0x1000 + } else { + 0 + }, + name * 16 + + if self.background.second_pattern { + 0x1000 + } else { + 0 + }, + (attr >> (((col & 1) << 1) | ((row & 1) << 2))) & 0x3, + ((attr >> (((col & 1) << 1) | ((row & 1) << 2))) & 0x3) as usize * 4 + 0x3F00, + col / 4 + row / 4 * 8 + 0x3C0 + off, + attr, + )) + } else { + None + } + } + + pub fn render_pattern_tables(&self, mem: &Mapped, frame: &mut Frame) { + for y in 0..16 { + for x in 0..16 { + let name = (y * 16 + x) * 16; + for y_off in 0..8 { + let low = mem.peek_ppu(name + y_off).unwrap(); + let high = mem.peek_ppu(name + y_off + 8).unwrap(); + for bit in 0..8 { + frame.fill_rectangle( + Point::new( + x as f32 * 8. + 8. - bit as f32, + y as f32 * 8. + y_off as f32, + ), + Size::new(1., 1.), + match (low & (1 << bit) != 0, high & (1 << bit) != 0) { + (false, false) => Color { r: 0, g: 0, b: 0 }, + (true, false) => Color { + r: 64, + g: 64, + b: 64, + }, + (false, true) => Color { + r: 128, + g: 128, + b: 128, + }, + (true, true) => Color { + r: 255, + g: 255, + b: 255, + }, + }, + ); + } + } + } + } + + for y in 0..16 { + for x in 0..16 { + let name = (y * 16 + x) * 16; + for y_off in 0..8 { + let low = mem.peek_ppu(name + y_off + 0x1000).unwrap(); + let high = mem.peek_ppu(name + y_off + 8 + 0x1000).unwrap(); + for bit in 0..8 { + frame.fill_rectangle( + Point::new( + x as f32 * 8. + 8. - bit as f32, + y as f32 * 8. + y_off as f32 + 130., + ), + Size::new(1., 1.), + match (low & (1 << bit) != 0, high & (1 << bit) != 0) { + (false, false) => Color { r: 0, g: 0, b: 0 }, + (true, false) => Color { + r: 64, + g: 64, + b: 64, + }, + (false, true) => Color { + r: 128, + g: 128, + b: 128, + }, + (true, true) => Color { + r: 255, + g: 255, + b: 255, + }, + }, + ); + } + } + // for + // let pat = mem.peek(); + } + } + } + pub fn pattern_cursor_info(&self, cursor: Point) -> Option { + let x = (cursor.x / 8.) as usize; + let y = (cursor.y / 8.) as usize; + if x < 16 && y < 32 { + Some(format!( + "Tile address (PPU): {:04X}\nTile address (CHR): {:04X}\nIndex: {:02X}", + (y * 16 + x) * 16, + (y * 16 + x) * 16, + ((y % 16) * 16 + x), + )) + } else { + None + } + } + + pub fn render_palette(&self, frame: &mut Frame) { + for y in 0..8 { + for x in 0..4 { + frame.fill_rectangle( + Point::new(x as f32 * 10., y as f32 * 10.), + Size::new(10., 10.), + self.palette.colors[(self.palette.ram[x + y * 4] & 0x3F) as usize], + ); + } + } + } + pub fn palette_cursor_info(&self, cursor: Point) -> Option { + let x = (cursor.x / 10.) as usize; + let y = (cursor.y / 10.) as usize; + if x < 4 && y < 8 { + Some(format!( + "Index: {:02X}\nValue: {:02X}\nColor code: {}", + x + y * 4, + self.palette.ram[x + y * 4] & 0x3F, + self.palette.colors[(self.palette.ram[x + y * 4] & 0x3F) as usize], + )) + } else { + None + } + } + } +} diff --git a/src/test_roms/apu_pulse_1.s b/src/test_roms/apu_pulse_1.s index b0c6587..c5b6a0c 100644 --- a/src/test_roms/apu_pulse_1.s +++ b/src/test_roms/apu_pulse_1.s @@ -2,8 +2,8 @@ .include "audio_inp.s" zp_res TIMER_LOW -; zp_res TIMER_LOW -; zp_res TIMER_LOW +zp_res SWEEP +zp_res DLCV ; zp_res TIMER_LOW reset: @@ -14,10 +14,12 @@ reset: lda #$01 sta SNDCHN - lda #$AF ; Duty 2, LC halted, evelope enabled, volume = F + lda #$BF ; Duty 2, LC halted, evelope enabled, volume = F sta PULSE_CH1_DLCV + sta DLCV lda #$7F ; sta PULSE_CH1_SWEEP + sta SWEEP lda #$6F sta PULSE_CH1_TLOW sta TIMER_LOW @@ -43,21 +45,32 @@ reset: write_char_x ':' load_ppu_addr $2061 - ; write_char_x 't' - ; write_char_x 'i' - ; write_char_x 'm' - ; write_char_x 'e' - ; write_char_x 'r' - ; write_char_x ' ' - ; write_char_x 'h' - ; write_char_x 'o' - ; write_char_x 'w' - ; write_char_x ':' + write_char_x 's' + write_char_x 'w' + write_char_x 'e' + write_char_x 'e' + write_char_x 'p' + write_char_x ':' + + load_ppu_addr $2081 + write_char_x 'd' + write_char_x 'l' + write_char_x 'c' + write_char_x 'v' + write_char_x ':' load_ppu_addr $204C lda TIMER_LOW jsr write_hex_a + load_ppu_addr $206C + lda SWEEP + jsr write_hex_a + + load_ppu_addr $208C + lda DLCV + jsr write_hex_a + jsr enable_rendering loop: jmp loop @@ -67,28 +80,83 @@ loop: audio_nmi: EOR JOY_PREV STA JOY_PREV + lda JOYTEMP and #JOY_UP_MASK and JOY_PREV - beq next_1 + beq down load_ppu_addr $204C lda #$01 adc TIMER_LOW sta TIMER_LOW sta PULSE_CH1_TLOW jsr write_hex_a -next_1: + +down: lda JOYTEMP and #JOY_DOWN_MASK and JOY_PREV - beq next_2 + beq left load_ppu_addr $204C lda #$FF adc TIMER_LOW sta TIMER_LOW sta PULSE_CH1_TLOW jsr write_hex_a -next_2: + +left: + lda JOYTEMP + and #JOY_LEFT_MASK + and JOY_PREV + beq right + load_ppu_addr $206C + lda #$FF + adc SWEEP + sta SWEEP + sta PULSE_CH1_SWEEP + jsr write_hex_a + +right: + lda JOYTEMP + and #JOY_RIGHT_MASK + and JOY_PREV + beq joy_a + load_ppu_addr $206C + lda #$01 + adc SWEEP + sta SWEEP + sta PULSE_CH1_SWEEP + jsr write_hex_a + +joy_a: + lda JOYTEMP + and #JOY_A_MASK + and JOY_PREV + beq joy_b + load_ppu_addr $208C + lda DLCV + eor #$10 + sta DLCV + sta PULSE_CH1_DLCV + jsr write_hex_a + ; sta PULSE_CH1_DLCV + lda #$F0 + sta PULSE_CH1_LCTH + +joy_b: + lda JOYTEMP + and #JOY_B_MASK + and JOY_PREV + beq done + load_ppu_addr $204C + lda #$00 + ; adc TIMER_LOW + ; sta TIMER_LOW + sta PULSE_CH1_TLOW + ; jsr write_hex_a +done: + + lda JOYTEMP STA JOY_PREV rts diff --git a/wasm.fish b/wasm.fish new file mode 100755 index 0000000..8a006ec --- /dev/null +++ b/wasm.fish @@ -0,0 +1,6 @@ +#!/usr/bin/fish + +# RUSTFLAGS=--cfg=web_sys_unstable_apis +cargo build --target wasm32-unknown-unknown --bin wasm --features web --release || exit +wasm-bindgen target/wasm32-unknown-unknown/release/wasm.wasm --out-dir wasm --web || exit +simple-http-server wasm || exit diff --git a/wasm/wasm.d.ts b/wasm/wasm.d.ts new file mode 100644 index 0000000..3afc473 --- /dev/null +++ b/wasm/wasm.d.ts @@ -0,0 +1,41 @@ +/* tslint:disable */ +/* eslint-disable */ + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly main: (a: number, b: number) => number; + readonly wasm_bindgen__convert__closures_____invoke__h30acef6f6c0e425e: (a: number, b: number, c: any) => void; + readonly wasm_bindgen__closure__destroy__h88746cad1b24036a: (a: number, b: number) => void; + readonly wasm_bindgen__convert__closures_____invoke__hbefc371369f44e63: (a: number, b: number, c: any) => void; + readonly __wbindgen_malloc: (a: number, b: number) => number; + readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; + readonly __wbindgen_exn_store: (a: number) => void; + readonly __externref_table_alloc: () => number; + readonly __wbindgen_externrefs: WebAssembly.Table; + readonly __wbindgen_free: (a: number, b: number, c: number) => void; + readonly __wbindgen_start: () => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; + +/** +* Instantiates the given `module`, which can either be bytes or +* a precompiled `WebAssembly.Module`. +* +* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. +* +* @returns {InitOutput} +*/ +export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; + +/** +* If `module_or_path` is {RequestInfo} or {URL}, makes a request and +* for everything else, calls `WebAssembly.instantiate` directly. +* +* @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. +* +* @returns {Promise} +*/ +export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; diff --git a/wasm/wasm.html b/wasm/wasm.html new file mode 100644 index 0000000..c19f55b --- /dev/null +++ b/wasm/wasm.html @@ -0,0 +1,47 @@ + + + + + + Wasm test + + + +

NES Emulator

+
+ +
+

Controls:

+

D-Pad: Arrow keys

+

A: A key

+

B: S key

+

Start: Q key

+

Select: W key

+ +
+
+

Load new ROM:

+ + +
+
+ + + diff --git a/wasm/wasm.js b/wasm/wasm.js new file mode 100644 index 0000000..38678dc --- /dev/null +++ b/wasm/wasm.js @@ -0,0 +1,649 @@ +const lAudioContext = (typeof AudioContext !== 'undefined' ? AudioContext : (typeof webkitAudioContext !== 'undefined' ? webkitAudioContext : undefined)); +let wasm; + +function addToExternrefTable0(obj) { + const idx = wasm.__externref_table_alloc(); + wasm.__wbindgen_externrefs.set(idx, obj); + return idx; +} + +const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(state => state.dtor(state.a, state.b)); + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches && builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +function getArrayF32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len); +} + +function getArrayU8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); +} + +function getClampedArrayU8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint8ClampedArrayMemory0().subarray(ptr / 1, ptr / 1 + len); +} + +let cachedDataViewMemory0 = null; +function getDataViewMemory0() { + if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) { + cachedDataViewMemory0 = new DataView(wasm.memory.buffer); + } + return cachedDataViewMemory0; +} + +let cachedFloat32ArrayMemory0 = null; +function getFloat32ArrayMemory0() { + if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) { + cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer); + } + return cachedFloat32ArrayMemory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return decodeText(ptr, len); +} + +let cachedUint8ArrayMemory0 = null; +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} + +let cachedUint8ClampedArrayMemory0 = null; +function getUint8ClampedArrayMemory0() { + if (cachedUint8ClampedArrayMemory0 === null || cachedUint8ClampedArrayMemory0.byteLength === 0) { + cachedUint8ClampedArrayMemory0 = new Uint8ClampedArray(wasm.memory.buffer); + } + return cachedUint8ClampedArrayMemory0; +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + const idx = addToExternrefTable0(e); + wasm.__wbindgen_exn_store(idx); + } +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +function makeClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + try { + return f(state.a, state.b, ...args); + } finally { + real._wbg_cb_unref(); + } + }; + real._wbg_cb_unref = () => { + if (--state.cnt === 0) { + state.dtor(state.a, state.b); + state.a = 0; + CLOSURE_DTORS.unregister(state); + } + }; + CLOSURE_DTORS.register(real, state, state); + return real; +} + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + state.a = a; + real._wbg_cb_unref(); + } + }; + real._wbg_cb_unref = () => { + if (--state.cnt === 0) { + state.dtor(state.a, state.b); + state.a = 0; + CLOSURE_DTORS.unregister(state); + } + }; + CLOSURE_DTORS.register(real, state, state); + return real; +} + +function passStringToWasm0(arg, malloc, realloc) { + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8ArrayMemory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); + const ret = cachedTextEncoder.encodeInto(arg, view); + + offset += ret.written; + ptr = realloc(ptr, len, offset, 1) >>> 0; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); +cachedTextDecoder.decode(); +const MAX_SAFARI_DECODE_BYTES = 2146435072; +let numBytesDecoded = 0; +function decodeText(ptr, len) { + numBytesDecoded += len; + if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) { + cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + cachedTextDecoder.decode(); + numBytesDecoded = len; + } + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} + +const cachedTextEncoder = new TextEncoder(); + +if (!('encodeInto' in cachedTextEncoder)) { + cachedTextEncoder.encodeInto = function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; + } +} + +let WASM_VECTOR_LEN = 0; + +function wasm_bindgen__convert__closures_____invoke__h30acef6f6c0e425e(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__h30acef6f6c0e425e(arg0, arg1, arg2); +} + +function wasm_bindgen__convert__closures_____invoke__hbefc371369f44e63(arg0, arg1, arg2) { + wasm.wasm_bindgen__convert__closures_____invoke__hbefc371369f44e63(arg0, arg1, arg2); +} + +const __wbindgen_enum_AudioContextState = ["suspended", "running", "closed"]; + +const EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']); + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + } catch (e) { + const validResponse = module.ok && EXPECTED_RESPONSE_TYPES.has(module.type); + + if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg___wbindgen_debug_string_adfb662ae34724b6 = function(arg0, arg1) { + const ret = debugString(arg1); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbg___wbindgen_is_undefined_f6b95eab589e0269 = function(arg0) { + const ret = arg0 === undefined; + return ret; + }; + imports.wbg.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbg__wbg_cb_unref_87dfb5aaa0cbcea7 = function(arg0) { + arg0._wbg_cb_unref(); + }; + imports.wbg.__wbg_addEventListener_6a82629b3d430a48 = function() { return handleError(function (arg0, arg1, arg2, arg3) { + arg0.addEventListener(getStringFromWasm0(arg1, arg2), arg3); + }, arguments) }; + imports.wbg.__wbg_bytes_2820db0ab474c07d = function(arg0) { + const ret = arg0.bytes(); + return ret; + }; + imports.wbg.__wbg_call_abb4ff46ce38be40 = function() { return handleError(function (arg0, arg1) { + const ret = arg0.call(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_connect_9a58a232bfff28c8 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.connect(arg1, arg2 >>> 0); + return ret; + }, arguments) }; + imports.wbg.__wbg_connect_f28a2db518e02462 = function() { return handleError(function (arg0, arg1) { + const ret = arg0.connect(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_copyToChannel_30d90303302ec449 = function() { return handleError(function (arg0, arg1, arg2, arg3) { + arg0.copyToChannel(getArrayF32FromWasm0(arg1, arg2), arg3); + }, arguments) }; + imports.wbg.__wbg_createBufferSource_156317138619c7b0 = function() { return handleError(function (arg0) { + const ret = arg0.createBufferSource(); + return ret; + }, arguments) }; + imports.wbg.__wbg_createDelay_6439a64d02500fa1 = function() { return handleError(function (arg0) { + const ret = arg0.createDelay(); + return ret; + }, arguments) }; + imports.wbg.__wbg_createGain_d5704df14f1e271f = function() { return handleError(function (arg0) { + const ret = arg0.createGain(); + return ret; + }, arguments) }; + imports.wbg.__wbg_createImageBitmap_50df7cebf5a3d827 = function() { return handleError(function (arg0, arg1) { + const ret = arg0.createImageBitmap(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_currentTime_7d6df02e29507923 = function(arg0) { + const ret = arg0.currentTime; + return ret; + }; + imports.wbg.__wbg_debug_9d0c87ddda3dc485 = function(arg0) { + console.debug(arg0); + }; + imports.wbg.__wbg_delayTime_56315e7f0ef53379 = function(arg0) { + const ret = arg0.delayTime; + return ret; + }; + imports.wbg.__wbg_destination_1dd37feba0c0cab6 = function(arg0) { + const ret = arg0.destination; + return ret; + }; + imports.wbg.__wbg_document_5b745e82ba551ca5 = function(arg0) { + const ret = arg0.document; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_drawImage_44577ef8eab8c151 = function() { return handleError(function (arg0, arg1, arg2, arg3) { + arg0.drawImage(arg1, arg2, arg3); + }, arguments) }; + imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbg_error_7bc7d576a6aaf855 = function(arg0) { + console.error(arg0); + }; + imports.wbg.__wbg_files_aa1f009258eadae6 = function(arg0) { + const ret = arg0.files; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_gain_435505e65fb96146 = function(arg0) { + const ret = arg0.gain; + return ret; + }; + imports.wbg.__wbg_getContext_01f42b234e833f0a = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.getContext(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments) }; + imports.wbg.__wbg_getElementById_e05488d2143c2b21 = function(arg0, arg1, arg2) { + const ret = arg0.getElementById(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_get_89bca58298277b24 = function(arg0, arg1) { + const ret = arg0[arg1 >>> 0]; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_info_ce6bcc489c22f6f0 = function(arg0) { + console.info(arg0); + }; + imports.wbg.__wbg_instanceof_Window_b5cf7783caa68180 = function(arg0) { + let result; + try { + result = arg0 instanceof Window; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_key_505d33c50799526a = function(arg0, arg1) { + const ret = arg1.key; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbg_length_22ac23eaec9d8053 = function(arg0) { + const ret = arg0.length; + return ret; + }; + imports.wbg.__wbg_log_1d990106d99dacb7 = function(arg0) { + console.log(arg0); + }; + imports.wbg.__wbg_new_1ba21ce319a06297 = function() { + const ret = new Object(); + return ret; + }; + imports.wbg.__wbg_new_8a6f238a6ece86ea = function() { + const ret = new Error(); + return ret; + }; + imports.wbg.__wbg_new_a2ec8094aa0713cb = function() { return handleError(function (arg0) { + const ret = new AudioBuffer(arg0); + return ret; + }, arguments) }; + imports.wbg.__wbg_new_no_args_cb138f77cf6151ee = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return ret; + }; + imports.wbg.__wbg_new_with_context_options_ef5b87cd25cac8d1 = function() { return handleError(function (arg0) { + const ret = new lAudioContext(arg0); + return ret; + }, arguments) }; + imports.wbg.__wbg_new_with_u8_clamped_array_e14490b754099e0e = function() { return handleError(function (arg0, arg1, arg2) { + const ret = new ImageData(getClampedArrayU8FromWasm0(arg0, arg1), arg2 >>> 0); + return ret; + }, arguments) }; + imports.wbg.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function(arg0, arg1, arg2) { + Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2); + }; + imports.wbg.__wbg_requestAnimationFrame_994dc4ebde22b8d9 = function() { return handleError(function (arg0, arg1) { + const ret = arg0.requestAnimationFrame(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_reset_6985caa8186d4f54 = function(arg0) { + arg0.reset(); + }; + imports.wbg.__wbg_resume_7d320c513be492d2 = function() { return handleError(function (arg0) { + const ret = arg0.resume(); + return ret; + }, arguments) }; + imports.wbg.__wbg_set_accept_4af7309453c16421 = function(arg0, arg1, arg2) { + arg0.accept = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_set_buffer_25c70ce663d1667c = function(arg0, arg1) { + arg0.buffer = arg1; + }; + imports.wbg.__wbg_set_channelCount_4b7d6cec989c8ae3 = function(arg0, arg1) { + arg0.channelCount = arg1 >>> 0; + }; + imports.wbg.__wbg_set_innerText_b0abb40240106cb9 = function(arg0, arg1, arg2) { + arg0.innerText = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_set_length_957d490e6b543adf = function(arg0, arg1) { + arg0.length = arg1 >>> 0; + }; + imports.wbg.__wbg_set_loop_8096808d7e93a3af = function(arg0, arg1) { + arg0.loop = arg1 !== 0; + }; + imports.wbg.__wbg_set_number_of_channels_f0c703fb96f63365 = function(arg0, arg1) { + arg0.numberOfChannels = arg1 >>> 0; + }; + imports.wbg.__wbg_set_onkeydown_d2621c474b636979 = function(arg0, arg1) { + arg0.onkeydown = arg1; + }; + imports.wbg.__wbg_set_onkeyup_913b36756e057c1d = function(arg0, arg1) { + arg0.onkeyup = arg1; + }; + imports.wbg.__wbg_set_sample_rate_9ba31b5c895c7108 = function(arg0, arg1) { + arg0.sampleRate = arg1; + }; + imports.wbg.__wbg_set_sample_rate_fc3bf6128936f9e5 = function(arg0, arg1) { + arg0.sampleRate = arg1; + }; + imports.wbg.__wbg_set_value_9b29412dd286d5d4 = function(arg0, arg1) { + arg0.value = arg1; + }; + imports.wbg.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) { + const ret = arg1.stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbg_start_865ed2d65a6d353e = function() { return handleError(function (arg0, arg1) { + arg0.start(arg1); + }, arguments) }; + imports.wbg.__wbg_state_c28a610878aaf489 = function(arg0) { + const ret = arg0.state; + return (__wbindgen_enum_AudioContextState.indexOf(ret) + 1 || 4) - 1; + }; + imports.wbg.__wbg_static_accessor_GLOBAL_769e6b65d6557335 = function() { + const ret = typeof global === 'undefined' ? null : global; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_GLOBAL_THIS_60cf02db4de8e1c1 = function() { + const ret = typeof globalThis === 'undefined' ? null : globalThis; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_SELF_08f5a74c69739274 = function() { + const ret = typeof self === 'undefined' ? null : self; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_WINDOW_a8924b26aa92d024 = function() { + const ret = typeof window === 'undefined' ? null : window; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_suspend_e4145c9878ac544f = function() { return handleError(function (arg0) { + const ret = arg0.suspend(); + return ret; + }, arguments) }; + imports.wbg.__wbg_then_4f95312d68691235 = function(arg0, arg1) { + const ret = arg0.then(arg1); + return ret; + }; + imports.wbg.__wbg_warn_6e567d0d926ff881 = function(arg0) { + console.warn(arg0); + }; + imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) { + // Cast intrinsic for `Ref(String) -> Externref`. + const ret = getStringFromWasm0(arg0, arg1); + return ret; + }; + imports.wbg.__wbindgen_cast_8e402a763b70599f = function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { dtor_idx: 25, function: Function { arguments: [Externref], shim_idx: 28, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`. + const ret = makeClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h88746cad1b24036a, wasm_bindgen__convert__closures_____invoke__hbefc371369f44e63); + return ret; + }; + imports.wbg.__wbindgen_cast_b3587965ddad1edc = function(arg0, arg1) { + // Cast intrinsic for `Closure(Closure { dtor_idx: 25, function: Function { arguments: [Externref], shim_idx: 26, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. + const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h88746cad1b24036a, wasm_bindgen__convert__closures_____invoke__h30acef6f6c0e425e); + return ret; + }; + imports.wbg.__wbindgen_init_externref_table = function() { + const table = wasm.__wbindgen_externrefs; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + }; + + return imports; +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedDataViewMemory0 = null; + cachedFloat32ArrayMemory0 = null; + cachedUint8ArrayMemory0 = null; + cachedUint8ClampedArrayMemory0 = null; + + + wasm.__wbindgen_start(); + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + + if (typeof module !== 'undefined') { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({module} = module) + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead') + } + } + + const imports = __wbg_get_imports(); + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + const instance = new WebAssembly.Instance(module, imports); + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(module_or_path) { + if (wasm !== undefined) return wasm; + + + if (typeof module_or_path !== 'undefined') { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({module_or_path} = module_or_path) + } else { + console.warn('using deprecated parameters for the initialization function; pass a single object instead') + } + } + + if (typeof module_or_path === 'undefined') { + module_or_path = new URL('wasm_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { + module_or_path = fetch(module_or_path); + } + + const { instance, module } = await __wbg_load(await module_or_path, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync }; +export default __wbg_init; diff --git a/wasm/wasm_bg.wasm b/wasm/wasm_bg.wasm new file mode 100644 index 0000000000000000000000000000000000000000..4375d8fdee1f95385f9e9baa03d4564f2cb8c424 GIT binary patch literal 325607 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

b{4WT$wB?{mSIt^t4g02 zg-aEaBGZOd%m?j=rSWFa ziSr0}*zTn$PO?)$TXnpdD^vXk^$N=uoOV#PrdsXn?8SUgED^&OheEK*xL*MC+SYF` z+B&7K4%$%$tls9ag!S(E4lGPwLW3Kn(Y?&ubYu52inz7tzqS=}NVu{;V4iS{+$>Te zn3;#s3IXnQL@qG;58ucyF(uZZ*m)`<0XUuY#Lw;RK^cdbC8}i*yOt@y8abU_3b*zT z8kdfs^KmV_ojlp|CYGWsr^`gB#b2w+sEc-xp}G|g&83{F#5D944C^hkgU}AIS$ILo zuF4@9gKiiy%^)O8v&drN5QC_IU9B(JI?&9e@q-cOqCSuXC!!@0&|*mt836;9g!RFa zq~tiWy@lOM#EmMcYPpzKmJ266!K;>}5H(fL^zl9k^h6dxM2GD2vCP=Zja%5`O6mA! zs#wDhNRUy5d9;cjFq69u0;IbP)Uk`{^aDH}mP9GWwP=1aB4#UhcE2?MJ5rOGi~@<) z$A-(Yzqe0?L5R=hh=u7$`W6Eq)Di}O866C2$s#3tQr>BstgLtfj-_PkE|xp46k+^w z7H}C;Ow^8t{znkC{RkQ#ZR0nSDH9PQNKnaS@4sB(xP}Djh^#-_?3>N9f{H&fEv+NW zn~}k4UH_%^D8W$6^81Oo$PMVgjMP08+lip0Y9ZiM6BYu^&)EICat$gM?ohm4(p_Tr z+e)qbvj4Zrvbx0XOJ$9T`*WotL_N)~A?>A%^h@0Xwc zzWeE0_UWne)AzfdbX8=~VA{0MXwi@%4AdYRU6iu|h``{Ua?iyA;~-q0?W70kP#VNj z;VRrrEA$EJe#12Lg=yp$$N<@loa&lq9L6nu_{Z zdQ}LAk4|r5y{(#K2{<{J3;yaj!~^M%4#23*5^LhEKH5YgM|AxPZc~JL(t$c{k#a4q zX-$v=MSDFpvk;c5Dx|k3e-8%jMGyx!+bS-8=*bz6$^ULrp*S5$x5=S^n5!@Y%)YAT@uOgU>Lm821ERGh-06AMVEV z!zlg|K4>>jjIu1@P77=7frZo4C<{v^``=k3_-Z}M`C-Y@wa%UW-p*y_ZJE8XitQ%N z+oGr|YsYHG!MK~pZW}#l^Ut$mud=&u`boyjjpnl2Ds-$ zZ*RsUZ4WJ6JN9rL6k`uRPj7^(up}N$v2HTX-8fc5GThiqVd+mMhSkuAZKw=l1skjY z&l1Lpa0coAC}FHrA3FuIii8!&`cn-Y{(;2j6v#O`H1yHb z-wBQJWr=x+G?8R38ib~EoHKg6EUt0v6Iij;+YgJs)!D8Mp>fu4End26xTs*63b1*m zZO1m4AfSB9sAW_;d_Xb#I0=k01y5PC;Dg#e(A2(hV!h40gM852Osr$5Ze1WQD?c;8>6) zwX1Xbr>R!#G!WF;d&Fp5lUxn+vuTPT=$bjk?3EFkyH>QiU)XeP6Dx`7a%oX%9UVzW zjOk)E&eSz07|#SsN`nGpsvt7O4@(7lj`pjlFAxQWR+SQBxRs=8!CDH%^5++(x~#1s z!;r~trX-P|^;K$u1V7vP%aK(AOGDs}9$-m0!Jq7tVq5}*(dw(omt_@Gg~&OuC)!7c zheH#a12lMEu}3*T)Ii0XuUP@GsU6Z`=ULLQ!7ZB}%b0qCI+hP)kHPDRnvqr;u7yl( z;TrmkLP+d{fpPs}e4BC6gT=QTJeN{`7!x3Xs#bTJ9_IT)34D$e%VHg&h5HQhlhX}kA zbMOyjcjn<353$d9^ast(-g< zYJQA|Q1gj{&%NgHsg-J}zF1{@6C8_GAbq-~h&Z(CMmQ5Sr$XO_r^yBnZpy{Z% z1Df-n!qM@?)O+h?zD&HgUPGvVV)&85a&1R6>>2I=6Oa@;<|Wv`p^)67@o3jW(>{m> zlL2Psv%hOwR_Vm*=t=*~L2I%BP?L{v;7$5Jvh5mvPW_Hd^H?*cl64pW6Zbv8;WS}x z>5i$Kr0*9={=z4PkVv!C@hd{S{=kor%GhFRl!I|cVFaeoGN355=6}SJqwkXS)bued zB))0(IjiY2MLYg(GYR4m!WvViGv_yWXcjB+(8I;M2c~fzU~It?p9hPPp%T&OOiBcs zmqo(|2%b!ywaQkXAmJ*wLgbHk!0qNlKT{R#gD1&TG@HCNl; z)vTt`n)w37IxkSXVxB;;j_e2&I-ko66qlC*1qZ{~f-G5Oeh#vGf#Px#C?+CgT_#Tf z?NlGMuk1oQ*$eF}OK2zOLn~V~bo!ck(B9yoeN73ioV*@g*Y-i%pQD8K+K{;|P$ifU zFD#`|oxc;QV~l-6ywLKC=s_Jnblbjhwu?Ugdx?8kBfay`!6tp?fi|Lho^pQGfH2_y zd1q`Y_GuCZ6tE8mUCN3E@@&~P{V$I-aacTZ42`Lyb#Vi-B4{CtU&AS*T-YIB9*jp@ zE~SE|$)tJwegHex<9Kok)*?>rPKkf%Pxd}U0lu6z-iEv(HB}8TK_F+6>Gf$cYTCx` zNqdqYT0loxgDkeq@?^oo6Qj37;);Z$8Y)Bckx0mVhfTsluUVlMK!to)g*iZuDaGy@ z&x8Ic46Zn-0C_II2NWj}-I|Y3eH~}bHTq}Yhg4x+5=qPuqO%c4j zNraLPL&s8io7=XK#vMV@qK!hg5kJ>m++x^X4m);E$WU?gJ9@)`+DdMWmr#HXCL#uJ zL-!29ucETKWBFv|RDdp-%H3WrL+w>7~7sRSZhLDcL zU$~nq)f}-*7Z}Ja24UC0rfaJM*~o0X0x8}6262ta^a~D1p|KKoEA2$?ZND7Vo;@^jR~YdQpd2t%5_e$*KTwS4G{H&GzqEq%os3- zZ>74Re)uHSLbb0py-@K{RSoi4D@gT1s}P)jqgAx5|xrH0lg_3uKL@Rtz!g)=tqXZ zHEWw7+(SjAbeL2fp>upeL(k1>W1OTE7Oi3!=!Ouv(KR-4*IsjOcD_h44uQxjCPIX< z%DMazD#U_^tTL;H#+2jjs)wdPigZSQuRPq6NPuISQu#4rTU?Y!JANtgJ_#c#HxkVf zY9Y=X?N8bmjGodk2}$jgVOIu8>IkB}a4o?&k1lao2v5=r>NBFwY5>iQc7crwiLfp! zl2-MRAz0Nymbx#m$xEBfF@L$#5oH|j z)@#-&H5(kO>e{_TnkV7Nq=2t+3gEWpKwGJDTMBK$xx_*2bkXCc#G84*sb?^)9ofUL zVq0#0Xd9r&F=KXZG1^d(&vMd$p7DU;I1V;p89<`h7OV&^ZKz|$ZvH$8+fuVTXkqECKC-Ld&x?}x&d(3Yn;Fk2=Kd_vzW1q*f#HA)4PCCnp?XL z58+(*M#7oZoi8M-Dj1_RuQK!6E~d?)%%$<@k6&n)6WIGtKsj`?+wBHcO%YgP`9Ejf zKDFBwffUkD)F0rH(x4SNzj#v2xD>u&=n%^vtC_x$LuA=!ZSvyv-m)S!cRNhSOe&Jt={O zL0XZO;)doW>hq4t%9@K*zF@> znqr-{QJIUl+GHX6!<{^oEYns96>U2q|F5DwTr7=bBE0(Pt-3;Q^GwBlV7F~gxb<9= z=OzmObYX&&PKvjD`$=W-Z?n67D|HPJqm)CZOR*M0%(*k{6mi6urX8En4`m}-ql*}DX^J9TNG$1LokaFjg{5t?R=Y^>N|{$ zv;Y!Ak(|eyv79q7;`p}wud~@q{d@Mz*vy0``mj&Cd6CL$@?;58;K!6aSc=ZM|4-hk zagYi{_tfH&hhjDnQ}c^vDSg(=t`@{ehyZ=K-6!!?KPKl~NPZBW&CjhiZ=V^C(aG{2 z5^nGx_SUTDJ}9nTTkXUub|RrqxbKS#r;_HAHF24_8$Lw(X zabsj+65b~smcAgo+(2uJ7fcDf&j880bAi|i>NsX)tVFYQ3XA)vC!youU5c#;mnF`a z`zP+5XS6xY5hE@0wV`I#U~><_oTz)Uh*@7F>(?c4E&&>hg4D(z$u0ueX!~Z78T-M-qzexFi)I7dscKM3>Z7?$GzGQB8<-*zji` zgI)x3)LC;KIM$RR?qmZNI)?n9@0y!Ztziu1bbiK)#+rtle^+WSg^1lsnzFiZTZZw^ zz(wPvrU4z0o0c7~!v(r{WQPehegx9~lhic31m{jH)Dm0t7Rx?=^hTM%IZ#GZFYXE? zz2%T!CpU1(pxce+R%V=+IJx;u8tlC4x-<*>Oc&wtu%0dQ;cDq-{Jah+pl_e$5fCgO z(8;7-bJbd2UB~MrG9zA>+A}$EewI=V*|QQ$=GX@1a7Lht$TkEtj*ObFK;`TXkiJRx z=&#_Y@9C5vpk2&PgHm^Gb@6332_$w&Cuga@?X_8hLUZNE0F>|?XO~i`3}5WBR&Z2L zeqh6Pn#p+z$t=10VfuYQ`0PMG)mp=*9srDjRn!DN`j${;ei!SCSpYLJ#|PsG>2Ov~ z`;I6Bu9~Q;MhwJQywBKSTD+vK1P6Xc^a%~W&&cixLKYb8Gh!}cxnkOk?b$ zaVHFx$v>2J=jffu9QHMcPJQDTuSBI}krPg~WF-$VDJ0H%Eb*0Ni9iBtO_mn?gPP(9 z%Ap6TEToN}99VbJm!`$UnD|^523jT@_kAnp5r$K&P63l_6imb;Y2pV?l<^X`QC%IY zqcIZ89c%bBxR9`TNA=*Vlhn{Yu&Eso^|gB1)+@DL?D5LtzqYDcyW66zXqy8~N> zj_upocBf_WCW8_*C5YG$Bq$nakU8W0{rE@G)SSHF@}PXC=w#BrYfcQ=#1C`s9)dnf zOojE?CAQN^*v2x9PxjW6#k5GFGI-0s^`W-cF#+SwQ`2m`CEw=mxR59{ zf}yJmanLJ1C!)HIX~fvsfKlogj?TE8(3wQ*Ru!h=(~l0adQO)ZXlnG5^O8`cq%aE5 z$ygm&C1k=tEZcPu&&FaJ>sQn_$Goue{;;*NvY0ns+`zn9$Gj3U#=N$wa~zDyU2sf8 zh|4g>!5S3eHx{SHoXA~qFbi5iNO5rPnQ$;RwwQyZE+7}QA=4Ga9848rd8o>OzQ(~C zaylDhdZPw{=V07<$_VtdO%GQpgYV9wN!f@E^p_JGMHKI`!u_9 zO*p3Hu6(%{n9RW+up*;a;k$_TD)DqO)goIU$a%Y4U_| zB}xgg^d48ZDkEXUf22@I|BNr3TeEKmlaboCx2gP07|hlH;D{P+pIxDqKPJwV+Qs_F z4~U!-9uD3jwGh>7CnFf)LqqazBuymyjf1q2vttxlW9YPq5I61#9qw13J2vS&o8wQY z-jl`HN*kp)u*%mt$LL@Nyd5ra7fm8A88E}H#3#7?pi?+Av?h8rS0kyk+sA}@cEms? z9y5W86=fojNfELSb?Ngf2p~5hYCXoLo;z7#KWKq*cKkA!?a>{xq*js}5-{?S8ro(U zJA;y>bXxQx)n@G){yq5k13AZ>gY)PH+|{-5twWPTNG!=OopKIkHj%jTpkxd(UWpHR z=tl>zY?iV{G3D9nk;zMj1K$9aE~y6O|0SDkzc71&h9G2lbj%xRa9}Q)sVNf#jkhl> zQw#0@qGmGFj9tJqwXv&HKNr01MrQTebj4IY#JrH4u5@uNIqzVG#CE~F-Y{LYH3}6#OtVd!q!PJ$846{ZjR;U2LXm=9U3`L^DIS` zAkPY$Ee9(nB~0Nb_PHKJ-ww>yGncgZ^tJ!;0FHi0)X5*MrnN+ME8i@q4vxw$Aq9Qt zME3*36DW|rNcIYys43h-K)%osUnshw9SvPfGx>%NXVzZ_kJ|Zv?!zzUrPEpUE*rnQ zfRiqATf&EyrUdyvWt|&}9jN>WP0*M+h9OON-I@Ce-&XJ34tFs+9_Z*IHZ}WTM`6G^ zk?`#%Qa7$=0*C5bOj$L#W~E55Ta>U9dGGIV$}9#KJJRGNoxA&^Rf)D84K6CDgdk^& zq?R*W?3IXsw+{3@+wUiJJlbjD?`n9Zsvyf_oERNXkz~+bCOylKDP80!{GIrl3XSgy zVl!tT10}_GbePRRy2!Nb9l4`(h3L_Xwgu6C4)g;GZ{}i9d@oHhZyRW9_lWS%;x7_G z83-y$`m02cv3{56F7Y%ob(X5o%rMs1kwKD}RNVGdu$V~#YhQ)4sS&C*GZ@x?N!*+a z=F}8QA(`wlGrypOlCrXp&NjOdnUTxdO|-3pj=^SJircOce81DeqKcT`u3`2fme{V* zY1)SE8r!N#0;uJ%t(p-4w9_aUOqc4IWJwwM44G}wFljHYuxi{Mi208L%+#Kj-{^80@K&2QX!;iZ>IP#P!}Hg_vav3j;0J2wiVDIq(zEk5F@5IAMK;+?&T7JW zc$aOWNYfzbYyvsSJ;{8D#4w{X%-YW2m{W#E$X+1aLE%e8VXMi3>k#c%vVX}8NM^S& zsfL-HfbHC3OG=boB*U~GZ%iTz+iGbNjBaC+aTIS%=1hM2+EQ(4LaHrQqtQ^tR)e;J z)7@ovV4mu0Q(hG=T<*?5NLO>4`?3K@e6smmlb)ECqfI!k03;|lpU6fW9xDt&v{_y) zbPMwbu{MB(JTt{PD?}HetMCyRFG{DPP@A6xUF00Q8a#oZU_l;RdozoWRCU!Nz!IUK zy~u=9sY7Xy23*r%Mfl8qc!kuTCm^I!3^F_)>3ok>REx+J&2A}{NUBog4o~Rv5LQZ_0+)p zUKuRv2`qM_mQemad{ens0?G%^A`KSHb` zouP*&AthujAxh3gk{HHg%+yeg-4Pl6`4t2IFPw{*V>Q$n<1Mm1gDL!ZBHJw)$H)I$ zG@m-zKJzykr1Dk6!2RE&EItn;`|AH%l07IpkUK5ejw0hc=AgA;7tlhb-EN25?AVz+ z9*IvFWWPIXxRY}dGCi}eaA1Tc5{^00+^?gm*hxjp8lpRlOpWfPY?OL|pI_Sn(M2O| zRmYVQ1}bHEFOo@(d`{1H=OLAikAKzY52+$W(8|>sZjAul-E@}{c=iMay_j%CKUw5AWzS86;$f!}i&+E!xJJ_M+%) zeRK|60gd8}93P!fhft^WoaA6HR_#&5cIst(GE2Ps>I|;H{5NLgu|j>?-td7Ltw-b3 zjx}LN>H{-u*u$!wuxi*z`^^AJh1CF8QEC)_GCPA^r=%-`?tm@*=yXg5&~sAZ{oI3D9bpWVjXuX%0*5TjvP!s(fE)L;6R=={ z46MO|woQ|%c6uj3a1z@9(z$nwqM7yonPJc>AB?uj|3Eg|=Bz0!RweXnM~zfd>XMxg z|7Ee!hFTQ3${~+LcNvGFRBp|Aw~1Vm3CQIkc$v%$Ojds!`%&*+)VcUT^^>kq2^=r8 zw_VURc0su5Mz~Vk#kYC%0XZ%!1MqdmsTt7JcBk9=WO_xaGIZ=*lFnSg%d){sB2gh7 z9ph%uk2ybqJk<)+LOMxF0xsoc4&j?vxJ$E>KrU57lQmnwj}25Ouk+s(+h|l}=WFph z>ZKi4jqY-A)@7{S)}f)QMg4NH*(hM@soAN_AUeAx9wRy(+fMy*PBx+w>^d#oq*b&K z=&G-r0ozqyQ0f)Jq;}OeMy_i(xoGsOzO3(^l}9Qc_%+#3l%XA;C>>d6-p18*wFY&) z)^Muk*k)IMb)fv=8(FvO%I@c~_$E!-?0_oq=sH}ZnV1|V${234KsFIj`PH(VG_kT* zH;c`3gfx@qLM$*eoIY31{gt^dDy-ykjvec$f(QZ;0a3 zLA2?MvV7PiVO4TQxcsH5!6{}G6!}Xbu$>(h-KCp+O_#1sBM{b1NP|U$u@lZ4a zZ9Eh|R5z#D_O7vxy1=w18zHeTCYuU!cE}3Kv_mURdUP=(TUVqgA>k2aY98ri4Cd%G zQ!D|5$4?+`O?VJ0phxn9>q<$Rj_8ta`Wm}bI>Yk|9SFa;=?F~{80O>MgxNVYa341BwW?pt+^1O=~nkY$&xd|GsQytW@^cN-LBM zBYw>EXE-G>or#YSpMo*EfkWR6;t-y)cIHgEL_D^mIB{Qi3EQPvP-kK{dhA*nEE?U` zHI5dHHN{D8^ziQ}H+u9TGL813ATeNq*lS*vcKgpnLx?Yl?%0pn%ED$ zL9L*GHcKIod8Tj!m7!~=I=6DFGdh&|;UQ{^!Vl`0=OY=az_}e8YUo9cPS!<{!e_xG zrG_msJe??j3@xZ(R8le}+Get%U>6HyiRBIkavF}Zlc?IE)ArvsEa;kdaykqilE5{9 zdq|5NK{=Py2r9d~6bcSBHQOvYAD^mW0v6Rp8f>#Q#j>yn0;nobSiUz>Y? zw|@+V_qB65&QPjb(d@Cyp_Oc`&cvFK#Y&-m`k^Iq;eRYYG?$H=sC_l*0k5NPdGlz7 zqtLm+2C4YbUo3>sjs7zBmF$c%|LcsOIVGyRGBZDamCmcWu@#@k=2}I}E!JP~x`-}M zFw&e^6&U$#2ZCWehB|TLP8zs+1s=$()!8*<662e}=DpY=tKdg58Ap?R>$Ji!=_NLe zDCG^RbabbNi1Mj?D%{U6}KuRlS*{mfduWjdos`~!Z>r0#X^vEN~nT)lM z);S}C4V`G@Jx26QH*gjy8|q-FhLrX(O8su->9!xD*q?l^ z!Jm9v4mOuRdC(BRpFG3GT+MT4m>Rsk=1;y|OD%*Js%gk3zV|0DGHCxacs(7Qoe_+m z%#UGfGe9JPg6LX2;(mkKg?w9f zmv0OCzUlJau)BOWkngP6UU7A*GT;TxHK|mk-LyN9Hv#g!4)v|O%XcgJF2iv3p8EJf z2E)=4iwsaE5oeNgEDl=CS;=v0mJG}@>~L%R#y6pL7}||r-l%sRK&B~KgDmHjZlu?9 zx}hY!!OV%dn#|!&j8+^-QVW^%kyhdEa1)X_QQ8C22lj}sMI*Os(uc6O8=6f_+wpNu zJH8=|=u)A+F9V#|kjT8`&9s`A)ONP}ZM2If96ENL!_1VV2s2KN61vUKw=<(`gu;5D zUc_Y47)Vq?5(8kShoaRPfLJys%b2X8f`0`9LCod^LIGz^lIBLuZFrH@ljQMCqd;-< zj_EFb>)gZ>Lq#%;z2@6&ubBaFGEM8TXftWZG@2a2X-8!r-L*(?Y7%KF@M5Xsu8Tig zfdqcDbeOOw!Y27}m+QzbdPKt-DWRJl2rhwli;?UsU zWc)?&IvBG~U4zU}l2qGE$^`ly=OYAN@Dk7@>1fM^uSJbf>y&$S#2_)d8VS-bu=GBe zG5H76;mVPQm@7vrZHu=cdIGm^QAQH5#;_)!STV~MThI8X(K2>6=KJ$#`Pv%uJvmyw zY-7HiP4Y4Iq8i0E7R}(%U(&gpIrl#@?j$p|xVpBW@r`hzoVjO9=m-Hb|6~Nr#0*v) zQH-2YuL+vwC{*bwM2sC!8FU7%s-*Gh^Tl+4V=i7iQx$;z$Q3SztDcDp@MxxSh2|G! zRIg!0_Q3z(6`38l$p0iBrLI$r)3MkW%6n(0ixqLMTH5-PAx;s?v3mP9O3oUzH0 zP!pa0%ygn9MckxcWHfwOo$AC3+OS1-1&W#1UtVpr6O;CW4Lq&rf@p_)6GS_{H|_)? zPg&%;$Htv-9)A}jyx|DTP4YSxsE@Z;{9a?NFa(_wc_*`D!s^4e~dEYO`@?KgJiq%+v01f?zF zraTw!WTVt%dE`D-t<3k}X&lB^4ONsY6}o4e%OMkLn^$|?a|r94 z{8WBXr!!dn5u%?W8Sl_$rBiM@+79oNJT1p3J3`W6mFfK4ZTKkee064`KRJh)8Rk9b zuz{T+pX84F&Nr;v0?^JjjM4r2(3Y+x{#5#AyFRw2hP7)9Y1xiMadRM}Ma^uF?*7O& zHIr|knVzYgs_0(Q+}c?pN*6_Cm1P&g%sSd|fP(rNYfhs0-i>SS_g?dV&gHV1R*Pt(A7jcW@B{H(&~jX1b2QwllE*QF- z0e(Dfqh+RrNc9NeKL+%zPcD-EI;-Ysp1K>hHZd#<-4qfIzl{Ub{2p67KApj{h|F>_ z5x6@Kc6wG$Pz&pwbVl+hz^Cr@GpTT0&V6k+r>jKwfI=oxn-k2Ig*mNeR+KXU*-08d ziIqhilxX-~tYo;^2`tc$1)HV~KG8s@(QQ_dzn9%7o_49%KgN?Yz8&Lf(0xTDh`x8x zwg3-j+ib8&X?5j46&GLvPZjuq3bavR#3U-*nrRzmR+o5CVwlhAKK>+Z{ti9Me=VyEu9s&Zf ziL?4J6fj*7AEz!wfX1d)o3*2NJi?scfZf@6$s1j!cNv?eWt_+d+QZ4ye$^YO`LAYb z$Jk*uO&vC1Y*o=#xLGGyH2J$k=|^T@be{~7G1GlA#8!vO&brfn5Ovbsq**{rC>rX# zI?dMmpXAhKq6a;uOcoP^Y6KwK1^8+?Ix@W=YpWr;Mbd>OjfSv${Y9koKgOCteSIwZ z2vl-bq~v;7P1YrBf47abtEsPz%i-i5y1g0D+4=6{e6r|2y(O@W_^R%x>)+e!4AkLN zGiSipA)1h>+!#c{a^eI>dD&qwg7O1vNH`N>ogifZLolDab_w(y3q3>;W*mUjc91L# zP31&MTaM^(GS8_GY8oz!4ssJ(sN^d zP|A9lGtmyqf-h^n_j2)F7Fp7%I@=%OCpU7F+o*7krXaV?&*)Hp8T+Js?}-KLzW0c^ zD=zFc+8_}B)i+U{_(PVQkiRJ=_Erv#WlVKt4c(`j2$SC!)iBuoj;SlLf31Y{rjEX3 zp^cf^%kz1ei(ev=F5wgNzt7N_w;E^DDKwOb+eFVqTXl>}axNR6RdORh!+CNxXJj+7 z#7aqKd->&bI@<{Nibgw#eMJM6G&y+A>6<4=8Ct9)Tq2($7f%Ua$co?!8Nuz?shL}3 zNJ=#)OU#|ml2ZG<*etiTAvJbr3rL=kzh7tNz{xrFa=Ze-g@2G^Kc5;hMY1H&aNo#6 z(T>z0Gk^mYYI%h|Y*Prus-dD;7|e{A;wWe}J0EnWre^Sdr(o4&pq#M2AH z88jQE=G**YW!Qjr>U$)L33qUscN(vf0mOwa- zlGEK_B{W+Vj|b~EDa2tWf1_3|_L*pAMXz_odv0SI_S|$Rq|=+YJGJLF#_zdtX+7+G zeOE{P4d<~eSTyLQAMs^h?YX(oWk`cIAZlM6Q(BPJDQ2c6O6vpq0hTtbS6!rozkY0FMQ zg`(OFxSQiwLcoNFbg-+(5;tQD-_n^9hJ)t9jOGv;6Wz4C+}DW*RJEFFL_`v_CS5t` zt;%u0hN;3%u&N&oKJ%}uK10Udx(`*7QzvYkrH(h0b_$Z4qs^i#gO5+P>Kf;2uCo9w zvuycR{r-2;@0$ATDxDn`ga2$+Y>N&tY2h4VWZWeNgbLgjU6d^p-H6gUBNts{PJIzt zVohb0$Q8RXv`DoL^e#*XDC=wN=pL&F7~HaGS{5ownJVN)buRxAjb{z3P6;Y%_7Ls%GCo3a}L9#J*cb`;%I3-#_CBoU@&I+c4Im9A!d} z&OBRHV&7X?d~emXs;s1R{z515V%wi-Jd<-#FgeK0m-u(*&DmeBIi5+L1!pqXl$*1? zKJ@#wT5sv=j}l?bYu@vW;JEYVfw`TbZr)gD6u_qS^efQd`Q~p?11`Hf8xrVR%Cn=v z1*tv|J0L>;wr10M7rgD6qEE7b7>{1ZH4(eC{4{qxG{R_G$G$1!G#F;>na&j+USmq`*a4(SF{eWbWGRzNvEu-77lTk@5RNgmS@^ZpKnL@+QJF^E+SR0Q zkVR@c3z>13jzuw>`H%I$H~#cg&gX(YXK5{KJ^t2bf_&}&N8IcFy13sFk2_e;b_R{^ zbpx}A-^H;JjdLC5MI(mLSV=U|Y0+2s0EDh-qNbqcjG1J*b7levuKvqKk6!K073SPx zDkov_7-`n~2msqSio4(X9maAUUbswJh=Gye4-SxxdQlMn)dGdvHG4~o@mA6%# zO`fuI9DqIQPMPi}nYC+!8<13{wpi6dm=i)2#&gbDv5lbCVg1Psciu-9aP1Yvf5ZIztK1X)3Kgk_c&Vfls> zo-;(M96Gx%AWAq^xJ;R{fkrqpLxAzZZ16QR1C42FW*A{qsEio3T>v#dQZO#s zkr|0Ih5N)7(&uuJ-bqP&V>=!9>Qc(*G6#qVPNUMHCK)lTc;Vix0kXwvkY5W*>ua+q zGpDgx3t&bimV9}`h_Fz(9->1;&+&O75B1gXxE7{1at)KZIHy^lX0t-mEm9Uv;iDfM za>wLAk^^yGZFIO{Y93QWQLd~q7q}5iW@Z*sJu_C7Yrlob|4@b=Hz%%8_#XaoHzz0? zb0h#@&&Ysj;hS?3@jM!;ewIWS57)<^51_%IXkXjKtRpL|2@L8XmPV?OLdQ#h#@ww>OUUO~Dz8TwVAl-B|INtoM8F)x@wi?N(=vHq6?ajttIRKg2Kt+29 zElz}UoLMLrUGcCR#yL%;a!2R9Q;|`#=2T;`95Pq2keCFm=KY)rM3bT$#GS0UFsHkP z47d2*LQNw;ooHPlqIPBd;)*5{_j^Z#3?g_{Y)O z7&k0#=5E^fG%@Xb-Y{)_;yJhJTtC>DjMhR>^Svmy`q}x~x4n=Ngj~t;*tubHahfw4 zM0KL~3G;@7pZ@C_HW`rMwsd61%CAh1t=%bCcV(!8+(N@MDTTXm71sG!vuaSqsghL4 zUM5bB+1llM+kZnOnZDp0RY?#ScgnaePBeD37_{BByVneNr3n%&+l-^nT@?qIzHXROui&!-EtJnx|`G?w8MkSV^Q zj>SAKr&_x~7B|BLoUgLC6f`u094UWW&kvGPJZG!pV#_2U+~u-=#Fai;E`y_eI!nWy zPR}50u}A^3{*avXk~GJGB6mPdM>nVA?v$WSY_&CrGYuCN~c^6=+sG0>lB#t#d z{^YI`KQ@jK9D8p1{;>=bK@+;ZfiB#{?rUV9RD&UG#qag}$KK%j}AUx?4JcTRG&M8%Q~1(D{~Mot)LZDhJzCc55fZJB6RtVm^ya%MoW zF>k`)=|cP1(}MO|W)kM^9GoFG%g$$X+q8lN)a-(T6FS5#Kd3odd$6)D^>R34yt@+3 zZBv~a$j2tQ;ZX z2*~d*#Ny?6IE^M|BEF3ScQDC*JmYK@LE(hhDXIi`hWVN`gLiLaNt$eSVvk@8`4nm+ z0^vKvh-G|i1QQP{cP@GYGobc8m;wFXkk+u^9(TM}wmH!AQeQ33zm8-%y*u#!xPeCE@&7$We+DbqcI{0VN<`^iJ2UiRhfH%J8lg+~2&68_C? z#s`}JIpIi(JaaQ;(|8#l=c|oSNG`USjM;kOL>S(*xjT+}L3XXOou_R(vFP6E{p5mqT}joaoMw*qNMa6%Lm z&aoxDi-s9IkQd&NUqIuSr<~AnHBk>1F0meGgHI$fYpc@@trzGz>jG0G@~<@lJ0?=u z$vO1O?0mTlvO^v$aL^NLepA$qwh<2-M%OgBOQANNE~W%(lGGyDkeY1~byHe|J}_nz zsFup=ZZVV7^^W%}C_c;;exIF84>>M`p6)A$(4)?UaIa7tj}B{GXl={Cibl}}3dk~u zEVN|~mO=5p%!1S&46>dGJv0Y8C(1$;s~~?o?TAN$h&l1dh zC~G78a!xRKni_E#&SL*MO`$0CfTo$4rt}#)zo;UrO*VSfcvoNbfPluweAfdSGIYOV zlqT@6KJat-41BH-UgJ2-^Shr#ujOtUYZ>W&(N3&}REE$Mq!upCOja~D5=Jqz2ZhZE z`BtMs17}I5kL0X6g!evY2vs zUwli9m9%b;!IUxt^IFqj{x$HZBn-0AUKDP&A)%3A%%HETHVlbaaAp}58Vj}Zf+`vD z$y)g~Ken2cZ;Q(xQ{&@y+s`w5rfuuld242rNJdk3m7J3`$;$iPV*}&@(7`YptY(e95DrPgGqC6(7yCPhBw!OWShl zpX+vK8amc@tTp?tTCdOVhsd#7WkvSLZpLfR3l-rlRfbc!+?VGKGKlqHRa! zX%@Y1w4!dU8B9TVx}_!Ts|7+3J#d?|VI~hc?jX&SqoW-gp=7zGl})O&#;q+L{Dv!< zSe2q_N~zj?xh=7Qc4WC%f-lNU&Z=V|z||S)sB}&AlZOz%Hu_={wWa~|dCTOkRQnE9 zPc|$wEMsjAA{DxRH8!6=(ls$H@pov2qtDMUKDPT6PF>C)?t0SZ_&r!V{2JyN6!8WU z6-jDeFA?3XN)K|gOe8{WyFW9TdDl%qnfzg{h*yg>fpH93N)gJhwgKaP)tgnuY$jsL zSXdQyj^t-j>impeC##?5=OdWy3SY~0WeV4^M99wPg(GcN{brwA;n$VPqGW0e%#cjg z+fA|rD$I{8jY^XrJv-F}=NGnecv#XXqJhd6`vS546;HhD5qKhF1Jz00*wc+%Xh4WS z5XmQ(q)ILjQmoHO2K75DBA6bA3c#60t7AG%-iL zM6G3^ya^GnFhk$$ar}W1nfS6_XZ{rp<4|km z^%b|#?hP^&vpuE!%P8Xvaonrop8nU}$LRsS{cA3WO^(Wl529RMMmV_@%ZP*Rbu6n2 z_ag*713Q`7HF}?0kBQ@$ zj+(AY1%;#1Lt;Ode)K5mb4N)(CY}DGTK5+Ao19hGQfaz2lTW;P(Wq}GkNRfHsBd02 z>YJC3`sR>P-%K6#&9qV9%o_F0Va?ybdxtl&r>72YqEX*081>D<#y2mp-W0!}5uMG+ z>$VAb^>E<}EEVbgzvLuL3s3Qre}M*uzsm=M>0E)>(+LuCBidqP!M-tACkoZAI3dX9 znbqQdA|Kg2Py$#fPh-D5u6z=!{Xy=xq$wXQ?HC=mh{s+mxveMDVaRS%W;8 z(qjqMZ3e!udSt>xF@X(AC~3oTZ%~P-qG4hGyyi0My#yw?J)?e+QYgLn)+ZO8lpk+z zVUmlWqDmSz;y=taM1Pc{_oE$uVm{YDg)a&UE ztgF!1L(h8B#*s-Leg>5mib}tmPZ$$Z{EqdLBk#QA5H6qfoTv zQnyY~KW3uMmwjD&8B7)f0QQ~9$dk#)u4H6mTcXTG$;icR`M3t}VO?r?cF=rY8A1>ooEJ1YyTZlRAR+*10 zs;y~NlaW>UIhW0ioR2@mn-FqZ>}qkw{w@ZC|1t(iA*3bHYg8wEbtY~zz2<^qmBI@x z)q?xhg9p@u2iAiJ)q^jt2M?_WXVil;Eoi(ryB>VC1;qwiTo)*KeLeWGdhmvN@Zs?+cRyNG)E>}vks+I0p1H=8ZR`d-W-c#zHRUN7nhe|6q z%vxFLtq#wuR0HK09IOSq>%pQ6&RSLOFU{&N4h^j;t(!HoyI5ISo>eKW>;={aL(n_W zQ(8Z>Tac?Wd&@HpJ7&%?-7DsHAGQ3*dEIBTd}?(1Gv>>a4m zE5+q~r5Wqz9(B%9b7l+=tQjb;8<^48J21R{#>#==Sx{(}O6gbaR9K1D&z@}64FK9O z&^-&Xme$W2D4*jxT+6SP{MVteLuEtnYgfx? zw42pm>hE6FkioaLw>)e4@QM|sN~uSIbrnH-9vkB7Hww~cGeRIrckjT;8KMB(blA)z z95eOwRtJki-K$*dJe?9`AlO@eK3hIinMI8t_kgha8r6EPsjxwutt?x9aW8{rmPQXU zrFV27%X{Jc{v?h>t81Ol7%92ludeE~+`<6kG%IMMqf$bAREh&b=O8uKG@;zH>At@5 zN_uV1%)^hd@p;ZUgO%R3h{JP=gS|qbO7)bM53g*3@2@Nl>LZ-74NEm6#9(otw|hUg{AdkluBtulXgEFM57IpZdzSsIR2H;tSc>_fjFg0kC-|42sgEqibKPd zQgs&M{+wu-LAS6xfSesVb%=gW61g@Mh9Ppfr!)&*7%%~!%;lNccyh4ZTP+XFDi3rw zYr)@+K{P`d$%LYN)?tSoc}(f(x!rS)o^$l_*@u@_9COT3r6Z4=J@@eCN6((qJ^PsD z#~eNT$hmWCQ%{1|YM`FGwjeT`(_QN8Lt{Anu$gm={=NN!OjbQf64nUKv_GrA-0;qm zmx*GOH?ckuzfBE-zZuEV>&{t=9_G8SN78x<@;M(?r>Hq7{*J1Nou{`a2)2<=Yfhi$j8a}h6DlPZUe(^U zrM?Yexe^vv&?0yO6@s;Dd2q1Qv!=9R25qE;)#1UxGPDO%Y5icS(%X;5MeBFeW!P4@|=9!sRv{;D&hXtKXCo74^7X8 z{9ky|{<%50G6-)Duj~j3b%fUkTiOVW3BR-b&zrXY@#e{Taf$xPka%-e|5(}$O6yRx zy_WX1T0VPW`5sbQTVuX&D$R=3;XP7=ms930SIp-#c$PM$2G8;tj$bKljEZ&YA5~w! z^%TqX1LZQT_1gVjX{na|sFr5Xtn42e(_W*f$aV7sAriJ2r^UzCC{ima(|7=9M zLA|u#!2P>_T|@AIPe~#ENn?6@K_!wcnxD+N2%qPH*k zu0r}7d1eljs(s~Rk1um6X?yb=UnGA|I8+X+rJ>=$usG1$UmWT!4}>c!#s1P8dIx&S z>%!h@I6Tl(TG2aD>PeTd+JxQ3zP{zf?ln_^*~!z!GmS^-z(03csXE*@G;iMUz`9Ct zaO$*kLr@e4!gG(SRL%|87W;-vwf3Arxnp?hn7YdY1EuaERkJwU(_0REO4Xs>0jp>t zSEW=OD)FwbxFH-U_moDwT3PHJX#U2516!8y5sG%@%@w(q0O3@sR4E zzax0&@Epl=6wlE-yT%lPb^NOS%GV2lD+9$oSC@GqWGYpt-S7aN*S)H^yss2?({=O0 z(^i$j*Pa?KhXZ>DR)*D8<>9^_xTbGISXx`EgoBlG&v17sEQ))2dmImiv~P%lRT|j4 zqPIIdq?exI^&v5j4Su~4Tu42BbL_<637)oBO$-V=j!cy8tp-PoF9dHQ&!hufozv~@ z?kiV^E2R+7?2`+E7x7ym(@>=-rh;pN;3o2k z_CDVw^wVC%XF=~({Hl%WHy^(uj=#2ghQ``djm^h^p|Sb|zv`QrnLen=`VnUH)h+{ySQ#P{Lx@HY|OKM}v2a91M!eZnWD;u8{=^_y2BkWK`J#sVyY05yUU<$=7R=u@e8^K<4!HLVFL~?d z4huhcaL~U+J?4yPn$Bvvt>dHt+i8+Fk#(de>6}_da#e;IFRh zy6Y>!rU!zvAD(^Oj*CzH-p@}tMIFK)`M3SsuKRwl>(P65J^8g=Pu=~ir|$j6A0PPm z!@s=xUw-%gFF$_EXaDQo&;9!McieG@%Re|c+&xt3lc-%+=^ZM~kbvOTwr>@JBoB{e z9Er!s-(Re*8Ik|7RQ_>s{&KOu*wa%Pkw3hr5&jF}{Jzg75!bi@U$whZ?n~G3T*~jq zd!PS>_4+l%w>gDx-xR*d#1U7)$z{aR%HFC(P;n>>wo`5b>2!DeR}Y0j@E;!kAu+r+ zM9WTIeDVqN!UerU;Zafw5IEt|rKc}EZP}7=M%d2`(=GiY?13^XOPa<9S8b^FGSMU0 zDn09pl@dav@a;lyJQ$ns=)Cas0h9C0=GJGL*1-@W9*2gjL2xc*52viJ+X>W7vdqU% zCa$^B$KMv$y;!Z5Do%GXt!5t8?^`jmw|Wi}OXZy9WptQgWy93s(6kZro8*O`XT|L& z^N1zi%lxQx(e|K3TryDOX<>0dO{}gf4u+L-e^~96gzqo)mn%s8D$2%?(u4WmDcG2P z3Y|?db~TUq(Z}CT_?3ycWa3dgP3TuE^KRZtPIwsC5f;z+_$~4KerCs4hkd01;tx{~ zjeDQxPz3*E;-_d{tquqO$o_lr~Uxs+Ak`uykdUj6Okl~jCvD!w5VU!ID0r{X=S`07;rqE!4H z#FPDcc^p3?R|qbkp1&UBWVx^J`*{D-ME&2Bg7+cfNqT%Beh)>@p*QA*FzER2IX-zI zzr3!|VhfRET|Siw(Y_f6Y;s-%?0&GO>FnsD|5|6B+p$9!8~OIeM< zr&0E>N&nJV_T;#%hjkk9(-N>xC$2S}e}6{m{Tov6-R7c=nzA0x~fM6mx$e z^ETCw|6B;LK}fn1r8_J4={&R7hbJyME!1!eb^uekAL6%z-$(gXxjL-oIQ;t<$B1#L z_aWnOo=_21KK(8Eej#Y**Ozy-vRBG)byZCH&)})AshwKTQ(8W}QcGjr9TTrjUPfl= z0^ysg-aUX%qL%CyU37$b8ZUGu^!H;$1O_M zXVVBcWJtidDFtV~hqG`=1Dx$6;E*8!=dl!=MRho5B3Lk{YKCoK)95Wk6Z&27H?vKXI_ zpXBi`Juyn+-;u&UFI0x}!*Ir{!`X+`+Y|iI;qByC{aNRF$LAykVFUlW9IAJ-biGx& zuiqJDH2N$(acQ!C8)JN4HmQC~sh{BLZ%e9P9^M;k@Rl^Rcl$_qWT3sr&S+@wV=>$( z;`|PC6=7*(AlJz{1_v*Jayj~A)$)bpbdw;U+>nVfkRg=rU4$?;*Z>Uh6 zH*Sq__(wGq$s^KknI4nlf7+ba?nt!h%*2?SPkyz8dy=qI<8bQF zn$zYxqrmpK{5bS9`sWl5HNe;Z3UJ8&lIE%Hd%%%y$B*kc&Pw<3W23a==P{0X;gUsX zCHi>EgN=RsP!e{kkC%|QSsy>#0K4AD8_D0Sj~}h$I5T|9V1vxvN||PT{HquTKlbNg zr)9`*W7xhw9vh{chm-EV$K&#l=}gJ$q?}vwug&}K4|~9ouH#=kj#E#IXurfjZO+*W zj%GCOKrB1Cqe68WKTQ5+H0~t7$pMF>fyR@5-kiqcVjP|}9(KC^yxSFHYiUGS6HKp1tY+ zv`m;1==;gvY<`)V#*>;~+IBR@^NLh^JpA;$BHK~SPa3lgJlg~8W;`o< zlIPho6Fhqj`J3_V;f**NWdA*sX(ktBlM)WkM;>;%A7q=V)j!3vQ~td<&(0kMw#Sv` zS=qN@9A~9zvhOJqETRvMx*0Bj?x|?&W<_7m=sL!$FOVx)A_4=Hhf+HKBgL7uXn(dO2aL7=Hb3+Qwxpg?FCfjvy z6F8?P;QS^9r>6$ztcLnbdU!;;$WX7(9Ns7CyxPNAu&}{ab9M@jpKk}q@Az2->hshU z3e@H1 z^haF#eY-!D!t;R|o~28YczWV;e%$)?g!}-*#PK!&(qq)zw)nj9Gze*Y^h*I0CuiO|Jt*svCPaAPI z=p8-4Xr^~O6yp>f^yhJTy(3LmkL%GSu9OVe4z6Z>`q(JAJnqrjN3ri`MRH!#F-k;+knw*JfGfxvp$|5Cx3F?FdE(8l*E}DV{?Anyq(=K zPT#j4myhqMoxOFOBkWc;je@h1XlK%H^&t754sEr!?Ra|Wh&9B2ohwWvVhyB$g>=Zw@{om#^ z`lnG~dtAO>JdW?Ca3p2&DsVKjNquh*IMVI-X&OhuCUx&9IR1SPIJ^w@?f7jHM-!Pl z`}fUd<$uR`=7r*^x=m^o`IEYDdha8{q-SH$im}&{lFeI2!PiN-}o5sLp4{lE0Y@|5ziA1{vN*nP$BF@l-oJ>~!CMG6_4y!}kEY**tga zD6mK4;m@RSBzbuHADi>=XZL_3-HtozI2vqB`J(XWMmT@)a86k^;{48B@;0OEpW`-j=$JzF`LZvD zou=zkNgOGebS-6?&6hf;;cOMcQRltwuDQIG(D{tJ}!GyLoj^8eeK&ePR@RuS~TojVC>?p5XCBCof8`zs~(j za~?Rk)+QCIkCUs(uQsK5U|AAJYMk6nnP%hUv<4jYaqOqrmpK(lqKx;Yf~?N5Ro-oUGUbj&wWv(>N02WXZ1P zIEMCsBRx*un#9p$oNNV8vvG29jED6XJXIejkCK0P<787BUuv9$NY7^Y-koY!8c%wh zT;uT^cgnK#IN1b_W<2nbTANg;K2Gi;f3tD&u_TVvIQb1_nvIi>H{hs`lQ1)}={UK$ z5l6!~SxT8^y38#x4$r$DcACFForIklC$|E-8I3+O3T%%nJx)HC!jT*&h3v$p#jpSJF5V<78+Q9N*Xjj`TRWH;JRkIC%g(&G`1d7|*;=JXIejg`DFlPq(z4;wNc* zsc~{5<(uK#k!n{OPkNmEhsU#E@oDLG+E#Ehd*HmR*S zpZzh_4iDSYE6ry+J&q-8Npi}-pL1Lfe2rbdC(M~c%aA<3dQDshzt(9-0X7{@SySWs zZt^yx$r#EwJyC_~G;*B)@B+cC}Kh)!LS?9(M3={|KCl6~4o9<|f=>5)lTsXo1i zyv_Rb=(xVjaa5q*r}vV-S)abT5l2Ix?xajJSv^0-;pyyQr)hCQ5_YOj&m7adPZy5@ z+v7_2>CzOAWS`yzj%IzjY!5in?KsQhScW)EjMK0)-KQ=?vQOueC)uYflCV;J+DG1I zeYz^HFJ}X&K)p}5kiS`<4mRRw=+o_#Y1XHe7>B2`hn=RyTavI-eL8(?^FBR)6xbeD zx=$}j;YjxBW^gp?)64dNBi)X7)p0b8)5n3|D0`Qkq72DCoiwhoPv4(}mFm;^6S(u4Sjk8Wt#Qr^)U`lXAe6~i%%wDr}{L=H}BJ1M}h5erTg^u z6pmz{_JE^VpMHK1IMVI-ipO#CDGm3t?g2ip67wk;i2J%e%6q2bn%wz9u+p^~%E-ny>x*uorR7`96LO@fQ<6)wxF+FxN=2GozErmD188ZoI0o zPoh=jKKW9*2fWi0Fy`+D#)%YZERAn~y(R`PPn2Ik`B{nhn~CcV{Yk^sq4-KIZko(1 zQn@@>4bG;#e4qF>^pO7m;&_zHx%6sY&o&$-q77w8W%eT;H+4&CmgrW-V^PfrPs?2CN3WGb-$0g ztFL`2cXK%iP9&f7UY}q5;r{BOFmYDwPT(vd1O11Or)s5p7A!KeQk{4BVaMRQ?VM8o z@Vt2>^_Qwu+^z&$flm?p(>M|zzJcdVp0jxB5FF3{j5O7IGvy}ndjr2JcL%>ppMwvq zZG?UL1B5k)>D?vx!&3MPo&wMA_}WNFo;edH29x>yLt7yj=2v%oj^;Og4}NE^5a7-# z_(QBm6STIdJ#SPb{!=~P#PbZ;A?V2$f-+_HMYvDncS&(Wd3ea($k*L|Pq)7#{AM2c zdpRXj2+rmAebh&OA;twyL9Z;n1KNV6NR%zi6vvXfH>D4-e|1lMpI|n*&c)-vHex68 zMqVXCoq$ut^_PhQ8U7Si3V##!-fMh*+}O@B9qnzotWvYNw)T!Oony!4$M3cGgf{RM zf-sm5^o?Nu4)r-dvorJO>=U`)j|mEksIU4)XUg~GcZC0+!bJ1`ubv+*^!cwKzs7cu$+dTMj?3@0 zcVV9wyl~(BUv%I>FFAN}*OZsNeCo7Ar_Y!*`>-SC9C`HIW9A+Es#m`zTCi}@aVMO( z__eQFf)sxJvQtkx{fsx9^~N`y{daFZ=iK7*ZafRFT-CdJO<#ZiKzZ=IN_A*>?b>zg zH@xMo=b!(!3ohJv(M1=({gO*Bz3d&EF2DTm-+9FqSHA1r@7{dXd*1WjtFM0F`#IedWg*)!J^Ug1R@k?L2>#i?<*|+Uov`uo!$FCwTnw|#_ui|$F z-6^>j;jW<@XF~F^RK^wEioWu?Is3SArM}gl=ew`A$}99__I0}mvs1XD)vbn$w2|GovM>@jwgp#y||Tf&X{oS*E@iF zMoQo?p*$F_TZL1(qC+B)YFH3xHV4T=o(7T-5a?c2n&}_{w6AxK{MZ#kd@oE6&ngc$ zc-|W*xf-kVh`P?3=NlsLj@_kj5CV;8(9B>xw0aU6Tr;K+tl;-c5Y5wws12DSzsq^L zd3tzCJj%P0M}5(ocvcf$!_&vp&ojWIzlUEiF}Q*!-G6!~`JzYiL4WDEmkoowJCEn- zd+@{0$fSu4KK!O3OEhN08*dw1uy%cv@KK5QKML=#*G48AB|rQB?z=ylzVz4K z>!VM+;k*OidFR-U6&Gdx>(0}z@0_*p;x`N(J})E_f4&`Wbx+8p#v@JDz*&#i^Fw-?NZ;=Z(N8s(r{?~p^cLVnp075%+X4|j4srGeg3Pwetl36;_c z$lsWPW4cvk)XRk5(1Fs>x^iVrGARM1xE#-BrJlHb@+MpAk*7WMDS5a9fsZLmaV>P0 zlR6I+FSrBCE4cf_-CggXoN=o9jbgb>Bb?LKb>^#dxyWMB!k%87gbv{o4hdVV$7;z& zcTETz#9HRWFq9|X>IQnVUtUG4l$O7}{!&lxaDU>RiF-20PpXiJVtu{+xbK@E}&Id+o@l)>Sla8RoTl;(<07T*r_f;&Wmaysr?N|o{e zUf|+-83R^Jr8V*hI6R<`Ir$Tg^M=c?eQA9+vj;9tg>|T04xKZ%Qnfr>fp?b=S2sBS zJGF9_)&oIANW3Ukt226Vn@VPD5sha2siFYuFAi+5WIXUWhp@twKRK$^#`q2(E0a+ZE!-nQY=(vtXG^*+u?z3M(N6O z1u@m*l1`B%uglsi2+PN<(ijf*NY1RG3zPEkU8KeO{_A+;orS-g}t$C{}}UC6$s4Luf*`V#pc`-_ovFg>@JEU3+jxwOw`paA(1M>1lpGJQ4p9VbMdJ>6F2mDkyPMch?)k zAKOtd-BFj4XHYKo5Q!SaykKJ%wsJBybTkfv^#@IKa}d9pgI>oRCmpf}7^+*`s{V3M z?}`n~G$>qZb-1crUgH$KqDz6X&;V`Lx(iryD7z23m)1Ap8No{O-BrZ(*U2NkdXFOf z`S^PYU(NGAp7-;7fXB}%*AV_7&xd$Kvy;n1$4kC1t;zRACf*l1kKPEYWlp*$6A%MeU*n|VBP#>we=XbHj=b3|V$MyNN=qOsUXr^S-9ad;8J z^)w0BQ-+7+5w7$`MC++et{%_S3&K-lar$~m(&J)5Dxjy8%S+@F6aVTaMi(GOk25c3 zlA_9?ltr-&T__n^sxC4iTBYnsNX;e84%N6SDj=B|#WHgVB2y?3n2WXEaboiHx|lq@ zCMJ(7ub}>?tT@ShpDrF)8jHqLBpOdo3dOqUtqym0BRy9P_no5k!qf7Q%@{w}>DTzn zo}o#Jar9~s6oo#$wtB|Jr*L7oeEuHyLu&+m9TUxe+E=TM$G zJg??CnWw~4<++IGT|C$Ge3IuIJooYZg6B^>dozE$h-Vhhu{l`_iC5uqjvgVz4v_~x`+;*?t&|tdYY)5-sus1y;m88i_yn^SIJSXwIiRV0?xAAP^ z+064no*Q^R&2tyeJv{gGJi_x^o}E0M@Zo;qWu7B>=JTAyb0*Jno|QZ{=_d?V*HVAA zQF8giJlFAjgr~d60zfLMH%O3nPZ#y&_h+mDLVo?a?+?sH;ywA45pPaH2ar$K(}{~t z{_p?Qb{+tBRAn39nYmjNl7RHOASFN&rrjw^D5($(0Z9M_;$>UPFIH4Uuuv=rsMrui6o0!|uu}3r=giD)*}J<5ah2RTbMMSKbLNz_fs6X4!E@aOZ@2>b0_1?^X!pOkPJ(aa>)Z7sdus4eNCpf@Naic-Zqf;@ksr*kl za-6>1BqixoJ5*IEy;<3Pmy^f!b$2T}mXvNqQ`!&I4(>i+N2S;0f>KvW(K>t7-IP9Y zd8vz^^r$;4s_H8xwWO+=rtGe2$~aMO=LgER>h>Lq_%-+LQaZIBb$8`pt{u;nles;2 z)!H?s)Txe>ccl#qH<9ICRi9E(%Wle%N(l>~qI4;5Rn*S$U7@0OkL#SL?!x^P#hsu~ zWBWK|?`|b6DIGLQ-AOHJlS*50*r7~RFgccX)pk>NR}WW}&MrkA*R4$Deyi2Jl+(46 z+O2eGKcxY*wo}|u?ds@J6@3q*r1zAxeY?l2y(P87;|nfo_qtT|T20wX=@gY|>SKqu zDPP~SO}j)nwYRNfsoGXjdV1AkRjh%udndJBxklZ2o2`_6yLK9kV-pVX` zURB5QTn8x@kFTojJof==m-1)PZ3@EZq)CFFRQaWX?N#F`OOv&d@(Jpg(cY#WQ<^)@ zD4nS|6Zhvydo+Xlb}ENxd$%iHhbrS$yPG~MsY*ptOLU9!5k>3TPWEl~9wu~Z?XwiR zNDK$9#KTQckM9x>xr6BG>^x)T545<0&t1f~{P>-+j}q~3NojBER@8qeJ*ARzIrW#6 z-k!-F^4)c)+B9B4TPNM59Jf79;~wws;P$))#-FH2Y2*Fd?d{qQJZ;Csw(*+Q)_!nj zn{rs`t&Ap~eVV#MTf5fL)undsUb;$ab4zBIGC|qCU75(8x0ZKpkCmIa=8#fb>2>N` z-r08Qy1$@9Ah+(xu%E_%Vx9czz~9b)GoR~Uy8FD7XDpxkXBG@)k9R&C|H)hNr)zF| z_T~Q^_B-vE9ov*cKQyiT!_RB4dD~4q=*3lU{^LKM`hM4QrAMCq3!C%+P-`I zZUOUCdC#z@15ikF{!>AA|k7Pb##n~A5PzO90! zTwjKr;2_$4I{%5adSg2dzg@aw^^o{6-xt4MGs5o&mt{XMe!I5iZ^PB;Gz1_lI@p|tsg>@BU49lAEBeQ?34QYV9DS<;<4**Q@zg_`F)D}j-!3zzD0R_Q+cbV zvfxACyYBabLsGo6;`(zbi{~xMDdqb9m`{1Hy6;)F8tR{rm-$KC^K*7SM0;xI|NH7I zPrNS5-+Ju2$9H&r@UG`xc}A9xdG5i7Uj5XX4gY-QIawb6!_#KGbj1k|ZT;$tvON9O z_g#L^9#3B~<<&pR@;TQXZ%jVrt>2&f>dUhHxo_Tj&t-SN>m$LdugdbbFZ%PF*X(t} z@6UX-v_aIjeBs)|ubB75y;r|FUY1XM^8UqVY%~4rPrbUWEW0PXa%z zm}`&p27Z6_<^T8U-m?67-`V?o`@B^@YI|*pEWdos!`FQ0sq=5zJ6zji zzf^v0x-4J%>GA=uEb%^l>}#`S`QXDI``+`B$>U``}Hlog&NUej+?;?`3!Y^nur6S^nple%N z@%uh-#l`0>xca2muaf02zjyz^z1RHb`BksqAj_A1;n!cd@ypNOdfDr@$nsTZt$P1c zl{@}@$Ln{?@>AE}e%S{HXMgdL*FP)Er)@X!;eY?7>%!+>e^8e1H;m-?eLne}|GfT) zEZ_aUGoOC!mxq0L+YL|1a>v039`MMdQ(m05;Tc)}{*^;ZKfL$ech1}JoGefHR@*s$ z``iVuMH^m}D{F7gn-eF|9&0lC2#7?{9Xwb;{DCuiQ$B<@LY6WN_#B&&sp=Da&N}s5LKL_u-E(|JY1r zl`Nlk+F74Hb8YwEPEmx1psj7qjz2r&<`)-zc8zkbEPw6M>rcM&{FBeWQn^@`4_SQm zHy&MB{>I&kumJG9H(m4JQ$BmZhaOjiWQyIWa?^*ueB<1ozo6VA%llmH|J454^`CfE zxm%V`x$)YMue|QDe{QdSR+gW9=y!`2KK$J04fR1;{^g9l{`~B*R zvOInEZMXd7J=eeTwE9O`o;3TG+vd+d{Y!sPUzX*aZ#ew^moB~Qq7Lm3GU4O79Rz+m)@i*N3%Jq|ebG)`~_WjEThd=3^eD|QXt1O@Q z)NSv6$6IEvyGYwxmZ$#gZtd_F_k8#h+7wy7Y{Tq#9CX8yOTVHCCT{$IU%2>&kL+MQ z^Qkclivyh4EpVy&W|GdkZ%EF#1>;%R2 zFEy2)$jh&ys|mSH*wBPdRFpr@@$k<|_nfRRMjQ(F)Ay_X{tGRCk8OX|P)*9QYju1v zzh;^~ZR&vwf(3Y#^^M0zgN(F1Sc|+=*UoqI9AdBEf7&$NFu?#gfB-TVzwBea0zZ<@ zO7JKZ-V;ou7^_HxHh{5uO%gYMUz|U=PzaA16c*FwWP-h?F2Ev`Clkb8o~#wl3Sq97 znSX$A2@@&J74AA*3-|&kXFudjTicI~%m(~#K85@u{!00OVt$FgqAcduA&2aF2nKDW zx1m}$ow_VZSM~O;T)L!x)v38Dx2KnC(^Vu^$Na0|HkvLXt!7c#5@youUGt?**k@QdZzT8)qB?D z$$T!>*Xp`%=%#MzwqDj9-PJwaH*~`=Ov5s4qii^aYj}ol>ZW0ure)e@*>p_T^i1E< zEyFS`%d)Mq^r(+IHqGc zwo`T-$8|i%cXiirP1ka5x9mEu>w2#5>7L=4p5@tI*>gPC^E}_Di9Xf)+}h_dUz~b_ zfArBW@G0!VXBnW?9(<<3GAz?8$y8bU?mmoHVqO=&{Q~8kDSsN9N-v-1^55=t<(oJb z@A>3u)21yB$<(!?7nii~FijQ*`)9z7Au@RioBgS$o@Hk^vWxf>@9;7{#kjeVPqAhR zuWUYs3omrgE7DzMgPwF(2lon3i*RxdEsc}j-pSIDOHE9SQ`^46eT2>D+kA@W_$!~n zmi8Y$JNPW>5qD^qP1)tu>nE4DmiD^h_iON*?8Eh$b{v>JI8oTkYDuTh|^~58hciO}$V1l=`6hl=@xunejj9 z{-OFK^;zW??JuamDg9RcbMIeD|5pE7dPNz(-@%72IOejCe)PsOFZ$rsAN%wJ=YOiB zv)ei3&=dat^mj|!?&!EDocO*w@4fHKpSwO`Nu9i{)D%kbjmwUjgs`Vp|xkd@4{Q|yzi4= zdHUY_Rt)^?=O28>UT3yzrKwt~DF;nkclK_YF>%+@-rc*mAJ{&-G~s}CcXsSu+PgHl z%O1Btv&XM@ySMM@+VS8yz7})W^QsqNCP9PX9g(tc2>r?b2B@ZSAOH>a?z-&`-3zE{_EtM}_H-QCwO{w@ zaWfA+pyS~7o{qP6DD9K9_Hl3TQg;h?KeDT5-L3D~YtFcyj;-F**U{6l?XFWwJFNTS z^myU;BfER%&e`S2u7z98>+D%~|6UV%I_CE5rX4ZQ)h1A@-`TU?*{SnjZMWlp$7I?y-}T zx0L+Otq&I?=bC?ao%_T6dp`D?_0~jXw~h&=uJspxpmbXMR$6!Gq{~iS_ur27pPhe1 z_p0gZ{@F9sHMrf}cW*m>+wmuM@3iiM^+#yu&78R1xySC&(Xs9a2eu!&r!qKI+qtB! z#~$0)uB?ChfOS7Su%xX2#kzm(KflydQqS3X_WVQEeQkP&QaZkU7h7FFVM-|;e?rf? zd%fMZno{cSR3~(-yY8GHm$ufn($s`2z2wp>uDs(@4}9s-$G-WkpTGF)4Q(Yk0o=ZW51Dt=;&U(M z%g;XWrN_SYKq)z9Xw~=i6@`(j!K+da>X57 z^5{38fAQCU*=p-K^WtRPxu1UUp@)C)qrd$1obxWa<<^HDe)RFDp8e^O*M9jsk3IR+ zyamUc`1W^HK5*$}pSu6^4}bNs$A7f-_B)(>%0K`0`i6DO-}Uq7C+x9eVAtI$XTA5{ z`;Pw7gWK=0`yO+TSa6J(B=3FS=N^6L2haWGum4y%blIxaSMNLRpxf^I{KJnw^`qyn zYdid!YxT?ac=D<5J@e#-1;?Cpa%b1XN&6l2=a*ItxQ84zbI#>gEL^hs8{d5TyFdQP zZ(iTf)?3-@?B`2o&+gi#)UoyYyCt9_5I^}A|2bt$ETN_MGJQ#w03x9&N1;x?Vf zcWR|wd%CqQty9DNtBo(UYvVeU3EQt61fu1(Yq#r}F=``H_|-m&YTt*2^xPTX_ix{FI^U$_0Z?cRS?`$5Ctg_EEDZE#9&+n-PQi}Jq3(~lFG{_<_P=Tk4LCE?XT3w zN^J|HffYjo%aV$Ox>O_tq9Py=eSOk-*4MWpS<}~7sjLZ?R5+}7fs>jR|0Yr5IZ4ph z*Y8D%9{769S!zga<-}2M$^ao9c79t~sOU-TmSe|5pbhoZiny_E*nX_Lsh)(P={d1_ zZ0j4#_7``|9>y(OcIYL3U^%G~gf@3{(pXRZvJu3#?M88`-LI@k!U_O{zP^3q7GX&7DsHx#(B}UCL7>0I;mV%NYo+;qf z8oFa~-q+KlW9g<=w|a1+%2p3ne8UPY$1OXFUUnk`tZ9Fu$7Z>#+w^N>q@LaRzA;v{ z68IfB(+bcalvVWRN-Ds8MYZ|YGm3BLiZ3g^Z^x0HgmGe;p%;s1jUrQzY92EM3)~pAp!?qBYr1=ZRmEfLQ#ntj9cY5~k(A ziapb%CAwa=-Pp8rUU2FgUiaxOx?*;9At$#M{!mGF$pQu;Pq8u(&Pc7Em= z^Wq9UZ+l*B8nzXgp=nUB;oFuGcu5$AAxntYv$jRON3L4FEWcM@UqeBRsHH0a@>W2d zG5xZtt7jK+vJ&b+7}~mNi;)$Da-8X@>x2#sh*R4SlW{k+>iby%_@bfX*slb5bIB~A zyxh~|DO-ONuMF1Y@1pLtWG|{{qWFz`Efw^5*G*C{2|_Qz9ze$gMrwHpJ>~16@0jWM z^;@!eENDr!t7M_#_+FW%g_Xr&2$bczh|wT1Jl{!t1Dk@r)tMu_9ErYactee6#0v?c zC>gBQTRT&+gVeQj-!5B`;n;FyB%x`=maV%^}(gTxWj(F}Dzc1_bxJ)R|Ia|I+Gt=(T1V$4d+Nj~Br z3dK_7i-o{Q%Lxm!r^n%&#@>DsrLU;nUzVH%b7`!{zUic?=ZUH1+Nl|pgTSH^KZ>1g z&ucZcW~`2v4$NGgrpd~M5(>Bgh;d(Ei_>B}W69;m#W1LyshH)+)#*&fiVaM0LXb&~ zC}B6(6P<@G+x~Vfr+AABTbvfP3S@eHD@3`1+0nt)7rTjX1y+Ep(a&V3;MiecTPdfu z-%@=cw2Ev;5`g1sQ{-vSDJQWRJLSNMv1-zz{gLIFG3HS#u#?y_qa9jFGIh_~@FF%6 zNdq%s`1p1ZVDYq~P(G{?28r%Cej0mLxxC{UEe3AuN}_?mGb*bFDwqS=a+Vd(B~C9I zn3bKZSPVC;y_TiZ2HO_9jTy(TFZQ^|E_Ov*@^&W7B$K< z0^wRIBPx{>ArGfz%aSrw?M%fl zBQ*Fr3q{$sf>;bIhIA?#5txqdv#9U#fiX<6QClz+2ylBvMC{ZzqwaLY51H0T%AU`B zGjxx(#J-2zYMR0Z&mI%*dd-$-%Zk;@Lqv{&v=|E2?M3v=#@|*_odv*3+00YNvK+Be zhjAL4pzOxAtU*qN02pR%GmCeW&DK%n~t`6+3ieCrToW_>mVR z7IjB{nTd~s!F40Y2;<$?Y*O89d?MZ_o8f_2CMzrC+L-Ns#n(u5ffXOH+gHhSvf)>5ph)r>42S1?}y0WZ3t_@y6|X@zBmX-az{F(#0F zU7?`*mK!iz_1;TbHDZnk9$zHj;M}*N03xW8h;J(*2u4JbWxXLhYGIus%kSiM0{1O{ z21u)B+z`SR!buEZRrZBj}%={cdBB< zXp3nQ2707NK_~>CMEAUiNviw4%eD~i)k^A@1F%|AV<`{WYgnD~b8>xR=*1~3p^1;m z^-VGO5Qu~`%3)bX26BQox6<(%YicZEAgEghM4`fR7dXs%*FzdYW}&LUwL;$$8!Z1a z2ll?K)thd-dt*u1IOKq1ObOw?G9cZh)j8kl`wDAv=wVY}`wt>77UD;UA{rsw2e!kj zw%mPM>C=r(Xe}RAS&CoT#6GnirC^4%QulhjeSSn;ak1r zOyA7J8$fg-ysW4^Q!wkrqzdYSg-_G+(61sl6jCE*1R)6rj&E5QUiAGoYpi9>kegp) z^>VYUIOt1(W5>E#*7Y|#?;Ey?Inb8HdcECXDSHbI$ES* zr$%DBhUoRkXK<%34p}R*9M9VSw9Tj$#f&JsqQb0HVV%HeP-YM%wr|E_N!80{5~4n$ zwYiQH8wXs}YK%*DQ^dyf_0=6#NAGH{5-nqs1veS2Tp65ERNe9i6*N?~{?IMktRaa` zV=*Q8?6>7K3}PPvBs{QXYwCw|N(V9Z9SgVtji%4}-_hm$Z0YZ%NJw2ZEK^*4o$CRK)05 zydDlQc$H%&qS$|YkQL&+I0l+I3zQvFJ8QA=_7)Wph>h-${VU!4#f@d50!9NJ74s5C z%!o~#TgT;h}@%p|p(GmG0Sq1OY{D=`kUx*t{?JwgVFLpx5eszqXB02@P>(kjp~s0zNj zd<>N@oHKv!$hC@JRCLzjfB}I`n{C$>Q^$4?dLuWrlEgs=H@$a_p}G_2Etq}Gi6d8- z{iYIlJWR;oX27xki7Ne=&~V!bkbz<|0M9d)Dzjc2xyrm}UB^f1bMViU%UH0*8%<;6 zjyTdCyfysa=$l_W)^%1-L25crLVELDN*FB23DOhC=8uqT2$gR@k6%9D8|-rq++6C#ER(}mN?8$=w;LU zo7_3e28QtcNRLi&C|zDrSP>)%Z1ma4YdBe9VM#;mO9!C{HK;jCSvn4FT~lVH zB=#GlcJ)bW4XOXSf?6Lsj*0GQy9_h2RHMH{DEGRBG>=EcIqamy-m7aganb{8hN(iH zudsg!9|(3ICykgU+}p5&a-aw7=GdJLBb{-BGAnxnlk-o2b}`|+I2+)QGs{zY(_(Gy zEmm26!ul$C3IHmeJZCMzw&JZVo&x{Q(&hQ3&J^NU!4V$MN-_m6w$S6`iG?CkM4a8f z_pB)*rd>q;0(bTcq%kYLIm^8TpHEaoc zFTRZ>0#2Io6I6!!1yhKSHu@86Lu~OFhFlwuj5&ACCfzAn8;C8cKQgdoqSv#^SSA|& z5qtHyv;t;7W^6zzd8?5jjmzZn@P8ebz!w6vo z=25$ec_Nx4lnEATrjY9=c4)X|-3#9`t?`b$5yHRw`XoaLzsJO9#f~M6$Gp+A9{Vv(DnTvCsz5hr`g&19qgN531f9-n;y5=MN~#{YJu?<-3lBLCQmMS@4#T zU(S-1ONY3w=`9QGn48&wh0z7$ppTIoAH^|Ks(*Omj@;^Ea4uiHtU@CUAr-|K#v&)Ogc}YUV);0` z+SrB{TQqu^(0}_KE3sLBBlgzBGZJH=S66embcviEGnX#0%(X)H$}1E)TZp+kMILZi zyJ#>5eY*b{l7;3vXU zCRZveVULMU#_1mgh8NmGJi;WjSnP%?W8Q2c@4nd28aOCkzkCw(qrqhmP))CnLnaN6 z+3)H2t4*{@Jl8?$#P6t0>e}ihR|{^=#*W1m#UwP%h-rv`WmfVPcP#I-Zs9f)CrJc^ z!3+Jsvz=4Rbt7nQ#zP}qUxPu+=D{|wQV8(D7*u zYv1hU!NSafSgh?KGXyt^<%X$1Lm2UtmJdjSFkAZNGJ2oG1A?YV4jum2S(~yI5;`Qn zRK$vKJt`Sn2*%+A+hp1FD2%p&rBL8-Wo)x+ITrR!Z0K=nE;%TxIhTJ~uA+X~waZt^ zgMNl27C~31o%q!4a{u(@CxuF_&Nvm+zI8-{}*L}V>nr!A~+TDW@YGB6kP z*0Di6BMzXGYF@cc6x=S1n5>uO;@R(70p0~)w~;c+j&3hIp!()(6C_g{5tl7Hb#xkl zBN&V9^4hX5_o(5e07Pu839P2*K03AMaOvw?C`q8^3%VrM^Xj*a zeZul0Mw=V5W*DaJBC=EcyAG2-msW{vAr&tbd2XPRks8tIf~Z`07Uc|tSZ4TfYO$LO z=M4W~IfzdmLCOM4RZg(v$H2Kzgv)D2_$@mtwtpAg5fjnz%(caCmMz9|6|KrsQW>E! z@D(#n#6FH3iM`^Csnw2@W2+Dm#pvPZet-suHs~R$8X&#iJ!90BC0;s2e=({1SFZqp z2{ZwFZWM!)M1e(ZKC`w9$<_AQ)r9TLDtzGm8T>61mAN{xfOz@%UGc%=`$^vO7W4uU ze1nuAc40B31WzhE9rem+FEPoFW4V_TUUonwfkc&?fdpiU2+DrQ<`tRoS+#j1AO6@T z`Pe|J!o44wDSl17K=1YQ%EgYmJb>~JPJqEd^bv7F1VOG4ik;{<)?m}a7R9*5f>-w5 zH>Wn`awO>-$^F(OJ@F8@=UIg^`N{I!v`o+xD=ku2qOVhG1HZOcy{oCyY&$kUrbLDT z3KczJy)wI1uQl=6);MB$1}r{UIkD|UsVUs7XDd5Y#1@*Vz7?s&R;0*rj^Z^|P!gfKHdwV<00Ppb$+FnwW5v=TF=SZf(h&497E7c* zBRXF>eAF4RdWGOWtWE%d48wJRRT6M5gXsb#-(+Po z`<40GXop)=FcXT$pvERHN$mF;8cob7QamDrWY!1){2b0Pg;7ih=NKMXpliC=``GB2@524UTjpLIWAJ_ zb(yM)pNYx2=zgQWZE{9lOUrlB{RP0gpXK`Rg%mMUdmV%XH zyF@%XY;%w9^3Bf!U9M%Y@}f_b#hj3*_>3w4`>!Y%u*e9x-3RktYsinEM0wbSJd`sj1^IG=9#C<89q%IxTFbyb<;IdCaw`;c6O~Riq|R! zvfNdr442K{)s{&sD%o5NZE&9{P7)-v82I#+$`PWDddW{zFXE1;FXFN)WgKI@(GHO& zVh%B7(JO^v^n+vS1>Lm(j+mYY1|MgddzErT*5S3LkFe@wkCHt}Ow=n;wMoqF(7@ae zDRW0%5U_tGK-eUqYIRw#Z9*kbL>cP{HfeCRQZMyy)SHf-_hxmL;VlA98@dMjKV9oz zqty2Dnn`AG^-zDs5JpzyZA2%qLAdaJl<8}g5rhkL5s+X>Vjv~NiIIF*Il8uQH;G(L z7Jx>XF<;UG(=&h$0Ssg;B0gTH%*!@JxtIv4oE7azmaTcVk@xnYxIBA$Uogblwfh%<4|Ufe?V@gcEB~j!Rey8VfA}^H*gx?8fvT?jCGe z_$YAxq@Z3tq8wP2ooah=4u@v-Ol_Tz6~uZIP?qyiIxt_dSn1^Axln#KJ?yZ(2kJDy zWrmKBh`phFva$HaEqXt5@l9Lwe%9ifm7})Y^L}iLHqKuBaV0n6$T?lp4QC500j~vH zHEW{~1$ggRT7?@HT_q}~j&0nc)D*j6*4;HijpQ;*_mEp%oMm7cV=MWDGJVvAg4?0{ zE)lj|f|Zb507?_lfq`4URdKQvYh%?M%^Wd|%j7V{KmuyOWuqtu2yoVIo3_-+btYTt z02^S^F5_oJZm~l9cIB=42o@0uayvdQSc4U7p73-?ySNzrD^C~F_yD@6JeFuW#Cy`k z@K{X5z-JOB=zwTv<{e{~9DNMB=$*I@uvuVCyHikjaL+@lo67$F4p^#R)# zRt|P~0(GQ2Vfwr&bEWK*jil^n2=0V{vgPvI05=$Lp8SY@NXaimRp1&8G$A$uy!W^u z?q&7fw|NC!C`|~WXRF^dE@s)N0#yfUS@&@D8iAGQ_th<&c z=#$F1O0lktSs-kb1d##jWk>9b15#|{!8sHUj|kE%B$i`r*dSO!oJE8zSf3iRGGWw| z3H%rMPD}*xvgpy^(~8^Z=R9gCGaX=u2{J)QAO(2=hL6`5Wh@jfo;0vOqa0N2WDar* z4*HXj{YBs-Mo#2+u(~m^V0zg}Kda2n-uf_R;TB#W-aiPBAW6y?v@C$0Nn(AjPy&Ws zIR&s46zfX7cKv8vgh0l2i1KB@9&*2u+ogxQa*Lk>X=JCG4O>iqu;~25+)|d z2Vl0iWxlA)sYyY_U=^lc7z~>f`35&g8RW8KAn^lnO9)7LK$%%5{z7Xn{SOTiut2L| z0i`by_@osS6guKRmQyS;JY@PMWlD7n$ca{Hky+b;E*hBF0YT^%NG0#Vk;FYc#9#q^ z43=bKZY}-GiZ}dHpF2pF;Di@0P1#2l`;(1PJjJnVn-3N5xvH$z=`z?z>Pi@PBODJA zjxR>57ugSQfwdK*7=ARYepqe5gxg=)0{8Slwc}<^u|r8~-d7tW&cOlUqgW|aovLsi zqy!tY6DQyfa5-6DQ}(aEEDpqk&3b|!#0E-OtOukl0&MHYUsnzyo=KRL=&REO7&#bZ zR}e8yB2btsunt6^83<`2x{P?ON0eC@yE7ZAy!6B*1V||2t}%%&$xPky3yO?xc?jyl z3y@DdrWxwJlRUclsv$0c1YMT(4eK|?^2d~c|JmLwp@j?`1I-qzBqnH&zIa@5We3+8 zCxp8!mjxu?I=3Y!Xh4oI>jSYQ6uJBjWmervu#sJ8NQ#3S8HNb5!lVucjL=U4blh($ zQwyU?Jv@oMMQ&65WedN3=te|KVM$7?Z*9)fw7Rx5rFdd7rD33DwX>b@+sYx0dkN!# z^gFC#xfh=;o=|hLZ;&NL3_92F5fkY=EL$M^o>2BFL=ds`WxgAJ2X_?6CLcq$kyrq# zzBBff0n0eSgseWof=f)mlS*bLuX{xTfSSJ+SI|(!W&(5ptf=QcrJPhVndbJxiWIIh zn?mlyVXtmldK-lfULQ{pIvygUumlnx3qIoMI-#T9WkP$z^b+{~xnrZw*qnd!75b_mgxyh#uJN5peEiR1lfvyXW;6THD zUO8$L+hsV_fec&{#I#Vbi8~ces*Mhttb$JkAq$R|CDLjD?`nyLihwBCq#-S;`eu(f2#nl8bNW0I}{Z> zuz#Iz(qp0lg3S()E&mE626It$@ABdPcb^ z!ynWsyBKyjkT1@E6sVd60ARSbW;YyI3E*dhc7n}Hkb=#K1r7n)`LA+horPAySr%sb z{TMDa)9s8bC)j{+H0Q4tcnacu02Kqw76ilCuWbIR!24hu^spEhpf1wzRps>TL5H#1 zRA*f=wz8=u_n1OFmcPlcIhop7mqf3C{Rm@MzmA`fBb`2QLDdN&p;<;Wvb-1@EU~B2x$0h0e;2wF2Wa=y>NDMZ0A83%9UxN4dFlwxJzThW zu&^Y-#{%p-K3^S+JPP%{jr*4{nz9oZp?`teS7*eMcC`izR=p3mKTNQmV3-jQK6s*% z_p4h_yK@P@Vc#O>7wmo`Vrvo1<^4}m(; z*a|fawnx*vNS$BUsZl}4>hH_6RV@2HcroagJ>ZhD&5*u$OWw|0e94x)owfK97|6D%e@LCT#m42;TXGcHi?10|zu*rd;*-tB0yGO3 z$hGR!QIYYP%q190lla5xqBjH#&H)Vx4t`6(sxaN!*f_3JPj0b#Y(_LV(X4vn6NZw4 zJ5TWVT(2IH%NiS53?M`V|0O_S*<2AqbtTRq6Ko9F<~@@j6i@?J;+4%C)LQ6F;lU8` zGlLmO#7=?eU~^zU4vpAxKcae4f{^#le5^$^u)zp>qTn+SLAw1!LlU?G8<`6%mdMDD zZqCM6548cl2L})WE>>3Xv+<2;9zrB1Y92kZkqM-J8^v9Zj3IvxNFH0cA3&fH5c-mq zZ)&;RHwAz<6=gg)WLJU)2eH{gF2Kljv-+;FSqFr-Xlb-?)yhrxL=#8=0U4;A2vR6K z(jQaz&qXBxo~e5|ybKJfDP)_#gWv%)o#f+c*kX9f&26)&ar&`)qXS}lBN!S)lzxk< z%fV7;uvN!g^`IXxE2a(v&Dc+TyceHP-`b*G1wCc)*^(#|U>qh*fP3g2*hBpCt!gW# zg5qAqXU@ez)X@mkm;FLX7jfOZX%AbbeVck>i#BgkU-Fi8&jykemkC${qnFyZtF5R5 z>L@nq4qK9GaBp-w6Jk1~>Ig>8IK4w1Rk4TBjo(6<$|sVMb?4}pz>Gn762G_DU>Kiw z)wY*1_o(j}=}x%HGQQ77L9g1oxKbLKdYJw`UVPkV#5ZCKckWe>-i!*W%sc%UfMD`7 zqZBI*ae4NA>Pee%zkE1jd7)#f%sNCsn*=^H&~RB{LGnJS9=G{7&-royxC37m08Aoh z@qpQ%YB`Y`JGHTtw>YEo=nt^A5VMIjls5;>!l%{wo6%5V(-c%U#O4wzhain^?f_ef zKclvA^fiW=WlHoQ(cMc0{wFEJ?MU2)A^32>v3^!$d#{sJB?VSP=anD7#@y z=#{5`ehk-OoyUuUY!1y3fz#<1#&8WIOpq`^P7r~VPUA0*;Tp2vxbT4ioU@6XvE^P678WyRB zLP0r!T#1oWc=uyLZA_#bf(3vh&-${uDPZNLb*2MYaRfgbc4M{}f`uMZM|UAfN2Bx~ ztsWu_uPQ%THedlz5VVMp0Lyq=4`dk;P#8ym)Q1OS#ecsuNa1U^8PG2`~=R zuWz1a78tq%mOX%-_K zNin^K=tVf(x7Drdct$dYhbPn#Kx-N2RW($I6j;RfMUhLi4DciGJE~o0-OId!z=Xv5 zA!3nbyb-+ujdS9WvkSVK0P;2WNp;Ey`mDsXWRCjPE5xHbrMflSbnR$X7JVmdgd!cU z*bYs=>v-Zw(}2Y`aQ&y%sl%%edCZ2O_Z1BDIV zFBMf)Snq$J&dp|86T<2U$rP2%Jz*A-vymcepgaT^f;vhBjtI>J8e;!YE!Vodc9i=L zX%4zLxSM_g$B2GF2N#Z8dh|yaPO8Ri`P{Vt)+T$Dbez$EI@3Os1i}SEXdcl3#ELpU zR%g~KuN~Em0TJ$J4qChkq>AiL6Z6}Ht~8humh4{ zpshqE`1t6BO}rja4$1-?Ft7|#ef-N!ydHWCh!9b5#a_bX`qd_0??JRjWIq@HTtP|V zzPO3kqfZdJ6%Z5x29Xqqzuv^_ftP^K2I3r{tCDH)|I~NptMSIP9oZKJR^vE{*_b|g z|D02za71Mcm(vRrV#dHHf$Z46pe)p}H9+(L6~6r&b;b0?$y$q}o}Gp2&SIq$fz@I; zYW36NH!M%tM#J`&F*Es~6MdF^#Ba24J^rnlw0yc|`{J-Lv|&Is)Cy@1>md6Xh%TXq zM88vysDTE7!;5eRDMh`7t+HulZ4~N+>nuT$Wjh9{?FYXfbxoBEsf=!^uBk-W5-j86 z!YB78hW9_H$Fx|1Y8g*zM*{MlH0C~mq6y)U5D#$2?17g4$4wk&AeZ4=1nUWf4xwxI zpHzE#I50qV*GAT!rVu-FW!P|~VaxSEj@ap+H?dlFUSwqG$s<5~_%C1D#Ora&!k+~8 z(oeB0I@Vv*87(@pMmbtL$`Ha%ndwa=0RD6vSv&pfCbj|EdwL(f8=`b{UoZbny`mKt zu9R0d%Z4h16TxMG>W33~EcD{l0DQ?j_jff9Y9GemUU&=|+>c_`05CurAv-I0ZINv2 zWp!qY-YquB;xn$M?12V^F(UlOpo>Jpp?|d0eT4(0F@ej*X9T;6kd#=HiC3_YIiWm+ zbMT*=^LzlMkTxM}BK-$(&*guqIZ@E2bW-z8aNPZSbbDx^8;K86i}*Am-O}Vgo6~+Q zmT3gVD$y@G0E_s)RmFGXy&-?e!x>w}t44|z=4-4pB7ubCzM}3sf_9PdNXc8ix;YKU z-B6CO2eT5xEvp-^sR!llt19|gBw&Vr67Az51?ezW@Dxa&`MP>_t4UUj!QyjF#`}DJ zA^5LKq~Uz*d8>LGXW9n!{8la7r0Fl>I_l^A81fo4wPc-kLb1sg{FE6Hie9}py*?Jc z-liL`*Q)fwZ-{%h>9%KUIj(G&>DNlMDITzpVi+pmYA|+`u|mXl?D_UNT1!@wLNJkG z-7ktEVXN3f5X1#L*#>w4%g0k zW4MM45dac_)e(bBUV`>Uq?Wj(b6Gpi@sY9dTV>GhO6zv5j zXu=$!ytLAbwJMwT2<$3#gwk0QBYiHCTi|~~gXLZzSufEJFQ&l=cdDn6?l<6cWakNC zh42FMzg?v<8a6<=V;? zGDe-TF9%mOIPJFuIt0DV{JTunZNKLh0sh!(u z&d6tO;dZP`v{J0+b*ILXd!?xzAJjg&Iqj&<;Emj$wO2A+B9pNsDrsurRoZ(-8XPS; zs_H(?+Or9XOPZ?xkapGPbkOkb)_ixD5=XshXe^0Ln%Z@>_C^w{$e~+|pscNOsE;MH zNmE0v(aw1T9aNvJA#2AGB4xuEQk^t4<65ni>vg30RQQ9l7n7C7lKP~n@(*h(T8vTg zG+QD;MN@^>Y5grKeB*f}nyR{9i;A75CQ*v{|Hkr4G}Us0cGv%m+k8t=m9iHgbJ0h`z0UO<~K@a zY*r(MJvSSsntJAzO}t&RovP_}pU{q}$C}P4QV48pRL#kTWaKYW_*k4hGoP zLsFfH=qCGCZB!H&gc&eH!#w~&EKn}kUc2lW$O6Ah1_X{SQ?P{_)DNQyShuv(*KT7NS#jwW0B#c!mBGL|ICP0hViYnjuz0c_Jy7#(?&HEeUz z`ZcxhF72(w3cmTNcbe{bx3=Ht%Y@V_@6o1>@s|>ik;M0E+t$tgWbFz9)r_C7? zI6cSsGEp*YFVVgsxxayw;*JFfQsK{+xE?*zVHQsm*T! ztLgpPvi}VRY5fgM|?vBs|nf z`jB=6JvVlyoEoFE;efJA2`z%j6z8w`@K}VXJZSJMS}Vk@@PsrZ39J?}kE#fJ&alZu zasZ)&gNy7N1YJhaSGBjb*g!XSuWWoq++Oe_%k(N_sKA>J@Y4(lF-(oGX?qsCNnti3 zBn3(oSegP7(qZGbzOGF!e$!+u?#CDg^&uQgWKRTRraz*2jY3-8xNFQ&1*#O1?hxi- zLMsIOz@u6XC?knlj+t>ZR^7qXMY5MheiD$P%i(GgT;)t!mS8}t zk85+QFr7M@nBmg-G`0gfoI_Bo6UHK1IgY+D`r=Q96DNj|MDVUg46tu%`;4%s*0_zn zrCBvQaqXyzL0Tn(+X=Hp0B7yciG0PgmVR5y!)%9(pB_HeyI*ADgk^=qBT%RV34202 zEL*dNyT@>W-Tf|TJE-%qONWHi1?G3OLt5Vf)qq&@`Y3MFF)*S?8bWR!kvznBvJhM8n<^Yp#b*;9DUo90b**Z95QfNm%-}* z9ZN`{6d6LfAR3n}0{}uG05ITxYpVMD+NG_wfTGUgvt@8j){gw^87r19mpP^9t_)x+ zC-j!LNWyZ$U&u`1(;@=su@#dnha7;ysod0}XIdM?YA}l0(J+9DtUY{@ud_4Hm`Cbu zsFa|4AkzR@0YXz`bTmlIVFbdePo@oAbWIKUfp$Twt{MA^UVBH9-eM8{#)?S)8N%vd ziy;A4UQAuwFQ|UBhyZFoY#ty#)Gi#UDWf^w>-T|LgR-5W0!Ygx&pnbX*;;JbG4SeH zF_0eDiM$Y0Xj8}hXcSXwy+yPRFtPDz(XKF$@Ts*cJ5wPAwhO&HS-%ByfJ-hV(o8_A z28$qMDp&_>zo}h6)>@`z7cVSREUSC(FsH;=LU73T;_4`xl}84RAzN=#gMOkdE4I&i zzPLhy%9qrvqRmM_*;L)Lnk8{ojRaxMS^RkFaTGUu7vP3I>*pB=~u4 z&SqUFvJtK(-Zl$EINkh3u^~w@USf9}p}P)YxUl{cMrh0 z_o0|cp;Q0mSkw^U(Bv8b0tjfwfr|fE+Nmuzl{(pejEGipO$Y%4zdV`|8AM@vPe}0e zVoU3FT@@qR4aEuoT?Y7J;p5K3V+2NsG#WgQ2n~j}lHj{vYpr5PWmR>{Om--4oZpTq zEyI{a=o!v(kv|Wb4c!d>Pm4zCp?uyqw!itLsHY**ct4^Ycv+DWEJ4^So4?UUq?|Z5 zV4uuYto&HqGf&}7aF~dtMam}IOQ^fvZ#BvJQOS*}B5$&wY0V6$0hAqRj)dWWwZ^va zJ8i}r8+d5;zaMS1Lw!&F8jwsxl>5lEf6x}>l@1F=7=85P90#)ou_SCWL|uh{9DTJx zSHTjBc?dWeT$bsdMr*VnV=a^L2$QH$hGz56qg}vL+PX)w1Qbl4gO^6VfTlwvMl7Zo z6QmvfMH?eq>ZS&d2VgrS|0P&XKn_H0>DYuZcKvme3>j&QD%fe!-Ej`L~V)esPR9f6`;m4GE-8N3_JXq>|2mo z5~fSgAK6>WM(q7lD+0+f>XYnFaEy)RW=NeNEJ#S{6ZmZC$-hQ>D`XibAOIPX4rLUJjYh{-ItEC7(BfA998U-m? zF06?{1)4kpW!UG5K!h$s$Z1eu`^?}}Pr?wcthh-|c}2Utl{8zoZ*0=mRFfXXR#gF& z!W@8(Hem~~0upZ%f)Z08Rum@6lv7P@dUcD*w9SEP)xLtO6{{l5TkwmrvRQC-&@Om! zn0(|fCqf~%%&4hdueH|C>iVj2kIDq?>N&BUG-gn*ovC0DB3z7Q!-Bk(tlhK-={kio zjW8RBYCU#(VR?_ zmawU}HfXnQiM9BtD9LcAQ?#r}jo&)Pj9~iNv zV-aX-P0A&mSu&L`DR{7MC6U~Y;i46TjL2%Afktc^X{EyE#;h;31pdj_*DUl5dvc5~ z70f?emj*T-xC~*Ipmn6Sz@Ue10*io&EwSmPo?RLdI5e^VRqG=uQ8A`WA2wkDM@Be{ zZSkfEnh^E~at5d5TeO<0Kc}>;g_KweMyMT0e??ZQ&?Z6IVMwFnJ<}zpuB=W_3p=E4 za8YV_=BDb-EuG$?x+adArlO>*$tvcsQicu$^9p;rk1O5@cusP1pu$ll*^x+d+iVFs zue7G60k;~qDLKxvTExG(XTSdI3X2HQUN|A}j1dbevQhyGAa0KgSTQ6;jKHQxKEKpT z4sY!XZv745A4%{{Y7F5_hfBvngRsjNlxDT)*nHO$t_`{U716uGMg%dd0gWJh*n~p^ zcYOaQ+$9mQNfmh)D}e(IlOww`wm|a(rB=Zh)h1LAmXa(>-UKEdK|o-L)Lsb${1=vH zjQN2GZI$;R1wn{7!s-sS2Z8MuZ9+rV1S?m_o3JjIh3Or-3{rQ7&c&spS~Nsr(Xyqi z?ofi(as*~S<^G+{8blnx z1aN7om20N)E{&y}(5PrAbi|Oi#`s1EfPhi-vX))f8Y|Wh&j^H+n6ymt&I3}vymWAj zt{Vpb)lX!f8@uqWTIBu24SWSn2!@u|l))-}#Zg1EmJJM%*bG@s1|o!{6~g03=L8P2 zXyOYQSr=sGSC*PMFzP0@R4%zju+NfU*cAjuB!><^SQ=v-aM6dPZ50WxV4Eh>3em_W zzI@kBt}5l>^U}7GXNb#5vtV8=G#eY~7Lx{^DQxwz?tQ2RhzfBq@*Mt9) zn-J6NUQ?RU9NSpXRb<5(uC7l1sIt^ zlDv8(y(Wzzy0c?Ae*BSA?m`;wx{diF2`~d)PrQ-HW6nw$e6;jvD`Bf}Zjd%3W0`B3 zP{gqJ^)Z|Hlzb^IW@~Yq>=TR#=^$4HB#0Pb%4Pdy?Mx;6RRz%&$2Dk-AaFc7iV1=n zTk!H?{R(VYVVd{o8%wPK_Kgi-L97PxWwjUON;xDsI}Gt6*S3LdLZuKnJ78+?$N(Ea z9cbE~Zz{D^*IMtwt-s0l=d4+>P$Bm;L^M1lNmNOllrVuVN*BNYixr+gJAdHpzsVKHURZ59qcz6n)UrH`!2tmua1?_nJ$ zEeWytWl<&8P$7*H3c?u-_DxTDOQ{tky83X{gF;lvYLq1$I3W~@SOzh^B6Lt8i~vZb z0JHG#V%KbbwV!AyZ&&N79^_(8R-Y`yENghx_#o$0=u({s5XFd0nq$~3U@>fZzFRlp z`3eart5255+zd-3T#aOoN+HXjLb7tpG{Y8^3ZOw#g}0S95AeTwUc zLFa>I7iMJSY*P6Mt&eeq{{;scG+7bvys06#ms)w98|9$J63d$4Le9EC7Ah>YkW{eN zdJHOFHB|?$6$%2*1P}oM;?4fdJ4z=H=NN0WQe>qH4kt7-c)MT@1g;?-jL2EUI`SP8 z&xtWH7{*G*OAkf5MN^xX^KO+Gh`6QBujw6nyhrxOd>2F(jgHxMh*g_xkv9V&6aXV3t=YXTi95f z5ym?sCFd;55C$^+o|2w{H8#o|okgG05NLudMiu68C{$o2xwn+34BzMyETq|0q%Prz zIAu6~kp94S2zW$vUum-;U*y^YZb$kzkzE^g=#!;#CpTi_PqvZQjld4Flm z^cEXk{nF5A@tc+DY5B>TTwcY_4hN?V8RK{u@m%5g#4Ypr(!Rwq(Exbv$IoedA~kpd zv<1k|7fMHrt!I}9BD2Nm$+Aj6d9!#&@DY*v5ld7Qg?JA1FP7$x?M{*b4JAQzlEB%J z$CrhcB$y_taDdu9P&&P7WYxdz1p_sTdw>VH}LoeUXR0tFV%(i)WuOD%~jVQ6wK z{sD9KrP8u3Uvcd@1u-{dAA&@YCDBM-VTr?jFIFHWfjFd_2ts? zE#GDl+mz3t7+*vjBN%u#l64q9RPr)%umuBy^M^~GSbJWg$bH|16ByKl4vX)@r2`N& z#0J=uxKTJh@F`-}2Vewk1~hNsS4v|+*F&Da>Z_$W_|3+SSxwOjMbcQ15f1#PfV|+3 zA=BU2N=J|FbquTk0i2JfI{rQ=)nMlEpmIz>M3u{5AM5MQ66R%Uz6UrHz0Kwod%B%E zkCaZ^@~^iVK10GY60V7a)8wQfL(rq8wg0QyNK3>jxn@WvYo_;cG2uMMFoF9Fi)#8< zY3Y`)I$0}I!-7aQA(yi(Vjsw989iRIM;^m+nD*PO3k*eGDG^5a`o2+eM!u{VSqWZ! z(uR6KFaqd(qV^pXWxG0grplZ#)VYn)MxYlP2JXN-QEKDl>=fcRNAMBkG8>X zKu+=MhdlMR5RiA(O- zUPxcdQ+0o;Vej9uhU62ghdT6Wrai4ZUTptUb6KmCbJN&I+OAS2vJnbHe8COZb>O&g z^|I5ZVxSmUdB%Yg>k3l`23H-py;xbNBC;)Ie65-)m`Xv*FFCMBW?z#&gaapLCWmBd whMOKb@J%b&?ZBkM5w&D$I=D*Yial^5<~FFZumMaJBojjib`3$kFqLlme;l{Tx&QzG literal 0 HcmV?d00001 diff --git a/wasm/wasm_bg.wasm.d.ts b/wasm/wasm_bg.wasm.d.ts new file mode 100644 index 0000000..6da246c --- /dev/null +++ b/wasm/wasm_bg.wasm.d.ts @@ -0,0 +1,14 @@ +/* tslint:disable */ +/* eslint-disable */ +export const memory: WebAssembly.Memory; +export const main: (a: number, b: number) => number; +export const wasm_bindgen__convert__closures_____invoke__h30acef6f6c0e425e: (a: number, b: number, c: any) => void; +export const wasm_bindgen__closure__destroy__h88746cad1b24036a: (a: number, b: number) => void; +export const wasm_bindgen__convert__closures_____invoke__hbefc371369f44e63: (a: number, b: number, c: any) => void; +export const __wbindgen_malloc: (a: number, b: number) => number; +export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; +export const __wbindgen_exn_store: (a: number) => void; +export const __externref_table_alloc: () => number; +export const __wbindgen_externrefs: WebAssembly.Table; +export const __wbindgen_free: (a: number, b: number, c: number) => void; +export const __wbindgen_start: () => void;