diff --git a/.eslintignore b/.eslintignore index 28ae9982..883626e2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,3 +4,4 @@ packages/*/coverage packages/*/extension generated public +pkg diff --git a/Cargo.lock b/Cargo.lock index 20609489..2a8c6a95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,7 +209,7 @@ dependencies = [ "ahash", "bytes", "bytestring", - "cfg-if", + "cfg-if 1.0.0", "cookie", "derive_more", "encoding_rs", @@ -537,6 +537,15 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.59.2" @@ -663,6 +672,18 @@ dependencies = [ "bytes", ] +[[package]] +name = "c_vec" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd7a427adc0135366d99db65b36dae9237130997e560ed61118041fb72be6e8" + +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + [[package]] name = "cairo-rs" version = "0.15.12" @@ -750,6 +771,12 @@ dependencies = [ "smallvec", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -780,6 +807,21 @@ dependencies = [ "libloading", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "cocoa" version = "0.24.0" @@ -840,6 +882,16 @@ dependencies = [ "memchr", ] +[[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 1.0.0", + "wasm-bindgen", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -957,7 +1009,7 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -966,7 +1018,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -976,7 +1028,7 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -1085,7 +1137,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn", ] @@ -1099,7 +1151,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn", ] @@ -1242,16 +1294,36 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1321,7 +1393,32 @@ version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eb359f1476bf611266ac1f5355bc14aeca37b299d0ebccc038ee7058891c9cb" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime 1.3.0", + "log", + "regex", + "termcolor", ] [[package]] @@ -1331,7 +1428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", - "humantime", + "humantime 2.1.0", "log", "regex", "termcolor", @@ -1362,7 +1459,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "winapi", @@ -1659,7 +1756,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -1670,7 +1767,7 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -1866,6 +1963,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.12.1" @@ -1954,6 +2060,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + [[package]] name = "humantime" version = "2.1.0" @@ -2026,7 +2141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.1", "serde", ] @@ -2054,7 +2169,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -2285,7 +2400,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "winapi", ] @@ -2332,7 +2447,8 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "serde", ] [[package]] @@ -2341,7 +2457,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "generator", "scoped-tls", "serde", @@ -2350,6 +2466,15 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c84e6fe5655adc6ce00787cf7dcaf8dc4f998a0565d23eafc207a8b08ca3349a" +dependencies = [ + "hashbrown 0.11.2", +] + [[package]] name = "mac" version = "0.1.1" @@ -2418,6 +2543,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memory_units" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" + [[package]] name = "mime" version = "0.3.16" @@ -2541,6 +2672,17 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "nes" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "tetanes", + "wasm-bindgen", + "wasm-bindgen-test", + "wee_alloc", +] + [[package]] name = "new_debug_unreachable" version = "1.0.4" @@ -2555,7 +2697,7 @@ checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ "bitflags", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset", ] @@ -2764,7 +2906,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" dependencies = [ "bitflags", - "cfg-if", + "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", @@ -2870,7 +3012,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "instant", "libc", "redox_syscall", @@ -2884,7 +3026,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -3043,6 +3185,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pix-engine" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae98b2fabd3b6182fbc76e5c09c7d22242ca2775d38e7be273758d97139f5d37" +dependencies = [ + "anyhow", + "bitflags", + "chrono", + "getrandom 0.2.7", + "log", + "lru", + "num-traits", + "once_cell", + "png 0.17.5", + "rand 0.8.5", + "sdl2", + "serde", + "thiserror", +] + [[package]] name = "pkg-config" version = "0.3.25" @@ -3108,6 +3271,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger 0.7.1", + "log", +] + [[package]] name = "proc-macro-crate" version = "1.1.3" @@ -3169,6 +3342,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.20" @@ -3374,6 +3553,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "ringbuf" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f65af18d50f789e74aaf23bbb3f65dcd22a3cb6e029b5bced149f6bd57c5c2a2" +dependencies = [ + "cache-padded", +] + [[package]] name = "rodio" version = "0.15.0" @@ -3466,6 +3654,30 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sdl2" +version = "0.35.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7959277b623f1fb9e04aea73686c3ca52f01b2145f8ea16f4ff30d8b7623b1a" +dependencies = [ + "bitflags", + "c_vec", + "lazy_static", + "libc", + "sdl2-sys", +] + +[[package]] +name = "sdl2-sys" +version = "0.35.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3586be2cf6c0a8099a79a12b4084357aa9b3e0b0d7980e3b67aaf7a9d55f9f0" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "version-compare 0.1.0", +] + [[package]] name = "security-framework" version = "2.6.1" @@ -3670,7 +3882,7 @@ dependencies = [ "derive_builder", "diesel", "dotenv", - "env_logger", + "env_logger 0.9.0", "futures", "jsonwebtoken", "juniper", @@ -3704,7 +3916,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -3715,7 +3927,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -3892,12 +4104,42 @@ dependencies = [ "quote", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "structopt" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "subtle" version = "2.4.1" @@ -4299,7 +4541,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "libc", "redox_syscall", @@ -4327,6 +4569,41 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "tetanes" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5220d18b48ea7e61e07d96cc58e96f92ed78f5a7cd414f56cc2d696055497d11" +dependencies = [ + "anyhow", + "bincode", + "bitflags", + "chrono", + "dirs", + "enum_dispatch", + "flate2", + "getrandom 0.2.7", + "lazy_static", + "log", + "pix-engine", + "pretty_env_logger", + "rand 0.8.5", + "ringbuf", + "serde", + "serde_json", + "structopt", + "wasm-bindgen", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thin-slice" version = "0.1.1" @@ -4466,7 +4743,7 @@ version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -4651,6 +4928,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version-compare" version = "0.0.11" @@ -4736,7 +5019,7 @@ version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -4761,7 +5044,7 @@ version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -4796,6 +5079,30 @@ version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +[[package]] +name = "wasm-bindgen-test" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b30cf2cba841a812f035c40c50f53eb9c56181192a9dd2c71b65e6a87a05ba" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ad594bf33e73cafcac2ae9062fc119d4f75f9c77e25022f91c9a64bd5b6463" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "web-sys" version = "0.3.58" @@ -4890,6 +5197,18 @@ dependencies = [ "windows-bindgen", ] +[[package]] +name = "wee_alloc" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "memory_units", + "winapi", +] + [[package]] name = "wildmatch" version = "2.1.1" diff --git a/Cargo.toml b/Cargo.toml index c0e7b365..650c7c24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,11 @@ [workspace] members = [ + "packages/nes", "packages/server", "packages/tauriapp" ] + +[profile.release.package.nes] +# Tell `rustc` to optimize for small code size. +opt-level = "s" +debug = true diff --git a/package.json b/package.json index a4f0fc57..0e1e2a65 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,10 @@ "name": "root", "version": "0.0.1", "scripts": { - "lint": "lerna exec --ignore @nesbox/config -- tsc --noEmit && eslint . --ext .ts,.js", + "lint": "lerna exec --ignore @nesbox/config --ignore @nesbox/nes -- tsc --noEmit && eslint . --ext .ts,.js", "test": "echo test", "release": "lerna version", - "prepare": "husky install" + "prepare": "husky install && yarn --cwd packages/nes build" }, "devDependencies": { "@types/node": "^15.6.1", @@ -28,6 +28,7 @@ }, "workspaces": [ "packages/*", + "!packages/nes", "!packages/server", "!packages/tauriapp" ] diff --git a/packages/nes/Cargo.toml b/packages/nes/Cargo.toml new file mode 100644 index 00000000..c8d19932 --- /dev/null +++ b/packages/nes/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "nes" +version = "0.1.0" +authors = ["mantou132"] +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = ["console_error_panic_hook"] + +[dependencies] +wasm-bindgen = "0.2.63" + +# The `console_error_panic_hook` crate provides better debugging of panics by +# logging them with `console.error`. This is great for development, but requires +# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for +# code size when deploying. +console_error_panic_hook = { version = "0.1.6", optional = true } + +# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size +# compared to the default allocator's ~10K. It is slower than the default +# allocator, however. +# +# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. +wee_alloc = { version = "0.4.5", optional = true } +tetanes = "0.8.0" + +[dev-dependencies] +wasm-bindgen-test = "0.3.13" + diff --git a/packages/nes/package.json b/packages/nes/package.json new file mode 100644 index 00000000..02f5940c --- /dev/null +++ b/packages/nes/package.json @@ -0,0 +1,12 @@ +{ + "name": "@nesbox/nes", + "version": "0.0.1", + "description": "", + "main": "./pkg/nes.js", + "types": "./pkg/nes.d.ts", + "scripts": { + "build": "npx wasm-pack build --target web" + }, + "author": "", + "license": "ISC" +} diff --git a/packages/nes/src/lib.rs b/packages/nes/src/lib.rs new file mode 100644 index 00000000..3eb77da8 --- /dev/null +++ b/packages/nes/src/lib.rs @@ -0,0 +1,216 @@ +use tetanes::{ + audio::{Audio, NesAudioCallback}, + common::{NesRegion, Powered}, + control_deck::ControlDeck, + input::GamepadSlot, + memory::RamState, + ppu::{VideoFilter, RENDER_SIZE}, +}; +use wasm_bindgen::prelude::*; + +mod utils; + +#[wasm_bindgen] +pub enum Button { + Poweroff, + Reset, + Select, + Start, + + Joypad1A, + Joypad1B, + Joypad1Up, + Joypad1Down, + Joypad1Left, + Joypad1Right, + + Joypad2A, + Joypad2B, + Joypad2Up, + Joypad2Down, + Joypad2Left, + Joypad2Right, + + Joypad3A, + Joypad3B, + Joypad3Up, + Joypad3Down, + Joypad3Left, + Joypad3Right, + + Joypad4A, + Joypad4B, + Joypad4Up, + Joypad4Down, + Joypad4Left, + Joypad4Right, +} + +#[wasm_bindgen] +pub struct Nes { + paused: bool, + control_deck: ControlDeck, + audio: Audio, + buffer: Vec, + callback: NesAudioCallback, + sound: bool, + dynamic_rate_control: bool, + dynamic_rate_delta: f32, +} + +#[wasm_bindgen] +impl Nes { + pub fn memory() -> JsValue { + wasm_bindgen::memory() + } + + pub fn new(output_sample_rate: f32, buffer_size: usize, max_delta: f32) -> Self { + utils::set_panic_hook(); + + let mut control_deck = ControlDeck::new(NesRegion::Ntsc, RamState::default()); + control_deck.set_filter(VideoFilter::Pixellate); + let input_sample_rate = control_deck.apu().sample_rate(); + let mut audio = Audio::new(input_sample_rate, output_sample_rate, 4096); + let buffer = vec![0.0; buffer_size]; + let callback = audio.open_callback().expect("valid callback"); + Self { + paused: false, + control_deck, + audio, + buffer, + callback, + sound: false, + dynamic_rate_control: true, + dynamic_rate_delta: max_delta, + } + } + + pub fn pause(&mut self, val: bool) { + self.paused = val; + } + + pub fn paused(&self) -> bool { + self.paused + } + + pub fn sound(&mut self) -> bool { + self.sound + } + + pub fn set_sound(&mut self, enabled: bool) { + self.sound = enabled; + } + + pub fn power_cycle(&mut self) { + self.control_deck.power_cycle(); + } + + pub fn frame(&mut self) -> *const u8 { + self.control_deck.frame_buffer().as_ptr() + } + + pub fn frame_len(&self) -> usize { + RENDER_SIZE as usize + } + + pub fn samples(&mut self) -> *const f32 { + self.callback.read(&mut self.buffer); + self.buffer.as_ptr() + } + + pub fn sample_rate(&self) -> f32 { + self.audio.output_frequency() + } + + pub fn buffer_capacity(&self) -> usize { + self.buffer.capacity() + } + + pub fn clock_seconds(&mut self, seconds: f32) { + self.control_deck + .clock_seconds(seconds) + .expect("valid clock"); + if self.sound { + let samples = self.control_deck.audio_samples(); + self.audio + .output(samples, self.dynamic_rate_control, self.dynamic_rate_delta); + } + self.control_deck.clear_audio_samples(); + } + + pub fn load_rom(&mut self, mut bytes: &[u8]) { + self.control_deck + .load_rom("ROM", &mut bytes) + .expect("valid rom"); + self.pause(false); + } + + pub fn handle_event(&mut self, button: Button, pressed: bool, repeat: bool) -> bool { + if repeat { + return false; + } + let mut matched = true; + + let gamepad = &mut self.control_deck.gamepad_mut(GamepadSlot::One); + match button { + Button::Start => gamepad.start = pressed, + Button::Select => gamepad.select = pressed, + // Button::Joypad1A => gamepad.turbo_a = pressed, + // Button::Joypad1B => gamepad.turbo_b = pressed, + Button::Joypad1A => gamepad.a = pressed, + Button::Joypad1B => gamepad.b = pressed, + Button::Joypad1Up => gamepad.up = pressed, + Button::Joypad1Down => gamepad.down = pressed, + Button::Joypad1Left => gamepad.left = pressed, + Button::Joypad1Right => gamepad.right = pressed, + _ => { + let gamepad2 = &mut self.control_deck.gamepad_mut(GamepadSlot::Two); + match button { + // Button::Joypad2A => gamepad.turbo_a = pressed, + // Button::Joypad2B => gamepad.turbo_b = pressed, + Button::Joypad2A => gamepad2.a = pressed, + Button::Joypad2B => gamepad2.b = pressed, + Button::Joypad2Up => gamepad2.up = pressed, + Button::Joypad2Down => gamepad2.down = pressed, + Button::Joypad2Left => gamepad2.left = pressed, + Button::Joypad2Right => gamepad2.right = pressed, + _ => { + let gamepad3 = &mut self.control_deck.gamepad_mut(GamepadSlot::Three); + match button { + // Button::Joypad3A => gamepad3.turbo_a = pressed, + // Button::Joypad3B => gamepad3.turbo_b = pressed, + Button::Joypad3A => gamepad3.a = pressed, + Button::Joypad3B => gamepad3.b = pressed, + Button::Joypad3Up => gamepad3.up = pressed, + Button::Joypad3Down => gamepad3.down = pressed, + Button::Joypad3Left => gamepad3.left = pressed, + Button::Joypad3Right => gamepad3.right = pressed, + _ => { + let gamepad4 = + &mut self.control_deck.gamepad_mut(GamepadSlot::Four); + match button { + // Button::Joypad4A => gamepad.turbo_a = pressed, + // Button::Joypad4B => gamepad.turbo_b = pressed, + Button::Joypad4A => gamepad4.a = pressed, + Button::Joypad4B => gamepad4.b = pressed, + Button::Joypad4Up => gamepad4.up = pressed, + Button::Joypad4Down => gamepad4.down = pressed, + Button::Joypad4Left => gamepad4.left = pressed, + Button::Joypad4Right => gamepad4.right = pressed, + _ => matched = false, + } + } + } + } + } + } + } + matched + } +} + +impl Default for Nes { + fn default() -> Self { + Self::new(48_000.0, 4096, 0.005) + } +} diff --git a/packages/nes/src/utils.rs b/packages/nes/src/utils.rs new file mode 100644 index 00000000..514d4d79 --- /dev/null +++ b/packages/nes/src/utils.rs @@ -0,0 +1,10 @@ +pub fn set_panic_hook() { + // When the `console_error_panic_hook` feature is enabled, we can call the + // `set_panic_hook` function at least once during initialization, and then + // we will get better error messages if our code ever panics. + // + // For more details see + // https://github.com/rustwasm/console_error_panic_hook#readme + #[cfg(debug_assertions)] + console_error_panic_hook::set_once(); +} diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 4a9d2105..814fa8ac 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -12,12 +12,12 @@ "prepublishOnly": "npm run build" }, "dependencies": { + "@nesbox/nes": "^0.0.1", "@mantou/gem": "^1.6.0", "duoyun-ui": "^0.0.39", "graphql": "^16.2.0", "jszip": "^3.10.0", "marked": "^4.0.16", - "nes_rust_wasm": "^0.1.2", "subscriptions-transport-ws": "^0.11.0" }, "devDependencies": { @@ -29,8 +29,6 @@ "@tauri-apps/api": "1.0.0-rc.7", "@types/marked": "^4.0.3", "dotenv": "^10.0.0", - "vite": "^2.3.8", - "vite-plugin-top-level-await": "^1.0.0", - "vite-plugin-wasm": "^0.0.2" + "vite": "^2.3.8" } } diff --git a/packages/webapp/src/gamepad.ts b/packages/webapp/src/gamepad.ts index 3626bdd5..8de1de11 100644 --- a/packages/webapp/src/gamepad.ts +++ b/packages/webapp/src/gamepad.ts @@ -1,5 +1,5 @@ import { isNotNullish } from 'duoyun-ui/lib/types'; -import { Button } from 'nes_rust_wasm'; +import { Button } from '@nesbox/nes'; import { events } from 'src/constants'; diff --git a/packages/webapp/src/pages/emulator.ts b/packages/webapp/src/pages/emulator.ts index 0fa45f7e..28dd5dfe 100644 --- a/packages/webapp/src/pages/emulator.ts +++ b/packages/webapp/src/pages/emulator.ts @@ -10,7 +10,7 @@ import { RefObject, } from '@mantou/gem'; import { locale } from 'duoyun-ui/lib/locale'; -import { Button, WasmNes } from 'nes_rust_wasm'; +import init, { Button, Nes } from '@nesbox/nes'; import { hotkeys } from 'duoyun-ui/lib/hotkeys'; import { Modal } from 'duoyun-ui/elements/modal'; @@ -25,6 +25,7 @@ const style = createCSSSheet(css` height: 100%; object-fit: contain; background-color: black; + image-rendering: pixelated; } .nodata { position: absolute; @@ -52,14 +53,12 @@ export class PEmulatorElement extends GemElement { return document.visibilityState === 'visible'; } - #nes?: WasmNes; + #nes?: Nes; #imageData?: ImageData; #audioContext?: AudioContext; #enableAudio = () => { - if (this.#audioContext?.state === 'suspended') { - this.#audioContext.resume(); - } + this.#nes?.set_sound(true); }; #getButton = (event: KeyboardEvent) => { @@ -88,37 +87,43 @@ export class PEmulatorElement extends GemElement { return; } if (button !== Button.Reset) this.#enableAudio(); - this.#nes?.press_button(button); + this.#nes?.handle_event(button, true, event.repeat); }; #onKeyUp = (event: KeyboardEvent) => { const button = this.#getButton(event); if (!button) return; - this.#nes?.release_button(button); + this.#nes?.handle_event(button, false, event.repeat); }; - #renderCanvas = () => { + #nextStartTime = 0; + #loop = () => { if (this.isConnected) { - requestAnimationFrame(this.#renderCanvas); + requestAnimationFrame(this.#loop); } - if (!this.#nes || !this.#imageData) return; - this.#nes.step_frame(); - this.#nes.update_pixels(new Uint8Array(this.#imageData.data.buffer)); + if (!this.#nes || !this.#imageData || !this.#isVisible) return; + this.#nes.clock_seconds(1 / 60); + + const memory = Nes.memory(); + + const frameLen = this.#nes.frame_len(); + const framePtr = this.#nes.frame(); + new Uint8Array(this.#imageData.data.buffer).set(new Uint8Array(memory.buffer, framePtr, frameLen)); this.canvasRef.element!.getContext('2d')!.putImageData(this.#imageData, 0, 0); - }; - #initAudio = () => { - this.#audioContext = new AudioContext({ sampleRate: 44100 }); - this.#audioContext.suspend(); - const scriptProcessor = this.#audioContext.createScriptProcessor(4096, 0, 1); - scriptProcessor.connect(this.#audioContext.destination); - scriptProcessor.onaudioprocess = (e) => { - if (this.#isVisible) { - const data = e.outputBuffer.getChannelData(0); - this.#nes?.update_sample_buffer(data); - } - }; + if (!this.#nes.sound() || !this.#audioContext) return; + const bufferSize = this.#nes.buffer_capacity(); + const sampleRate = this.#nes.sample_rate(); + const samplesPtr = this.#nes.samples(); + const audioBuffer = this.#audioContext.createBuffer(1, bufferSize, sampleRate); + audioBuffer.getChannelData(0).set(new Float32Array(memory.buffer, samplesPtr, bufferSize)); + const node = this.#audioContext.createBufferSource(); + node.connect(this.#audioContext.destination); + node.buffer = audioBuffer; + const start = Math.max(this.#nextStartTime || 0, this.#audioContext.currentTime + bufferSize / sampleRate); + node.start(start); + this.#nextStartTime = start + bufferSize / sampleRate; }; #initNes = async () => { @@ -126,15 +131,17 @@ export class PEmulatorElement extends GemElement { const ctx = this.canvasRef.element!.getContext('2d')!; this.#imageData = ctx.createImageData(ctx.canvas.width, ctx.canvas.height); + const buffer = await configure.openNesFile.arrayBuffer(); - this.#nes = WasmNes.new(); - this.#nes.set_rom(new Uint8Array(buffer)); - this.#nes.bootup(); + + await init(); + this.#nes = Nes.new(48000, 800, 0.02); + this.#nes.load_rom(new Uint8Array(buffer)); }; mounted = async () => { - this.#renderCanvas(); - this.#initAudio(); + this.#audioContext = new AudioContext({ sampleRate: 48000 }); + requestAnimationFrame(this.#loop); this.effect(this.#initNes, () => [configure.openNesFile]); addEventListener('keydown', this.#onKeyDown); addEventListener('keyup', this.#onKeyUp); diff --git a/packages/webapp/src/pages/room.ts b/packages/webapp/src/pages/room.ts index 1cb7fa6b..2f087100 100644 --- a/packages/webapp/src/pages/room.ts +++ b/packages/webapp/src/pages/room.ts @@ -11,10 +11,10 @@ import { RefObject, } from '@mantou/gem'; import { createPath } from 'duoyun-ui/elements/route'; -import { Button, WasmNes } from 'nes_rust_wasm'; import JSZip from 'jszip'; import { hotkeys } from 'duoyun-ui/lib/hotkeys'; import { waitLoading } from 'duoyun-ui/elements/wait'; +import init, { Nes, Button } from '@nesbox/nes'; import { configure } from 'src/configure'; import { routes } from 'src/routes'; @@ -119,17 +119,15 @@ export class PRoomElement extends GemElement { this.addEventListener('dragover', (e) => e.stopPropagation()); } - #nes?: WasmNes; + #nes?: Nes; #imageData?: ImageData; #audioContext?: AudioContext; - + #streamDestination?: MediaStreamAudioDestinationNode; #rtc?: RTC; #enableAudio = () => { if (this.#isHost) { - if (this.#audioContext?.state === 'suspended') { - this.#audioContext.resume(); - } + this.#nes?.set_sound(true); } else { this.videoRef.element!.muted = false; } @@ -141,51 +139,57 @@ export class PRoomElement extends GemElement { const ctx = this.canvasRef.element!.getContext('2d')!; stream.addTrack(ctx.canvas.captureStream(60).getVideoTracks()[0]); - this.#audioContext = new AudioContext({ sampleRate: 44100 }); - this.#audioContext.suspend(); - const streamDestination = this.#audioContext.createMediaStreamDestination(); - stream.addTrack(streamDestination.stream.getAudioTracks()[0]); - - if (this.#isHost) { - const scriptProcessor = this.#audioContext.createScriptProcessor(4096, 0, 1); - scriptProcessor.connect(this.#audioContext.destination); - scriptProcessor.connect(streamDestination); - scriptProcessor.onaudioprocess = (e) => { - if (this.#isVisible) { - const data = e.outputBuffer.getChannelData(0); - this.#nes?.update_sample_buffer(data); - } - }; - } - + this.#audioContext = new AudioContext({ sampleRate: 48000 }); + this.#streamDestination = this.#audioContext.createMediaStreamDestination(); + stream.addTrack(this.#streamDestination.stream.getAudioTracks()[0]); return stream; }; - #renderCanvas = () => { - if (this.#isHost && this.#nes && this.#imageData && this.#isVisible) { - const ctx = this.canvasRef.element!.getContext('2d')!; - this.#nes.step_frame(); - this.#nes.update_pixels(new Uint8Array(this.#imageData.data.buffer)); - ctx.putImageData(this.#imageData, 0, 0); - } - + #nextStartTime = 0; + #loop = () => { if (this.isConnected) { - requestAnimationFrame(this.#renderCanvas); + requestAnimationFrame(this.#loop); } + + if (!this.#isHost || !this.#nes || !this.#imageData || !this.#isVisible) return; + this.#nes.clock_seconds(1 / 60); + + const memory = Nes.memory(); + + const frameLen = this.#nes.frame_len(); + const framePtr = this.#nes.frame(); + new Uint8Array(this.#imageData.data.buffer).set(new Uint8Array(memory.buffer, framePtr, frameLen)); + this.canvasRef.element!.getContext('2d')!.putImageData(this.#imageData, 0, 0); + + if (!this.#nes.sound() || !this.#audioContext || !this.#streamDestination) return; + const bufferSize = this.#nes.buffer_capacity(); + const sampleRate = this.#nes.sample_rate(); + const samplesPtr = this.#nes.samples(); + const audioBuffer = this.#audioContext.createBuffer(1, bufferSize, sampleRate); + audioBuffer.getChannelData(0).set(new Float32Array(memory.buffer, samplesPtr, bufferSize)); + const node = this.#audioContext.createBufferSource(); + node.connect(this.#audioContext.destination); + node.connect(this.#streamDestination); + node.buffer = audioBuffer; + const start = Math.max(this.#nextStartTime || 0, this.#audioContext.currentTime + bufferSize / sampleRate); + node.start(start); + this.#nextStartTime = start + bufferSize / sampleRate; }; #initNes = async () => { if (!this.#isHost) return; const ctx = this.canvasRef.element!.getContext('2d')!; this.#imageData = ctx.createImageData(ctx.canvas.width, ctx.canvas.height); + const zip = await (await fetch(getCorsSrc(this.#rom!))).arrayBuffer(); const folder = await JSZip.loadAsync(zip); const buffer = await Object.values(folder.files) .find((e) => e.name.toLowerCase().endsWith('.nes'))! .async('arraybuffer'); - this.#nes = WasmNes.new(); - this.#nes.set_rom(new Uint8Array(buffer)); - this.#nes.bootup(); + + await init(); + this.#nes = Nes.new(48000, 800, 0.02); + this.#nes.load_rom(new Uint8Array(buffer)); }; #onMessage = ({ detail }: CustomEvent) => { @@ -200,11 +204,11 @@ export class PRoomElement extends GemElement { break; // host case ChannelMessageType.KEYDOWN: - this.#nes?.press_button((detail as KeyDownMsg).button); + this.#nes?.handle_event((detail as KeyDownMsg).button, true, false); break; // host case ChannelMessageType.KEYUP: - this.#nes?.release_button((detail as KeyUpMsg).button); + this.#nes?.handle_event((detail as KeyUpMsg).button, false, false); break; } }; @@ -247,7 +251,7 @@ export class PRoomElement extends GemElement { #pressButton = (button: Button) => { if (button !== Button.Reset) this.#enableAudio(); if (this.#isHost) { - this.#nes?.press_button(button); + this.#nes?.handle_event(button, true, false); } else { this.#rtc?.send(new KeyDownMsg(button)); } @@ -270,7 +274,7 @@ export class PRoomElement extends GemElement { #releaseButton = (button: Button) => { if (this.#isHost) { - this.#nes?.release_button(button); + this.#nes?.handle_event(button, false, false); } else { this.#rtc?.send(new KeyUpMsg(button)); } @@ -288,7 +292,7 @@ export class PRoomElement extends GemElement { mounted = () => { if (this.#isHost) { - requestAnimationFrame(this.#renderCanvas); + requestAnimationFrame(this.#loop); } this.effect( diff --git a/packages/webapp/src/rtc.ts b/packages/webapp/src/rtc.ts index 297115cc..5a1c904a 100644 --- a/packages/webapp/src/rtc.ts +++ b/packages/webapp/src/rtc.ts @@ -1,4 +1,4 @@ -import { Button } from 'nes_rust_wasm'; +import { Button } from '@nesbox/nes'; import { configure } from 'src/configure'; import { events, SingalEvent, SingalType } from 'src/constants'; diff --git a/packages/webapp/src/utils.ts b/packages/webapp/src/utils.ts index e4330822..6aeb8ec3 100644 --- a/packages/webapp/src/utils.ts +++ b/packages/webapp/src/utils.ts @@ -1,5 +1,4 @@ import { history, render, TemplateResult } from '@mantou/gem'; -import { UserAttentionType } from '@tauri-apps/api/window'; import { matchPath, RouteItem } from 'duoyun-ui/elements/route'; import { Time } from 'duoyun-ui/lib/time'; @@ -60,7 +59,7 @@ export const playSound = (kind: string) => { export const setAppBadge = (count: number) => { if (isTauriWinApp) { - if (count) window.__TAURI__?.window.getCurrent().requestUserAttention(UserAttentionType.Informational); + if (count) window.__TAURI__?.window.getCurrent().requestUserAttention(2); } else if (isTauriMacApp) { window.__TAURI__?.tauri.invoke('set_badge', { count }).catch(() => { // diff --git a/packages/webapp/vite.config.ts b/packages/webapp/vite.config.ts index 07726e5a..594af4a0 100644 --- a/packages/webapp/vite.config.ts +++ b/packages/webapp/vite.config.ts @@ -1,8 +1,6 @@ import 'dotenv/config'; import { resolve } from 'path'; -import wasm from 'vite-plugin-wasm'; -import topLevelAwait from 'vite-plugin-top-level-await'; import { defineConfig } from 'vite'; const config = async ({ command }: any) => { @@ -27,7 +25,6 @@ const config = async ({ command }: any) => { 'process.env.COMMAND': JSON.stringify(command), 'process.env.API_BASE': JSON.stringify(process.env.API_BASE), }, - plugins: [wasm({}), topLevelAwait()], server: { host: true, port: 3003, diff --git a/yarn.lock b/yarn.lock index 0d5b8cb5..0c260195 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1803,90 +1803,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== -"@swc/core-android-arm-eabi@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.192.tgz#528164a4f88f111980ad1707fbd5de70e25aba51" - integrity sha512-OYbmJGB9Jp2zZ/GXALTdyWSwfjfC3g/NiZLBEG/4btVA9xU4hy4kA3tiWP1pmqF29VM1a7IHtzxwMXEBwXYX9w== - -"@swc/core-android-arm64@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.192.tgz#32d96c8e24c9122652e052c55932cd0dec02ca9c" - integrity sha512-0/0KuxrCK+I5VB8lg/KHijR3bSeM3f+s5KlNR0uE/2Hf30gnjkBfWlokeFj2e5RhjQlCmLIAXmVDVvXU6uoh4w== - -"@swc/core-darwin-arm64@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.192.tgz#0965ec4e85b9c95ac7bc73da970df15e2065394e" - integrity sha512-dhgeWV9qgsTJKURYqMWjZRZVX41FPkOdrHXPJqm1coayphCgfYvIffmZYh0bfPHBfzHLZ/eyvhNXdgXlIJtNqQ== - -"@swc/core-darwin-x64@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.192.tgz#82f322a0916901dad094793a129d43a8f7e3790a" - integrity sha512-oSXeKRpwlct/PA4GmNZ1dzWUFBBv24eCt303IHOjJMyVOul+8E0Oa7sBxSwra7mvPljKEM6g06EIW+i6NzCvJQ== - -"@swc/core-freebsd-x64@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.192.tgz#67e535bedb9352681d2a548d0efc071e03f4d651" - integrity sha512-DDEUlXpyNhcslbis2viAUdZjDd9FGSKYszZCeqi/8aHZjiJYjj5EPCUJw3h0mtK0eXLFjeOaD2qfjkuZlRauig== - -"@swc/core-linux-arm-gnueabihf@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.192.tgz#91811a3e400a65e57bb99069eddda3c6e5af439e" - integrity sha512-KcwljdxT2ZBe3zy1H+1BBWk9cR6AyL9qi8/h6X78nFwiJoktk25AMLAhUSusn9VghStveWZepnaYU9kWG62x0Q== - -"@swc/core-linux-arm64-gnu@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.192.tgz#850bc9fbdbe08a7c1e847f20bf0d45bedc99ccf4" - integrity sha512-0VVFoSWNvDOIN05QsONpSbfa+NzevICc+eFsxdjqD1qRGMWLGtzTRXfdfJWvQ3qp2uSJThpU51FyIrtN59fRPQ== - -"@swc/core-linux-arm64-musl@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.192.tgz#91671a454c767928108277c6012f7bf851f92b8a" - integrity sha512-7pK5SaiB+NHHMNU/aQQzhfi1JqAxCKh0MSiSFmWtojGUAP0WYWEXGxXuw7y5zkxb4uA7EAFII0WOmmfvgM4Vvw== - -"@swc/core-linux-x64-gnu@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.192.tgz#48f9fb73044dd99948ae05baa5d77e71b3af3e42" - integrity sha512-pwt2yYy8Ox1PqXNu4egYoDLi92gF+fIo3vzfyuPZo82ie/zG+7hBb/FJeoLcchih9vq+qnTEtrC8aWNjxkQOcw== - -"@swc/core-linux-x64-musl@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.192.tgz#2cf24fa2c9733369d9d85731aa33f81d55f37873" - integrity sha512-IXCsH7xdXLASIuHJXCSavHYU2X2O5+dmtG14bKsI2i3PTqdSFaRn7WTO7C2PlLeGFxC36V967BW0tCipE+OL0A== - -"@swc/core-win32-arm64-msvc@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.192.tgz#9f70fe568ac7ce3b5f96e27c93fddd3a041d1b3d" - integrity sha512-TSPsjvlfCz5DmTc4KZvp6KkH9xi+Ir1Y8hlISzqARl3hqI9Lv7HAoXvjkO9yMfkRAEpzwPQmeH2ZUtl0oOzeYA== - -"@swc/core-win32-ia32-msvc@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.192.tgz#6612357fec531bdeeef7076a66a172b1cdb0442e" - integrity sha512-yIH68QAY/x3ekCnIwHD4f4mXiUD3KIPdDtSmrMIbwV6NgdvcadY6BT861/NfXzCiG0+o1Jkf5790BEhiWnA4GQ== - -"@swc/core-win32-x64-msvc@1.2.192": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.192.tgz#cc049ba896e77d3337b1772b71702e42003345a3" - integrity sha512-x+blRKKYgI92vHJ7twIOKcvWifAyj5AeH0G6tCbUL2qXl2TjW1gDIyYagowH/9uiIueFLPwIc/X/1BP6HxpPLg== - -"@swc/core@^1.2.147": - version "1.2.192" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.192.tgz#03d24cb06a4142d91e5383e53303b5dc714936c7" - integrity sha512-qQPt1KLeuopZ6J50MTyXkaxkMpaXbG8IHKqMhPwhGD6oarOkVjpILgMfD5esWr9v8gb9yDyOrRrfbDSWdGxDNw== - optionalDependencies: - "@swc/core-android-arm-eabi" "1.2.192" - "@swc/core-android-arm64" "1.2.192" - "@swc/core-darwin-arm64" "1.2.192" - "@swc/core-darwin-x64" "1.2.192" - "@swc/core-freebsd-x64" "1.2.192" - "@swc/core-linux-arm-gnueabihf" "1.2.192" - "@swc/core-linux-arm64-gnu" "1.2.192" - "@swc/core-linux-arm64-musl" "1.2.192" - "@swc/core-linux-x64-gnu" "1.2.192" - "@swc/core-linux-x64-musl" "1.2.192" - "@swc/core-win32-arm64-msvc" "1.2.192" - "@swc/core-win32-ia32-msvc" "1.2.192" - "@swc/core-win32-x64-msvc" "1.2.192" - "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -6284,11 +6200,6 @@ neo-async@^2.6.0: resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -nes_rust_wasm@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nes_rust_wasm/-/nes_rust_wasm-0.1.2.tgz#ba4e462f62ccfb7bb6fe56a3720fe3d52a0d0d81" - integrity sha512-Ni/LFJ3RiVhRffYAGzaFY3PHtv5YhtDFl80Sl7OZeSZY/f17pGdZhN7gO+jgNLEbEy4FYm326k2puKL6d/KC3w== - no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -8640,18 +8551,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vite-plugin-top-level-await@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vite-plugin-top-level-await/-/vite-plugin-top-level-await-1.0.0.tgz#e462b5758f5f62d6d342395a7661599e99362d20" - integrity sha512-U18r2wD29eVdkfGAf8SbFgI7d/xo4fvZxrxnO9xyd5KKRjejmlxb+m66b1Kp2UANMWEoSi+kFoV49g+tPzbR5A== - dependencies: - "@swc/core" "^1.2.147" - -vite-plugin-wasm@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/vite-plugin-wasm/-/vite-plugin-wasm-0.0.2.tgz#36279c667f1c1cc406c34428e58e57853a43e57a" - integrity sha512-tZmwp8Mj7RhicenZeDYw9VXbuT+9u85FFiBIvNbdbhiF1cDJqdV44P1ia8a1nGCbN+Dz4Aq+t6fun1eUs3EJ6Q== - vite@^2.3.8: version "2.9.9" resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.9.tgz#8b558987db5e60fedec2f4b003b73164cb081c5e"