From d9fc5457bc436394551a819a6742141e0af0e3de Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 14 Apr 2025 19:47:48 +0200 Subject: [PATCH 01/20] Emscripten tests --- cmake/toolchain/emscripten.cmake | 40 ++ .../icicle-emulator/icicle-bridge/Cargo.lock | 420 +----------------- .../icicle-emulator/icicle-bridge/Cargo.toml | 6 +- 3 files changed, 56 insertions(+), 410 deletions(-) create mode 100644 cmake/toolchain/emscripten.cmake diff --git a/cmake/toolchain/emscripten.cmake b/cmake/toolchain/emscripten.cmake new file mode 100644 index 00000000..761a920a --- /dev/null +++ b/cmake/toolchain/emscripten.cmake @@ -0,0 +1,40 @@ +set(CMAKE_SYSTEM_NAME Emscripten) +set(CMAKE_SYSTEM_VERSION 1) + +# Specify the cross-compilers +set(CMAKE_C_COMPILER emcc) +set(CMAKE_CXX_COMPILER em++) + +# Set the Emscripten root directory +set(EMSCRIPTEN_ROOT_PATH $ENV{EMSDK}/upstream/emscripten) + +# Set the Emscripten toolchain file +set(CMAKE_SYSROOT ${EMSCRIPTEN_ROOT_PATH}/system) + +# Set the Emscripten include directories +set(CMAKE_FIND_ROOT_PATH ${EMSCRIPTEN_ROOT_PATH}/system/include) + +# Set the Emscripten library directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# Set the Emscripten linker +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_SDL=2 -s USE_SDL_MIXER=2") + +# Set the Emscripten runtime +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --shell-file shell_minimal.html") + +# Set the Emscripten optimization flags +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") + +# Set the Emscripten debug flags +set(CMAKE_BUILD_TYPE Release) + +# Set the Emscripten output format +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -o .html") + +# Set the Emscripten file extensions +set(CMAKE_EXECUTABLE_SUFFIX ".js") + +# Set the Emscripten runtime options +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXPORTED_FUNCTIONS='[_main]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'") \ No newline at end of file diff --git a/src/backends/icicle-emulator/icicle-bridge/Cargo.lock b/src/backends/icicle-emulator/icicle-bridge/Cargo.lock index 0cd2e74e..b507e56c 100644 --- a/src/backends/icicle-emulator/icicle-bridge/Cargo.lock +++ b/src/backends/icicle-emulator/icicle-bridge/Cargo.lock @@ -43,30 +43,12 @@ version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" -[[package]] -name = "arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - [[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.9.0" @@ -86,12 +68,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - [[package]] name = "bytemuck" version = "1.22.0" @@ -113,148 +89,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "cranelift" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27711210499725bafe52c320a988e27283e6cf477ee8edac57e8275bef8ea550" -dependencies = [ - "cranelift-codegen", - "cranelift-frontend", - "cranelift-module", -] - -[[package]] -name = "cranelift-bforest" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540b193ff98b825a1f250a75b3118911af918a734154c69d80bcfcf91e7e9522" -dependencies = [ - "cranelift-entity", -] - -[[package]] -name = "cranelift-bitset" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cb269598b9557ab942d687d3c1086d77c4b50dcf35813f3a65ba306fd42279" - -[[package]] -name = "cranelift-codegen" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46566d7c83a8bff4150748d66020f4c7224091952aa4b4df1ec4959c39d937a1" -dependencies = [ - "bumpalo", - "cranelift-bforest", - "cranelift-bitset", - "cranelift-codegen-meta", - "cranelift-codegen-shared", - "cranelift-control", - "cranelift-entity", - "cranelift-isle", - "gimli", - "hashbrown 0.14.5", - "log", - "regalloc2", - "rustc-hash", - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cranelift-codegen-meta" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2df8a86a34236cc75a8a6a271973da779c2aeb36c43b6e14da474cf931317082" -dependencies = [ - "cranelift-codegen-shared", -] - -[[package]] -name = "cranelift-codegen-shared" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf75340b6a57b7c7c1b74f10d3d90883ee6d43a554be8131a4046c2ebcf5eb65" - -[[package]] -name = "cranelift-control" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e84495bc5d23d86aad8c86f8ade4af765b94882af60d60e271d3153942f1978" -dependencies = [ - "arbitrary", -] - -[[package]] -name = "cranelift-entity" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963c17147b80df351965e57c04d20dbedc85bcaf44c3436780a59a3f1ff1b1c2" -dependencies = [ - "cranelift-bitset", -] - -[[package]] -name = "cranelift-frontend" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727f02acbc4b4cb2ba38a6637101d579db50190df1dd05168c68e762851a3dd5" -dependencies = [ - "cranelift-codegen", - "log", - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cranelift-isle" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b00cc2e03c748f2531eea01c871f502b909d30295fdcad43aec7bf5c5b4667" - -[[package]] -name = "cranelift-jit" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f74630af581f32b99c8f4e06ee45799383ecc0795e3ff8aa86b7584bb2d643fd" -dependencies = [ - "anyhow", - "cranelift-codegen", - "cranelift-control", - "cranelift-entity", - "cranelift-module", - "cranelift-native", - "libc", - "log", - "region", - "target-lexicon", - "wasmtime-jit-icache-coherence", - "windows-sys 0.59.0", -] - -[[package]] -name = "cranelift-module" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aaa16c4f18a15be310df221ea544f516acc42fc58ca96e09a3d08651744efa1" -dependencies = [ - "anyhow", - "cranelift-codegen", - "cranelift-control", -] - -[[package]] -name = "cranelift-native" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbeaf978dc7c1a2de8bbb9162510ed218eb156697bc45590b8fbdd69bb08e8de" -dependencies = [ - "cranelift-codegen", - "libc", - "target-lexicon", -] - [[package]] name = "crc32fast" version = "1.4.2" @@ -276,16 +110,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "errno" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "fallible-iterator" version = "0.3.0" @@ -340,15 +164,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.15.2" @@ -370,12 +185,12 @@ dependencies = [ [[package]] name = "icicle-cpu" version = "0.1.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "addr2line", "ahash", "anyhow", - "bitflags 2.9.0", + "bitflags", "bytemuck", "gimli", "half", @@ -387,30 +202,12 @@ dependencies = [ "tracing", ] -[[package]] -name = "icicle-jit" -version = "0.2.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" -dependencies = [ - "cranelift", - "cranelift-codegen", - "cranelift-jit", - "cranelift-module", - "cranelift-native", - "icicle-cpu", - "memoffset", - "pcode", - "target-lexicon", - "tracing", - "wasmtime-jit-debug", -] - [[package]] name = "icicle-linux" version = "0.1.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ - "bitflags 2.9.0", + "bitflags", "bstr", "bytemuck", "icicle-cpu", @@ -424,7 +221,7 @@ dependencies = [ [[package]] name = "icicle-mem" version = "0.3.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "ahash", "tracing", @@ -433,11 +230,10 @@ dependencies = [ [[package]] name = "icicle-vm" version = "0.2.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "anyhow", "icicle-cpu", - "icicle-jit", "icicle-linux", "ihex", "object", @@ -464,7 +260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown", ] [[package]] @@ -473,27 +269,12 @@ version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - [[package]] name = "memchr" version = "2.7.4" @@ -509,15 +290,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "miniz_oxide" version = "0.8.8" @@ -535,7 +307,7 @@ checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", "flate2", - "hashbrown 0.15.2", + "hashbrown", "indexmap", "memchr", "ruzstd", @@ -550,7 +322,7 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "pcode" version = "0.2.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" [[package]] name = "pin-project-lite" @@ -576,31 +348,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "regalloc2" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0" -dependencies = [ - "hashbrown 0.14.5", - "log", - "rustc-hash", - "slice-group-by", - "smallvec", -] - -[[package]] -name = "region" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" -dependencies = [ - "bitflags 1.3.2", - "libc", - "mach2", - "windows-sys 0.52.0", -] - [[package]] name = "ron" version = "0.8.1" @@ -608,7 +355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64", - "bitflags 2.9.0", + "bitflags", "serde", "serde_derive", ] @@ -619,25 +366,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - [[package]] name = "ruzstd" version = "0.7.3" @@ -682,7 +410,7 @@ dependencies = [ [[package]] name = "sleigh-compile" version = "0.3.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "pcode", "serde", @@ -695,23 +423,17 @@ dependencies = [ [[package]] name = "sleigh-parse" version = "0.3.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" [[package]] name = "sleigh-runtime" version = "0.1.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "pcode", "sleigh-parse", ] -[[package]] -name = "slice-group-by" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" - [[package]] name = "smallvec" version = "1.15.0" @@ -817,122 +539,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasmtime-jit-debug" -version = "26.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02a0118d471de665565ed200bc56673eaa10cc8e223dfe2cef5d50ed0d9d143" -dependencies = [ - "object", - "rustix", - "wasmtime-versioned-export-macros", -] - -[[package]] -name = "wasmtime-jit-icache-coherence" -version = "26.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da47fba49af72581bc0dc67c8faaf5ee550e6f106e285122a184a675193701a5" -dependencies = [ - "anyhow", - "cfg-if", - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "wasmtime-versioned-export-macros" -version = "26.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8efb877c9e5e67239d4553bb44dd2a34ae5cfb728f3cf2c5e64439c6ca6ee7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[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_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "xml-rs" version = "0.8.25" diff --git a/src/backends/icicle-emulator/icicle-bridge/Cargo.toml b/src/backends/icicle-emulator/icicle-bridge/Cargo.toml index 8019c2b2..f74bf4cf 100644 --- a/src/backends/icicle-emulator/icicle-bridge/Cargo.toml +++ b/src/backends/icicle-emulator/icicle-bridge/Cargo.toml @@ -7,6 +7,6 @@ edition = "2024" crate-type = ["staticlib"] [dependencies] -icicle-vm = { git = "https://github.com/icicle-emu/icicle-emu" } -icicle-cpu = { git = "https://github.com/icicle-emu/icicle-emu" } -pcode = { git = "https://github.com/icicle-emu/icicle-emu" } +icicle-vm = { git = "https://github.com/momo5502/icicle-emu" } +icicle-cpu = { git = "https://github.com/momo5502/icicle-emu" } +pcode = { git = "https://github.com/momo5502/icicle-emu" } From 68022ef501fbb6d7087b5672cf222d5b0ed8e146 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 14 Apr 2025 20:01:00 +0200 Subject: [PATCH 02/20] Fixes --- deps/CMakeLists.txt | 7 ++++--- src/backends/CMakeLists.txt | 4 +++- src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt | 4 +++- src/common/platform/compiler.hpp | 2 ++ src/windows-emulator/CMakeLists.txt | 2 ++ src/windows-emulator/windows_emulator.cpp | 8 +++++++- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 19217d54..eaca04f9 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,6 +1,7 @@ -set(UNICORN_ARCH "x86" CACHE STRING "") - -add_subdirectory(unicorn) +if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + set(UNICORN_ARCH "x86" CACHE STRING "") + add_subdirectory(unicorn) +endif() ########################################## diff --git a/src/backends/CMakeLists.txt b/src/backends/CMakeLists.txt index 12d192df..49734038 100644 --- a/src/backends/CMakeLists.txt +++ b/src/backends/CMakeLists.txt @@ -1,4 +1,6 @@ -add_subdirectory(unicorn-emulator) +if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + add_subdirectory(unicorn-emulator) +endif() if (MOMO_ENABLE_RUST_CODE) add_subdirectory(icicle-emulator) diff --git a/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt b/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt index 73ea9f1d..d64c0d21 100644 --- a/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt +++ b/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt @@ -13,7 +13,9 @@ endif() set(CARGO_TRIPLE) set(CARGO_OPTIONS) -if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) +if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + set(CARGO_TRIPLE "wasm32-unknown-emscripten") +elseif(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) set(CARGO_TRIPLE "i686-pc-windows-msvc") elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") set(CARGO_TRIPLE "aarch64-apple-ios") diff --git a/src/common/platform/compiler.hpp b/src/common/platform/compiler.hpp index 5cece6a8..07fc82c2 100644 --- a/src/common/platform/compiler.hpp +++ b/src/common/platform/compiler.hpp @@ -13,6 +13,8 @@ #define OS_MAC #elif defined(__linux__) #define OS_LINUX +#elif defined(__EMSCRIPTEN__) +#define OS_EMSCRIPTEN #else #error "Unsupported platform" #endif diff --git a/src/windows-emulator/CMakeLists.txt b/src/windows-emulator/CMakeLists.txt index 16167e84..94ec8aa2 100644 --- a/src/windows-emulator/CMakeLists.txt +++ b/src/windows-emulator/CMakeLists.txt @@ -14,9 +14,11 @@ if(NOT MOMO_ENABLE_CLANG_TIDY) target_precompile_headers(windows-emulator PRIVATE std_include.hpp) endif() +if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") target_link_libraries(windows-emulator PRIVATE unicorn-emulator ) +endif() if (MOMO_ENABLE_RUST_CODE) target_link_libraries(windows-emulator PRIVATE diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 4cb8b45f..372d1d19 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -3,7 +3,9 @@ #include "cpu_context.hpp" +#ifndef OS_EMSCRIPTEN #include +#endif #if MOMO_ENABLE_RUST_CODE #include @@ -263,6 +265,10 @@ namespace std::unique_ptr create_default_x64_emulator() { +#ifdef OS_EMSCRIPTEN + return icicle::create_x64_emulator(); +#else + #if MOMO_ENABLE_RUST_CODE const auto* env = getenv("EMULATOR_ICICLE"); if (env && (env == "1"sv || env == "true"sv)) @@ -270,8 +276,8 @@ std::unique_ptr create_default_x64_emulator() return icicle::create_x64_emulator(); } #endif - return unicorn::create_x64_emulator(); +#endif } windows_emulator::windows_emulator(application_settings app_settings, const emulator_settings& settings, From a35745ba905399bdd9b7100557441566aec3c826 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 14 Apr 2025 20:16:30 +0200 Subject: [PATCH 03/20] Fix functions --- src/backends/icicle-emulator/icicle_x64_emulator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/icicle-emulator/icicle_x64_emulator.cpp b/src/backends/icicle-emulator/icicle_x64_emulator.cpp index d6296d76..46276f22 100644 --- a/src/backends/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/backends/icicle-emulator/icicle_x64_emulator.cpp @@ -25,8 +25,8 @@ extern "C" int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length); int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length); int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); - int32_t icicle_save_registers(icicle_emulator*, data_accessor_func* accessor, void* accessor_data); - int32_t icicle_restore_registers(icicle_emulator*, const void* data, size_t length); + void icicle_save_registers(icicle_emulator*, data_accessor_func* accessor, void* accessor_data); + void icicle_restore_registers(icicle_emulator*, const void* data, size_t length); uint32_t icicle_add_syscall_hook(icicle_emulator*, raw_func* callback, void* data); uint32_t icicle_add_interrupt_hook(icicle_emulator*, interrupt_func* callback, void* data); uint32_t icicle_add_execution_hook(icicle_emulator*, uint64_t address, ptr_func* callback, void* data); From 1d47e06253336feee31641cfee05a616bce2409d Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 14 Apr 2025 20:25:38 +0200 Subject: [PATCH 04/20] More fixes --- cmake/compiler-env.cmake | 5 ++++- cmake/utils.cmake | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index 9238fee4..a6602ecd 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -22,7 +22,10 @@ cmake_policy(SET CMP0069 NEW) set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) + +if(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten") + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +endif() ########################################## diff --git a/cmake/utils.cmake b/cmake/utils.cmake index 4c9dc09b..9b96e990 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -335,7 +335,7 @@ function(momo_strip_target target) return() endif() - if(MSVC OR MOMO_ENABLE_SANITIZER OR CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android") + if(MSVC OR MOMO_ENABLE_SANITIZER OR CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME MATCHES "Emscripten") return() endif() From 1959f94c39d006b02ff48d758760db3ad71997a9 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 17 Apr 2025 18:54:16 +0200 Subject: [PATCH 05/20] Support logging for emscripten --- src/windows-emulator/logger.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/windows-emulator/logger.cpp b/src/windows-emulator/logger.cpp index ea4dc2ee..72e18404 100644 --- a/src/windows-emulator/logger.cpp +++ b/src/windows-emulator/logger.cpp @@ -6,16 +6,19 @@ namespace { #ifdef _WIN32 -#define COLOR(win, posix) win +#define COLOR(win, posix, web) win using color_type = WORD; +#elif defined(__EMSCRIPTEN__) +#define COLOR(win, posix, web) web + using color_type = const char*; #else -#define COLOR(win, posix) posix +#define COLOR(win, posix, web) posix using color_type = const char*; #endif color_type get_reset_color() { - return COLOR(7, "\033[0m"); + return COLOR(7, "\033[0m", ""); } color_type get_color_type(const color c) @@ -25,23 +28,23 @@ namespace switch (c) { case black: - return COLOR(0x8, "\033[0;90m"); + return COLOR(0x8, "\033[0;90m", ""); case red: - return COLOR(0xC, "\033[0;91m"); + return COLOR(0xC, "\033[0;91m", ""); case green: - return COLOR(0xA, "\033[0;92m"); + return COLOR(0xA, "\033[0;92m", ""); case yellow: - return COLOR(0xE, "\033[0;93m"); + return COLOR(0xE, "\033[0;93m", ""); case blue: - return COLOR(0x9, "\033[0;94m"); + return COLOR(0x9, "\033[0;94m", ""); case cyan: - return COLOR(0xB, "\033[0;96m"); + return COLOR(0xB, "\033[0;96m", ""); case pink: - return COLOR(0xD, "\033[0;95m"); + return COLOR(0xD, "\033[0;95m", ""); case white: - return COLOR(0xF, "\033[0;97m"); + return COLOR(0xF, "\033[0;97m", ""); case dark_gray: - return COLOR(0x8, "\033[0;97m"); + return COLOR(0x8, "\033[0;97m", ""); case gray: default: return get_reset_color(); From cd348e009582c450ac1ba2e1ddf3402340205846 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 17 Apr 2025 18:54:46 +0200 Subject: [PATCH 06/20] Add padding --- src/common/platform/kernel_mapped.hpp | 1 + src/common/platform/unicode.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/common/platform/kernel_mapped.hpp b/src/common/platform/kernel_mapped.hpp index 931c5d35..221545fb 100644 --- a/src/common/platform/kernel_mapped.hpp +++ b/src/common/platform/kernel_mapped.hpp @@ -883,6 +883,7 @@ typedef struct _KERNEL_USER_TIMES struct THREAD_TLS_INFO { ULONG Flags; + uint32_t _Padding; union { diff --git a/src/common/platform/unicode.hpp b/src/common/platform/unicode.hpp index f76bac36..f9cf9561 100644 --- a/src/common/platform/unicode.hpp +++ b/src/common/platform/unicode.hpp @@ -8,6 +8,7 @@ struct UNICODE_STRING { USHORT Length; USHORT MaximumLength; + uint32_t _Padding; EMULATOR_CAST(typename Traits::PVOID, char16_t*) Buffer; }; From c1553ad2ecf527c178a22e84400ae4ae71b7812a Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 17 Apr 2025 18:57:17 +0200 Subject: [PATCH 07/20] Fixes for emscripten --- .github/workflows/build.yml | 8 ++ .gitmodules | 2 +- cmake/compiler-env.cmake | 21 +++++ deps/CMakeLists.txt | 6 +- deps/unicorn | 2 +- src/backends/CMakeLists.txt | 4 +- .../unicorn-emulator/function_wrapper2.hpp | 88 +++++++++++++++++++ .../unicorn-emulator/unicorn_x64_emulator.cpp | 39 +++++--- src/windows-emulator/CMakeLists.txt | 2 - src/windows-emulator/windows_emulator.cpp | 8 +- 10 files changed, 152 insertions(+), 28 deletions(-) create mode 100644 src/backends/unicorn-emulator/function_wrapper2.hpp diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5f06e03d..aee2a841 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -161,6 +161,7 @@ jobs: - iOS arm64 - Android x86_64 - Android arm64-v8a + - Emscripten configuration: - Debug - Release @@ -201,6 +202,9 @@ jobs: abi: arm64-v8a rust-target: aarch64-linux-android cmake-options: "-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchain/android-ndk.cmake" + - platform: Emscripten + runner: ubuntu-24.04 + cmake-options: "-DMOMO_ENABLE_RUST_CODE=Off -DCMAKE_TOOLCHAIN_FILE=$(dirname $(which emcc))/cmake/Modules/Platform/Emscripten.cmake" steps: - name: Checkout Source uses: actions/checkout@v4 @@ -214,6 +218,10 @@ jobs: if: "${{ matrix.rust-target }}" run: rustup target add ${{ matrix.rust-target }} + - name: Install Emscripten + if: "${{ matrix.platform == 'Emscripten' }}" + uses: mymindstorm/setup-emsdk@v14 + - name: Install Clang if: "${{ matrix.platform == 'Linux x86_64 Clang' }}" run: | diff --git a/.gitmodules b/.gitmodules index 9c5a000b..ce0fdeaf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,7 +2,7 @@ path = deps/unicorn url = ../unicorn.git shallow = true - branch = dev + branch = wasm [submodule "deps/reflect"] path = deps/reflect url = https://github.com/qlibs/reflect.git diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index a6602ecd..5f610950 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -23,6 +23,8 @@ set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +########################################## + if(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten") set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) endif() @@ -49,6 +51,9 @@ if(UNIX) momo_add_c_and_cxx_compile_options( -fvisibility=hidden -ftrivial-auto-var-init=zero + #-Wbad-function-cast + #-Wcast-function-type + -Wno-int-conversion ) endif() @@ -86,6 +91,22 @@ endif() ########################################## +if(CMAKE_SYSTEM_NAME MATCHES "Emscripten") + add_link_options( + -sALLOW_MEMORY_GROWTH=1 + -sASSERTIONS + -sWASM_BIGINT + -sENVIRONMENT=web + -sUSE_OFFSET_CONVERTER + -sEXCEPTION_CATCHING_ALLOWED=[..] + -sEXIT_RUNTIME + #-lnodefs.js -sNODERAWFS=1 + #-sASYNCIFY +) +endif() + +########################################## + if(MSVC) string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE "/EHs" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index eaca04f9..5ed0c395 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,7 +1,5 @@ -if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - set(UNICORN_ARCH "x86" CACHE STRING "") - add_subdirectory(unicorn) -endif() +set(UNICORN_ARCH "x86" CACHE STRING "") +add_subdirectory(unicorn) ########################################## diff --git a/deps/unicorn b/deps/unicorn index 73be28b6..b29e3445 160000 --- a/deps/unicorn +++ b/deps/unicorn @@ -1 +1 @@ -Subproject commit 73be28b6509d0cbf3333071aec4efbb9be1f1e59 +Subproject commit b29e3445a4694e3a1061c910906b57d7d2a05ed9 diff --git a/src/backends/CMakeLists.txt b/src/backends/CMakeLists.txt index 49734038..12d192df 100644 --- a/src/backends/CMakeLists.txt +++ b/src/backends/CMakeLists.txt @@ -1,6 +1,4 @@ -if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - add_subdirectory(unicorn-emulator) -endif() +add_subdirectory(unicorn-emulator) if (MOMO_ENABLE_RUST_CODE) add_subdirectory(icicle-emulator) diff --git a/src/backends/unicorn-emulator/function_wrapper2.hpp b/src/backends/unicorn-emulator/function_wrapper2.hpp new file mode 100644 index 00000000..f9628bda --- /dev/null +++ b/src/backends/unicorn-emulator/function_wrapper2.hpp @@ -0,0 +1,88 @@ +#pragma once + +#include +#include + +#include + +uint32_t resolve_indexed_argument_part(uint32_t* args, size_t& index) +{ + return args[index++]; +} + +template +T resolve_indexed_argument_internal(uint32_t* args, size_t& index) +{ + const auto a1 = resolve_indexed_argument_part(args, index); + + if(sizeof(T) <= sizeof(a1)) { + return (T)a1; + } + + const auto a2 = resolve_indexed_argument_part(args, index); + + const auto arg = (a1 | ((uint64_t)a2 << 32)); + return (T)arg; +} + +template +T resolve_indexed_argument(uint32_t* args, size_t& index) +{ + auto arg = resolve_indexed_argument_internal(args, index); + return arg; +} + +template +class function_wrapper2 : public utils::object +{ + public: + using user_data_pointer = void*; + using c_function_type = ReturnType(Args..., user_data_pointer); + using functor_type = std::function; + + function_wrapper2() = default; + + function_wrapper2(functor_type functor) + : functor_(std::make_unique(std::move(functor))) + { + } + + c_function_type* get_c_function() const + { + return (c_function_type*)(void*)+[](uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,uint32_t a5,uint32_t a6,uint32_t a7,uint32_t a8,uint32_t a9,uint32_t a10,uint32_t a11,uint32_t a12)-> uint64_t { + + uint32_t real_args[] { + a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12 + }; + + const auto lambda = +[](Args... args, user_data_pointer user_data) -> ReturnType { + return (*static_cast(user_data))(std::forward(args)...); + }; + + size_t index = 0; + std::tuple func_args{resolve_indexed_argument>>(real_args, index)..., resolve_indexed_argument(real_args, index)}; + + (void)index; + + if constexpr(!std::is_void_v){ + return (uint64_t)std::apply(lambda, std::move(func_args)); + } + + std::apply(lambda, std::move(func_args)); + return 0; + }; + } + + void* get_function() const + { + return reinterpret_cast(this->get_c_function()); + } + + user_data_pointer get_user_data() const + { + return this->functor_.get(); + } + + private: + std::unique_ptr functor_{}; +}; diff --git a/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp b/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp index 6c449b13..97cd07c3 100644 --- a/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp @@ -7,6 +7,7 @@ #include "unicorn_hook.hpp" #include "function_wrapper.hpp" +#include "function_wrapper2.hpp" #include namespace unicorn @@ -385,10 +386,7 @@ namespace unicorn emulator_hook* hook_instruction(const int instruction_type, instruction_hook_callback callback) override { - function_wrapper wrapper([c = std::move(callback)](uc_engine*) { - return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0; - }); - + unicorn_hook hook{*this}; auto container = std::make_unique(); @@ -396,18 +394,39 @@ namespace unicorn if (inst_type == x64_hookable_instructions::invalid) { + function_wrapper wrapper([c = std::move(callback)](uc_engine*) { + return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0; + }); + uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN_INVALID, wrapper.get_function(), wrapper.get_user_data(), 0, std::numeric_limits::max())); - } - else - { + container->add(std::move(wrapper), std::move(hook)); + } + else if(inst_type == x64_hookable_instructions::syscall){ + function_wrapper wrapper([c = std::move(callback)](uc_engine*) { + c(); + }); + const auto uc_instruction = map_hookable_instruction(inst_type); uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN, wrapper.get_function(), wrapper.get_user_data(), 0, std::numeric_limits::max(), uc_instruction)); - } - container->add(std::move(wrapper), std::move(hook)); + container->add(std::move(wrapper), std::move(hook)); + } + else + { + function_wrapper wrapper([c = std::move(callback)](uc_engine*) { + return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0; + }); + + const auto uc_instruction = map_hookable_instruction(inst_type); + uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN, wrapper.get_function(), + wrapper.get_user_data(), 0, std::numeric_limits::max(), + uc_instruction)); + + container->add(std::move(wrapper), std::move(hook)); + } auto* result = container->as_opaque_hook(); @@ -533,7 +552,7 @@ namespace unicorn c(address); // }; - function_wrapper wrapper(std::move(exec_wrapper)); + function_wrapper2 wrapper(std::move(exec_wrapper)); unicorn_hook hook{*this}; diff --git a/src/windows-emulator/CMakeLists.txt b/src/windows-emulator/CMakeLists.txt index 94ec8aa2..16167e84 100644 --- a/src/windows-emulator/CMakeLists.txt +++ b/src/windows-emulator/CMakeLists.txt @@ -14,11 +14,9 @@ if(NOT MOMO_ENABLE_CLANG_TIDY) target_precompile_headers(windows-emulator PRIVATE std_include.hpp) endif() -if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") target_link_libraries(windows-emulator PRIVATE unicorn-emulator ) -endif() if (MOMO_ENABLE_RUST_CODE) target_link_libraries(windows-emulator PRIVATE diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 372d1d19..4cb8b45f 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -3,9 +3,7 @@ #include "cpu_context.hpp" -#ifndef OS_EMSCRIPTEN #include -#endif #if MOMO_ENABLE_RUST_CODE #include @@ -265,10 +263,6 @@ namespace std::unique_ptr create_default_x64_emulator() { -#ifdef OS_EMSCRIPTEN - return icicle::create_x64_emulator(); -#else - #if MOMO_ENABLE_RUST_CODE const auto* env = getenv("EMULATOR_ICICLE"); if (env && (env == "1"sv || env == "true"sv)) @@ -276,8 +270,8 @@ std::unique_ptr create_default_x64_emulator() return icicle::create_x64_emulator(); } #endif + return unicorn::create_x64_emulator(); -#endif } windows_emulator::windows_emulator(application_settings app_settings, const emulator_settings& settings, From 7d7336e8d5b1015f1fc3ccc3bc49a0acf8a89a29 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 17 Apr 2025 19:52:18 +0200 Subject: [PATCH 08/20] Deploy page --- .github/workflows/build.yml | 26 +++ page/bigboiii.webp | Bin 0 -> 51370 bytes page/emulator.js | 35 +++ page/index.html | 431 ++++++++++++++++++++++++++++++++++++ page/noise.webp | Bin 0 -> 37576 bytes page/why-eclipse.svg | 20 ++ page/why-eclipse2.svg | 20 ++ 7 files changed, 532 insertions(+) create mode 100644 page/bigboiii.webp create mode 100644 page/emulator.js create mode 100644 page/index.html create mode 100644 page/noise.webp create mode 100644 page/why-eclipse.svg create mode 100644 page/why-eclipse2.svg diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aee2a841..0c2bc13f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -481,6 +481,32 @@ jobs: arch: ${{matrix.architecture}} script: "adb push build/${{matrix.preset}}/artifacts/* /data/local/tmp && adb shell \"cd /data/local/tmp && export LD_LIBRARY_PATH=. && chmod +x ./analyzer && EMULATOR_ICICLE=${{ matrix.emulator == 'Icicle' }} ./analyzer -e ./root c:/test-sample.exe\"" + page: + name: Page + runs-on: ubuntu-latest + #needs: [build] + permissions: + contents: read + pages: write + id-token: write + steps: + - name: Checkout Source + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./page + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + summary: name: Pipeline Summary runs-on: ubuntu-24.04 diff --git a/page/bigboiii.webp b/page/bigboiii.webp new file mode 100644 index 0000000000000000000000000000000000000000..15089347cf42833e160b7a42568e7b188d8ed2b6 GIT binary patch literal 51370 zcmWIYbaPvDf`K92)hQq>z#@W+fq_ARfq}t*34}bIodZrVGB7YOFrEOBECvh=xp^f; zLGDfp5s^^}><<_i8Nl)k42j9b1t2vzFe3xQw`&l!mvwQd!6(d_l3JY1z`*cfiVEYE(!^9W?*1UVPIg;NJnBPA+eJS zia_dn7#J9Aa&t;Sc7faj@*PiVUT81_0|N&G1A`1hF+&i8JA)I*{~!en4Ec)~7%aXr zFfdO*h$YQrVA$Tuz#wr8A*Ql`fq}n;fnnQugcu@B3KEMF!RE0rFfcHsr7Re1U<1D;g}vz`%gRZJ2XUJzrXUJhlWl&)7WXNMkX3%3$U@&4ZU@&Ab z3k$ID*?f$FLEnI>hk>_Lanb*SK^zJUT(delI?jm4ysfYCo|NJ_DJ6Q*=l}QbuqpYR zS(G+!rfEOhrEQ+?<3Fb>!IM(@GB;`_`Vr+%7D*ydaIe^xwm=Itfl*Z<^>+_1JS*W_^3mb{QeZzq5L z6l>4@Fl(j${=aV+Z#k81)fpe1talSb`#ElH>$UzD!T-?l_O{#?J%9h-)2g|+E%fTP z+-TzqbA7TGPtP()}|NqT(SIB()tNdTH zkjlwKY0X8=?T4j~H88OCvUvnfivR!pUXr1O-sSVQx05zTMCyoncOUiVJiS?U!;#=Z z4($Z*m>zZR8ygE_rfNqVH{wg&eRxaqWecNo-fzsNf8Wto8u-@c`1RKhS@-<>^P=Xc z;SZU8v*qU>@A&C+VE*;Se%o`$4|l!Ycw~l!M0rxIGIQUn6j8^TG}DI;o9!pJJ#TvP zXN_l{wEp(T8xFPju0HfEGcwZH=YfIG@wmC~H{aZ%v-+Kw_xktGx4r1iyl^AWx4LKR zTKmJdUpxHZ5I(;(Ea8~ha)}-9!j{c9NvgQ8t0H8IXu43_9*)+-*L-}}FD$u`vvGD> zl8+4QcmB9y=4gFsg_(s1k~T)@h;<(&OkHD0)Ai6kb9`p_wOzmd<=mEi>umNX#rEu* zqW<*xw^^Nwl+yp5*gEm7)uE1t1DAI9?tZ$EOMmsxe95@D()zatZm+mG`Cr%B?o-BF zr+ZnH@PE3UBz<(wQJYuEp$ji_7<<=i{aP>Z@95(91{Wn~`*LseTys?av0?Fdsr<*g z)j!NQd((2?TE-w{UrGPRKU)`FV^z!ltzq=cqQ}OzmjAdx#Y(yS2(RzoUWabVt<;~n zip}e?_}x#z=eNE7CaSwFc%^KT#1vuqX#VHhKP)xoH?=*r_b4m>D&OvP%M4_{=6Gu} zGya$%e(r-~?ftK3+M0e}`2OYjljYU&-`~m2E4)49zrt@nw;%sL9+>{Az4c$w^9UDV z?S4-0SvnglYgcpsNwJv7wQs@Y?TR1os{Iz{E4}ddoZW=gt2w)_KC|ZMzs;;Jvv9+U zOU5TQ_`9(m|M;R^{`0(ow!3<$V#} zEq&4Mio(4Em4$rXW$(oPK7SUoZU3Pvi~Zhb(|3I?O{vjbyLy&-Vy!IC@rOIsI+uLT z(O%pxOWSLVEZ@y=%Jd!vH$ zs(B*OIC$#U(oOL@90*$ZATYu-KKY{uQ~Yg#<|lPPCBRBv7A4epP~1q z>EH+3+5Z2zuGxP+{Qpu!w{Cs^Q@+>xy}#&-tjoJCFM89v^5OOeM-C*_PMF(vzCNvg z!6m1Q-TGDEKHBqbIFh4#wBy*jBTrw4u6Jc#zft1aqMttV0<5yH9MYa;eZ8wi^u~h8 z>iTO6J(Mryyer#pb+4H3tjil8=~7wK%MLHMd~PjSzI^XWvHGnNk`p-HpLpK%-f8|j zH*tCW_rzm~-+vp1uWC8`y-+eeY@^Y$&h7ut{M+_gDD@@N$D{9Lr<_eH&tJx^RG_@> zK)c8T?e3$-orzbIKITM<@h-l2yY9>3i=H8B+3|adFP-YO729xyuSbS$|Kr;Ec~Ad) zPRozpwf%)i@xz~Sx!2abw(d!|lzejbProy^(`%;fdU}6`M2oJmlG~qT`#=7@6L(DO zT)5+}-R({9-_HC0-g=MjhHvY**81Ojw9US~J?0ogNwVEEhM)aA|1XzcvYg4?`fs}Q zAMf0+iigYQifow?^LDe+K9k~3F|%CNk9y~g#oVs9zuR?MY_CCNt@QbfpK9|vk9+qh zC7v>MmnhHu;x>ghanaa>y#RnXf|7|nxuG5ZH^)IUZvVGQUbKM=%%`ds%>1&C=1{YqA`}r2Z z=WbuTDrymRq*L^3x5Tw=2CtRVWRIz|-&V1{bGDl|^|hbP%dqD+3p%x9U)nx$`F@ml z+1`w`6LNM`8vLv{i$k==!(GK8@xYmhU8>*|eyTLu9i_8wVom^T0Z0zXTB_cwA@ z8F$kY=KbtiVZJZv(ZgeH8_F-SX6@sw|9{?W-oZBsUqoMSORF|LvSgOA>RxrRTN8is zdH=|&US*h5xY>B>e>|+Ws88kH<+^F9g__-pGW+uxb7engMOB=S zFaM!mTEH_?KQ-pu#02a25{DZfw*G35)swUQf2S_X)$38?mJ3D~Obs8Y^`(pN{rLBC zY`x{-iPIQ;rpjd>lUT)m-uLUF^(Fc8lLQTQ42{kk_f7lzS}&JXIrfOw#Feq4Yi%#} z1kOmi>09f#X|wu{(92~)i(?X=7Ee~6YO5+U(^!+CG}NN)%ygr5w({wHiht}Q&EtgQ z^wS09OoWa7t_HCm-Y%D=b$i`~+P)8WWOlzlJ+oWV`CDbBe);zGyXKew4Xsns&wl^l zP;%nM>YP>i3m$nJeN>&fL8aKnT=A8V>5pd?kB`ndomxNb8e{d8V=KMp=WQv`4Y640 zYazw6^Ridup^`OcK3Mf72$%jSztO78zWx6U^KFvT)_nbO==AL(IX|}_6VhaEH7Wm& zv<-XU(&jF)BfdEIxu?nDV%c+<+a|gCGd_#BbH488!$X%-?Nes7v=+Q~?LAUebL!b=PM%e#ENnmiFX=yUL0jPI)cB0L z1*X?h^)ps}m38Ike6JuCtMPIErRHQqyRD(t+l8`@7ksV}wTPH8G1~sZHN%^aB3d^2 zCHa34nfzl#^2J}lCRRBs%j--e3V#c+9T(oRVBg}_^l4%F+Y%ydW8-{h2A`DcG&J^@ z@9(i`O}N*^KlUxhzdpSuYTAEKX4<|d3NBK!e=lx1`twTJn-fpP-~U-6|6KAX_w&O? z7qCw)n>WQ^g7(!ZqW-CUPo_5*T$DNO`(dHk@vfM|w|e;_p3Pj=ziD++>MHe|vm!e< zE*|*2CXT&TVoiPcboWp0MGBAW1@t%Xz8fse&Tn=j<ovZ)YyP1Pj!z5gp8j;SZCb&5*7)VlTRTOQ zLe`14UVI`kEh+rI#=es_FOMg#T+MdLL@4o7qx#1ZojvVppBKw){}eH`#^;H5f$2s5 zw=pL+R=n~0t$n?=#Z}$i!i?ugLe%X;ZRr({w!GQqu9~TGVZt|i8ScXA#*G`cRLW$o zm%Ob0z4q}!_X%4RMStGd8EUmJ|G)pI{(o9yz=AJ`!jhH4{=X+tBIf7?B2V6y^W4&B_HWyH|Cyii*O{@$FYUe5ELytT*3w<; zP_fTM{e{gBeSX$W*}tH2VzKIibt~VlY+v-|VsnYS@qsyqdk#KW?aJ0?v_;mY;8(#F z2YuCPonfBzWBgU()-y>+pF^8*`1FhR@ZIJxWumf@10a;-LB-sJ8P!a#Axns zYoBQRw(4B$#x=7JYSk^Nx?WUs|Ea{51B%TLHeU!y+dc9B@voD%_g@K|cbA3zqikaK z&AWYaYYuBo?tS-Vby9V4?&CdIyJVP;*M7En7N1)CY9B|<$!TRD(jIts8k@GYIPWxm ziT~Vk|wJf1stW@a7f$1$v=6Brr5%kFC(1b7Z**`9R*(WjY%7%SErzCDz zX_nFusNmb(_t!qw`0m3Q>E+v(>z7KHH!rci`{ewN=bzT!FyxH>$8^2<-IhgXrrxps zx0qY~sd$a&#+9P(54;!;3txTx?v=!wFDDr`1*dbZImqCmQ~E_WW@%tW-{CKZEN0D0 zTCnuZqEk(qr^NrX-`nHl!yVBhz3}KV=BaapHRnCmWxCIFT}khw>hTGmJEy+??Atx_ z+)NX_{&OFetWRIEJVExBwna<)nweCv4^2X^I$689#SeWvnT38DU7XP+&vd%w{7M%P^Z zsh0LdI)d&-FYK-~tg*|q^|uu{Y8Y*e#-W$u9pL@QyIuSK7dB>^0JAX{Cn{lPlI40Knt8D zd(F4`k6bS`$h22(+}ORf9AlO_vd*0<`$9D1%>#n!1P?HhUc)Gs5R1??XG zmVDRUPV;@Q@b>TdXD`&ePWbGv{4WQ(2C&6Tjc zIzRqQ`5wL6->JG4(ar}By87rZg&1wmi%c=5l1#> z|C^t?FvsDh&1TP)o>iBVVoX+)^_||=^QXM`;g1@g(~FFl+pCwg^qyUzJXg2cAhvjx zZAn7Z#mT!z{n`82KT-aR1^!pnP=7VO>Om}mD`BS^g9 zUK0B?hUcyCI|bu+U91pFSBh7%f3$9Osr>Z@r@hD59(&*E-5Yeltm6cqzrX3^+jk6C z<{gQay?#dAtw~sl>H)F6nF4k8gQr zx+=cr;hlSp$scY9&HNE`tzzA)%$~@pwy6~-CKv4$Q;M3wmoi5q=qb;l9~U<2{INgg z-@1B6yOr8y_jplTtCvYU>;6`-xAE#S&Fl2%T@%A0ZS^7I`mKYm`_8{^`g%Ub`|OuV z1)P^-+-09>SqQmrdT%~k(OS4|rP}AEJqKSKr#I;v)qN4D3|V)6*ZEk}ENxRE1NSwF zsq95-OAO{jmE^iCfAX2LXVJq)+D@TQDm?raURYr0_)mGtGXF_=DamuzNF`XzwwPL? zXgl9k&Q<0@{S)o~7aobPsVJA(E|)v4@I%5A?^V|(g|VL!yjJ9Owd#4#tE1B;HhbB4 zebidNzdt!Pm7VdA{QJKmahABZpquY-4}LW>4=hFymhJMJTX<98{y^; zcEsyH=&;_mr*2*69*;F1g_>o{OQ-FAoxW}5XOsO(@mVsSpEF&$!Z-f2>nois%li5M z60;z-N5aPqKmHWhw`}{SZ9@KUcQCUFn%!ElxpYF|rlqZ)wGub+eUWA6tJF$7D|gm* zTKR^!aDl0`%Q0M zI5+b`<70z$A{&lW@g84o&GyiPCr5qmKg|dpU)zu^Js$$f`i@&CSs%4ik$HZD-Q>u# zUmeLgF)`Avp~(*-vL8fm=ZpC*X?Ik8;W2(Ar*~3;@6-y{#fzRdOHsGEy!==3okK1W zW#aSx9jQ>+U2Dbm-0M)=%gm?qDG% zvZri*uY~GO)i0f)vu1U#^PRC^F;CJRe!1+=Qe|=sNe3qF$~Z21tnRMk>eE*`qL>$j ziF94;*cN+p5C3Va0{^g2>sRQ$`*O@V{KcH6qatTAb7cA7P1TIpBe_gtah3nH?q8f~ z%FUd*JA;B|WY62dcEzS^j^<0-D`iG}iY0T?*I$2mcXgz`B^%en|1)1KyrSOtT&L;H z&yXyY%sEFqC3k$QJkEY);}SikbtNA6!fuzc&&_`<74RtPh>=uahTB_>(hbj_R+z7u z8E2K#bHB#G=EviEX9~{52JY6|%3!YK?p1aEj_SgX_=XN|*PeO1g`ZvA@XT=5TDR!4 zH_R71U$t*szF~%eiPTpV{U&OQX-!y&A z6aFcRUnaiP=GZb_;_3RAs)rQkgw0CrJ2~s|L#?ExE^Ic}BAlv^O)K6ft!BM<%EjAk z_bo4{vTwEZVQ2Jy;?|~^>|40LL;cLUqUmq9zRI0iv#fTHp`x_nymU9a%#>YW*AFG# zU<%g~t_rMYi;n6uSh8d4(@QhxHWjDDr&X;8WB$+o zvz&wdwbB6*tE@Kt-`ndLrcW(@?wad*!$be8>YU@(HQJ2#u4=QlPT@J%+j4N{lx%m) zcdC9n3b+2-@-#N~--U;|x?5%2ZLPK4WtjX|ed#v)D7WXKkN2HZMVSryA-kU`_lsEs z>pQGFC+fW7e2r%EiLW{{4@a17x8Z0$llq1!p{dbFK0@MA2X_Xp%=zlb8c!< zx4P-H!{)krTjobj{C@S^X(9hvM!6Hqbbc44W&6B*U&!-_>3qigU6-9VvjkZ!>vp?m zd06<~DvA6P$E(&vvwsRNet0%v6`mQG4j(NleXF~-|MhX43=zbDbD74d5= za<2Wpetv_5y+ZR#@lu(({FOgv_nxc_lGguO*RNf9DMiku3Pw_m78}=ePSmc{K)fc{|~u6ziXtkte?2` zH5Td|TP=2OiKKh^^{ZXS>XNeJCJX#7Q2TYfaLK$vJLA0{XB0Ch{3`w)yl|yVx5Vn? z6NTY_PWDWHnq?>d?yJSIXBN@yWf9EvWhW$z<{Rm4{h)jPW#=F5J?uXpCw+X?xcTxw zheXe_Q=XpS;*vNpdD5&LSrhYJE6sD$cT7xnDF0N{5uQ6o^G4X*qC&Id&+6usB%bg~ zb30^k&2x7CGa2IpJ6U?Y3mvz7V^(UNU zW1suZs>|5P^yj81o0D7TX3up`J@$Bx#%t$D|5H1U{^~LIh`x4tWwu(K!gZT@jjvZ; zvFS`+G<8XshkWW&)qnF8zD!#8xBXje=AJ99)A(ei-{t=#bmr=hb8Gg6GphHrZ!6DDNo@T7(Dbazf4})V8;gU&N|M($i ztuf<&xB1Jz{{C=k|7D3z)k4+!`ZG^>^^g6Sx{u+;zwq7X4qNOrQLNl@Wa*mSPk(Au zyLq+m+`hx@^1T+tcixYq9=+hWZn2_0Cj6OJyZ)Xi^My&BVr= z=i9!WyO!8~abDa3!9S+QSvfPz%sh|nU~;~gXD#>G+ME4c?>fVpi228VpFZ^U!r6tt zJ9g+qooDJX|M%qJBlpvh&&s{(&QuDS%s(;p2BUOL((Ip?c7)DqaZhgimV|y^n@cTdcL#j5M?0cSP)E!Yi+a}u~oLM)cJV)0+>eH&aI<7e{ z9eh_*iW%5=1RL=<^KU?~Ye6FM$GaBEFbIWNzrpWuX&ewI`6l;mRE!z`z7OM3X zu7CdGUCm27=}%nccQ1bl+7w$S@8A}hZ6edN^k?mo-fw(24%pjk+PpR~3w~T!^w?{j z^PN}zkKC>_ADMY#X;9zCx1R$y&CXe9loq*kW>wRVbtl*M&)TnEYa`2_F=ww@sHuM% z1MkgsM{m{~wAf@V(z9%($LgC;>$fdo4O}f4f2vUPxm$@*+d;mAo6nrLtb3mFN+H{~ z#P(&tH#wOD@0r&;Z@*$+X|>UUFKO42uD_16S`Du7JQ3lY-FwjHl8^L$hU4d^wzS8* z41D0WjJ?yi(fg>(V}rIoIal)B*DYT1a>W|u^Hp}AoxlC8)^m_G^*JE%D<}7u>Sv>W zOX^OZk9-`Xct1jRkNqA?mDioef9;bJxO7gq^{QmH{>wA3?kT)BT2a3CN1wK&J5yUk z{mkW?ueVS0@||v#_3Znq>&{F2pP%CwvEuqr$aL(&U&l3D`LuGkX!E+soH*8Z`HD=3 zY{37*x9VArp*at2Jlk!>&uw19{<37Z*^%25${$pG%DQthUA~<)bfSQ5wvXhenG%0~ zO9^*xnUdT#%UCDYJ$LRQi6Hisj`o+A2yZ^V=u6FI+3-ozyLG4SnKNhk;$Lf+fByYm z^tR{v1)BwCHp^dDY20l1HCR)swom0N!`MGfK@$?^di=JIvRy$*6P4CKwlh4g8h(CU*bjs_=Ww+*^P2=gl74Und zu9$0F$>FIlp6)q1ZTjSbirPz!KHiPCmAq?j8t&7tes=j`>Dp-7P$Q104fCC4t{pyE zpTd9sMa5)K-^Y?Qi8Wid8ZVsBylm$YPsgA=Hi;jc=aqcakiC@6-EUCf;~B5yH)+n9 zyf4;!4xgP@@2GHdzVT;C!)@yp2Q6=~yU2OrOe@>W=QUORvn=)4d-D|9 zhFo^Om+0xfcRG{lMD9ZQyuI5O=d%~6=pB9{?%CfjA@sg*{nhDYTvvD!=4B}!@GZu)Uw~d9?ZUL zMzEjfoZIVfmCGKzmDRTRcmK1SrF$oRm3VHhUtGWx@3m3)_|^v-Z+_qSM&goLq;Tb~ z{&rI2J;sk6#-0B?_$S4= z@SK}jb?!)eNApMhhXT)XdH&4dyFR_+;V*k@pAwM^_XOIr8n<5aExY>ODDI^FbcV;C zk)q-@8p#QBx;E+_W|d2==+RC+w+#clx{*uIJ(v9j&thJ}Y^gxp+%M-IxALjQ9WLxhl;oPvd4H*XzBGa(^M>iGb+c5Gy zlixh4DphsAiOj3NoeuG=8MVj6^%qZC+i=bLXpDx(d;W&g$IFe~9(l^{(UiT-&2u!C z{a?NL_WpaC&#bgc{U3SEKdIUmxPZ<0eBkdLF`s7&Z-06GY;%#H->%O~e@y$Jl5@s2 z?C);2P4o9Wn;BcPh9lx`!HG+|Uf;Qnh_1RZ=$@FtuZ#BH<`Ssk^ zWfgzMlEn`c->6zY;52MmnP%{aD-%FH z=C_><{u`wc*FGy#P3$qR_|3>0R_Cs`9}-B8*d-ftZo=bRJ0>07*pPj+p?t#anH5(P zu5Z8WcCGEqGKsIX7I&{J^A*j#^4H1Lee3RZbNVu6#OO=3zvr@J zzANs(WjQH%lHQa;i~F~dBV?36?)c|iy7BuQo<(nVOJ=FPp6ADE9CPT%*7v(qv)Css znR;pR#C4i|onM>9tv9r4`^sn+s3r-7Rr7i6+FbDdYp3zW#UG2Gc5Xd*%iHg7%i-%A zW_(ZhYb6z~bjxDT;^7HWItCed?Qiz zMzY!MZ0fQXf32>Z`G2{f@$PJ{&INld116r_{^f1b$3xurXKsI)YiW5(`CIv$kCqyV zSBnGY)fb1)wGehceST{A8t<(NnyU}~Qn$ZWW1BVi*F2GzE8l(Jm_1j3U5#Ou_nhC{ zs~wEr9;;co*y%k(f4%cdvpo$G+mrriUKFa-f5!J&=xbH}0!!ifr!0Qrt@3|lFsDYZB!v+Am`t<mxh!IV%f|%BD)C$VBP~v3JH>^8Z$O zwe#2cyiMni&0P3)WuPtt-?iw2b??_EUVKvfDc$9ivZZ-e`@26J@2`4W9!~4X?!A2c z;o^rL*|oc?%O9tT;%D*nIsTURt7cAJ zk-k-sn}6Akl^=c=KZv%i%i2>Ya;`r_XshVqg@!*9IKJI2x5)VaS#eR;9^v`@$we-r z?q8W_>S1$WrI| z{e33E7k(suzUII8V&3h!r^7|h=HXzy-uL!H-r5lQd#i(8+5>($u32@XF#Mxb*yo=gW=)M)`H&-S(fyfLrzCa0 z1f{Xhjoxb(DD892Yb|4HVz7N*$B$nB^%Vi9_s{fB<&koHez!u-@7&%(nM3nFeA#qT zS4jBR%*y{fH#Bp+EyAkBt};DT>AB=6b0xJpgY(C{xN5)5FvX1(f0eWBI{jbfEq_(F z{@$c)=6xphCGngQI%>;iINH(&RPDx0JCn_+2q>+6fp((XO#zWDy_w)8!RZSpL>{p9`Z(bBi*zTON|;g2&P zU*J;sUBdDF*o|u&y5?sHL^1vU`EJ{vxNFsZen0-G&WV4w|JP=Ivt0K|Tl>&?wGmtOHvTY2bs@n-h)`uu(7f8YJ)l-V=w zYPly{*tv7Zw`V%^9@RHFe=`8n%zhWdyg%YElV9c0mp?Ur&Q3cW{&!c} zp^Mil7oF7me{<$~j<+&jZ7&D!Ydgy6Gd*%%a8$|cosX7$zESMgx6(KNNY{@e6I(v6 zeAKz?V$u7Jm5J()Cnr@bmfOfa|Ndj=O+F_dWGq#bd$O*Nd5e%?^Rdhek;bk?hTEn} z|K0Gf&ZqLt_U~6`Kb~-HLTs(v^L>k|ZI5P0y!qd`L#{*dqe?>IT=&gY2d4^&Szq*D zqHiwusCAohMbo{>^=?viE{4k-bsSn3u`;Xm91}>%$-v{IVrl6+fwcLgN-`x6Ry{D zuty#L%9B_q)1Vzz9V|Za{c|_}hf-mjXGJG*hF_^)!ur{m_r&C|bt*nbgk*PpD~{TK zXX4pe4<4PGm-9a1)y)^@{~Y)}bM~jkkC|p0+1*~mxK$SlxLZ3g#5C-4uQ54jihYMv_upc%#*gJ2LsSe-gb-Qb3%9<%V-<@g@3pwL zwMB4?(5s#=tbvxDk5?D&uU__>FZftNf31{iZ^;ghw`zZlFFURD4CXGCS+m?rbFqD~ z{q}70M}Zj|&)@i;m8(!EVwlXxvhIriS%&F()1$bnc+7c|cbt1Lr#8&OrqMiS>zptD zC!8wexyM*m#_Jw?o~f>jvZY~O_n262f9?^U^LOtdx#N@WPqdr*L!@?k zMNrkd+lC)%O`V=?)H*lu@so%}|C%i)zE8h1+1YrZuCMyh4+n0YFkIH!yF9@2(%(3) zu-Auv|88{l;V$2Dq+R0is~hDOPvv8aFQ$0eJ}OZy^zd<*=c@&5h&%(?|1 zXNe{>ypdUcfBmxeXA{@F6TWqy|4mfDsqahMCfhH6xy@00+54751s35_{hTtXTPrNC zpV7Hj5jIP;RPLXvltlF6vj6#s)lV{RWU=k# z5tm83Udwab^{;u&tJ#$`$@YB73AUxvWnXJ<(|P>S`ry5U`5R@uBPKHK+wNhp;UT-; z-Y^%5Ek<+nm-+=Yhs`h3d*)o#*SSANT(E6rnwM_toGDj@EfzgrE%@$ppw)qAY7LHs zOAGG3eQuw*=GEZehrYdT)_RE%Dtemh{w<7(1!p*K4*61}_iih{4^0+*;(Nz3cCVeiS|MNWE&ct=g z(`IoRTscrt!;>$Sb6&sn+u3>1pG97uRqAir*X*pCEx>$!kDlK7hBP~K-^lwp69VIv zpTB3Ek-2Q$TB-0yGirL%SL}VjZpr?xGWPq$8E=cH2~Dr^*tlX&eol>6wqxJJ8TI$- zuQjgW(N?c2*A+Q$yR?6SS?uL0rdnrhBJ)dQdK6E!h{>JiN-oq@FIMTf-901PIEw$Z zy;j}N-!pVn^DE@n-!Bg^R_I~A>wNKo&xv?}uX|T+ez8jZspW+Vef!%7OjoaY-C_Lp z*ZHr{l`Q2uRLxc^P^{he3-o@ZfPmm*>JBW8K+yyua*d9SKGBqF}6 z=pA}EM}=q2Mv3hSD%Xy*-#TAuY9J{ub$>_2+8Q?|vwnX=xvQ&#m`}!dmdjkPDtUay z%Ky`yb${QqcpCJ+{gze!=t9kL(^L1h8qMy0X}zM@Z`%1P^9PC-v&H4EG4!h#*nf7J zvBNN^$0pPNpm+1}pL=p*x@7w2Uv|muu<4Sxly13ncGf$-ibJnTX7gX$=<$Be<%Y)z z2EpuYpXT~DoL?U_@u_#Y%GxaqYfioOeEd3e+g|N7g9pB;d(Rx0`b9L0wO_T1d({q2LnP4B~2UN%!CZrz);Ze?0^r?7VF z^v_+}%a3*#3r^oLX-~qX+G$QToc7Mk72p3lGu5f%NZ!tq(K$_(#thH@u6V6d`@F>M ze0hNQ{(k%K-R|AzR#=>R8E)X&UUhx$v*SCbR7^@1oPWvYtwcp#5OHUFNX9wJ_z}mJciRyX-$M zzf;V&@cqPX>aHw0ReHWprah5;sA;$0f``)c_P`JkyNJ_D^8*gq?@vC}efaO^b;kZi z`@S%;C2X~DIX0ns;;J)eG;20qmV3y<{Hr{OdF97t`_*e*Ry1~nCH0oxmfainz~%7F zGP$Mco0^Xq+nX={l(p#`bHgLAM?RKuTR*C%*ccd>>^t>c!=qO80sp)WUk)Cs(%_kEVWZV7uCs1;P&i|M;>3uK zjge>mG#x+sb7c$PB(svngLU&HpND)XO4K=ddSy(~Wq+5yzo$e53-)<-&Fo)seA{Ei z@K5j3RHiY%`PFZK`$+ocgOlI4Tj zb*Goj6rEFAaOW{^gXJc* zy!6sN_s$2|&y#q5v!VGCW4P$9h@-rM;i_rX%d8(v>^N5v^Q$R~ZP{`+2?^5=Y% z>*E|}_)NK;>-lflRNv?43#S|`NLpA^J8N6~>Ar2Zo!3v@IpwqJdA*q1A|-Nj-!9&q zm*31Co}^pM@N~stx3^|0`$DXhjNY$UwW(`%tpfL)IB$ns!MVrp8QblRoL77Ca;o&E<4dpG{Nj|p`6=(x zUWvDom973&7N_RVE!R3|c=`+Dxt9gjb-l$8mv*f75!XLwek3$5(J^D)(KVme?pgEL z!`)K5Wxe_a5nI;kGA8C^m$fVs5ogj|Hr~{WSk+QIDK@UqKRB@NNJgEEwExYl>%a94 zL!VVH5}ebvX6x)xolcad{|WWtI6uj*D_Dfv3nBAEG{-}|-~ zFYB{>uSTmbzrz37*-}!y^~NH(X+ES179CG4L!@%sE52DWDtk9lv>;S4@$l&W3&tTXg` z$!^`lNAyK!oH8!-VoqcGc_;K=jnS7q0>AC%Etu*Q+*sI_6A->CVY_RPbMGPkyVJM- z`pd|rBRXI5{5i2Tkry_`Ts_$)Wb-oC?|a6-FN%L3%zINhU)SxCPnxe@OycYhQ_gNk zSg~LG`vQwAEt&oWGfF0yUTUk*oSF6N&|SHt2^E*WtXuht@!G|%bKKTf(jQ&No zo@f${Sh>CPy`iSah1Rf!e=im&D`)7T%?;Z@? zar{Q<)DH%I?(W)&O$PICH_S+DeHD?h*(`O=#Z7*J+XXK_{FC-}uV{eW3z^JgQ<*q- zv%fUkb)iis<($>i9qZe~6u8AUUTQq6^WgOCMT_6?`hU86XV2!}R@+T3pL5uD$$F{6 zJk{RG>!!Y_Tq83-eEy!ZZb#$|dv^tHa|)Kv7u%{jd*kJm8-?|^u8mp1`X%aMb(sHm z#`%*^)$&zM%dtIQe(m_Y>hR6mV`RP*%~`_dcqZh2(XtE6CG4)e{1-HK_pKQB1LwfsT z&gh-0-G*0Ey0&IU?VMfTI<;8e`}BeJ2jh5`dCudXeKULR$JLo9{lp*tdM8?a=F-V2 z(|=^`tl$s0p;$VlSR#Ex=@k3>`Hw9At$Fl6kwS`-Q8?_MuwtGfw-w{ZY5+PJ8#8xm-c+FZXiY z+PzCOUf|cP+CSbrb#K?_i9S7VydwOLk-H;%fn!_wlJ>~eQ=h0$JjPqXW%c2K*|M#b zUjr?hYwT@`R>@r1wRxGYYCzu+#VBh=Yo~W5UrPM<%$#U0d+z3~`BhH^B;F+3eNmrt z|NWjPQm4O8u{cwE_N98!*{3lR*2mwNHPu%pB---0ckSzN-hXyJsoFF8*H@mtdOPCB zhO#Bxw~e#DZ3xnPFmFwG&3%tLgI!iqx)-jfK9;*`rLFRE^4Z$oEDO_4Jv?YC^>S7E z0@updRceMU`@FYxn_76R=Lrg*Isb&D;j7T{5}u4zUs=Z^>{D-%J}zDzE{`O_%nybsr)a!%tZP#2m9#nJRBbV>RsV`ra#A)og za@51-;>^TnJTD&15S{KcF>I3CX^|JgUUOS2<{Yni-jfnn-Lww~SZUeReYiKV?fB0# z*Eb6>uPc<~i`l>FJInU#I^5beZ>Q~0xZb#t;qaxe6;dag)T6E$9S?Zj$y#tLQo2l1 za|_GK_Kj|zSDD}aOnnxnrP{y3Y5G9D7uNYF_VIdathYXKTM{#iAxv z&{HVMwm&^%%G#~Dn?3i4zTC*4xw!41|L5u}v;MO$?s%)Y<5>w`OR$mHr>ENMm}}h+ zPTP8I(`83j+m@-DS zUs`*8@8op{Jmels{W9avdh-nZZnmp^XQu92UNmn?d%}C3=gO-$9dSv??3@|mU>iL- zPf~kh=v>Wh^A6S?_u3V7W>faO=d$IyFTI>!W!A4&8~jOicH+@z>}uw+559BG=&0hc z?91A7-*mI&H@Q`@yIYUN`uFZ%$6eSL&Gc%)sZ*kEYmV&TIDYTuWrOm)OH!wIzw!CL zG|XxCt<3G~3v53>SBstc^(}L1)U-3Kg4(J%s(xyp9j`Rj__pr9bhD&-NBgn2Ct^;% zy&`fmD&8lR?aq&>=Y?NqUpp9)EwfBHWB%;FpKIBVyIe`W*|zoH%B=^j-A_em-nQ6o zWxXx4{NA_Bt4E_Wzs|Sl%6YXsH9p(QKB>2q&-m{t{|PU5THQ5t-y8ld-1S_#=YyKO zDUI*17k;#x)H8LH!0j3bx0@e+U)uHW^V|j3Za#g?DRW3!Cp6r2(x$6hOH1dtWV^{O z=|BGI(xMB$0^?sk`Bm&usBQW<(D(XGxA~s)e=z_uUbFFmF>*( z3wv)T_lesyHdM9K;lJ%9^QHGsZMYEdsF^9uNbkh2Ul-0k@;a1$V}bR?mb+IRZFjs{ z`PukziEP@H!p^DJqBN6#{e1Sg`D#P!IisA(nV&9P%3FNJ@xk#V`ToqM>sCAcGumA* zS9Lk)tC7mPqtBC#J^!^^xLc*jxSpBv^MPdltToxH{wt>~G0MLDDaSbd)aLD9Pdcq~ zPi3*@PpKA?pYq9fK7aijyYp?upSRq4_B3o`)8DfN2J?=5h`O&5t6n>$PUq3uBNt0U z=UV6g^Rd~=tL=8fAV?$OnV02~)0<)sc|B>GHi3KBr`al{vMnE&XHHFB|AG5#N$B^_ zDqL&MTxtk&lS;{c6ydg6d%Momsfy-H+$L-YIp%sZ`?tKwA1?%CwB8iroc!?IwUu%A z%68rQV83nYOJ$D3OMANB5K9_jUK2=L;|KvpRamSM!R%>s5a&1*d)u^MCiB(}?B&l}ElmBC9oy zUs5f!J#Bq)%F!3~4t7Q5>udOHdrKxBaNF;^VG+;o+twwqsW%EfuHJpuamI=#1w7HI zub)`%vI#gATI;@2+`>J*|Lebax9F*lvs<*e)~S0feZJb|z4vOaKV1i+R;m`9-^4bN zb6)20@}$ClvZn&|rc}s^Dy&h7-NYy9{&HIGliH#}NB;LO!eai^e*H12@Jfo`v?#AB z7v}E}`Fdq9+f*~B{Zmqp&*Hqku4TKFq($?p9rK?k3o!*1=IwrVUYLJM>14Y{{T!)UzR_x8pBT56u6gtQ*X^7LxtGrzv-_(Xn0T~PWxZs+MnBC^-pt8KeBIl$K>J-qSls%~4JY|! zf{c$cBstkmZM^xH)&}mnV%1=&vtz;6dFMKJvG05;_V~l2Mc!csH&&E& z|GAiKYn!}=XL66hWcEw>cAqDydChFGTabFW&yii@X`yT1(p54xevx{GhJ3G2{8W+M zl=tiBpTcL|&ua8uUOhSC`<0ZqBcUH>roT1b=bTV;ZKHAN+QVko?})tk=vA5gcE0h1 z`R#^*`sel(wQhd)Z2h@}$Ct_#-S@xeej$G5&6Rle#JQ_^4_^LrC@G@8{Pg6F=lI^u z6w^;ujht6+RVcG%>J~1)y;C-y=U+ zDy`@)meVFGXH?!yu8=?OBFpFTOU=jltH#DjZ&EKZq&;8vdBwW_UvekR^}lqO{r9_C z-rI(+X5K5CsTX~}o8|MC<*kd?t3T5U$(q%l`Rv)Q!YOxB6Urra+)v*9sdCFUgCm#b z9r(}mz<8_UhJW_+C;guwazo>_f!u~5VdYT0y2F9>i+JWuZ8o`HKVRQhef$#Tz%k5`6+j*=K0jW?YyuutJJWSm0!hn-b5zd?_XX>s`5Rv zOibC6bLy4&s>^o2ch)eaeE7M;KJvNEgH>C1N2XfxStW?S-sco7EPhp@^G8QjO7xAH z8%^b=&h`plX`Oy5+&T_vF^ni^dDmKUz+ZTotXKZMfO}O0&Dq+*i{oS1hY8)B34xr1h{w zddBvJ`Wn|8cJ*zN6O7<5*&Vpy%c9@)Y}F+}IbUA!E_IdivQnAjQr8}){d!-`maOYdX8n z^cr)>s-8{Im7Z(1C*5torhJ=2yoF@_^tv^*5 z_$gL(j*IM~a9Q$Tq*#vpeukuI0)tGPZUdyEx+mwQT3^Jlnn| zGDUIc`?lMDY35vas$?rve!TkNI-9vRtYE(V0=}DZf&6K9*F(+SkG%_ickx{9MA;ba zmVFBE(ju9grrNhuw{Pa#DSG&R@ZH^t$DeAfw1ZmqR-h|II6w{h#CV zeyHtzh_nY|G*QU?U{`y4rdgiwae+qS1tG_5&9>&{i9rf>1VybLg5r5Q`-k0Ys zWL_%QOs)+#eSZ1!;sf>;_UXI6%qj1EbIZW;OPuW{%{5=nZCY*nxt#lPovHQL@MDVp zETt!QS{}Oo{I5Wrgh%MvtS^OdNQQf=O zUbnfzP3yh{UHG$4{H*5k!j12i%P)?|Kk3}~H{QagZrb+=FPu#SpT~<$dYpDLu=~S4 ziEmd+QqM_jX%l^v_s41}bCKiI=LYqvKR4z@Z9FJ?e)7i9*6KO@uN+mMr&KQ5<8FSc zy8l?2^E*i+^;Zx6wjR6gGgExV&kZa6HwoJZ#l1b>cV+Qri{EAXYk!{3KX-TP^f@(Q z=Cx<@O!oiQ^!)L9RekPjItYX7-@;fp=@=KXD7xP9TV??zraFPOc~KG~i4 zX_vy^bI(}4&X$zVvU)MgCNVN-*R@@;u2JGwKSsZOJWp!M6Vrg|^10`Ob-cYUnElyh zzAo=_Zr7U=0r%}nvMkOS*EQDU#1)C3|68s9|NWN2(!8CVwO3!hWZCaED}CqD{iY$J z7Ey-+ORxU3EqeI=%CURvZNqF;Y*#RcZ_2y9$gn5w1u@c-&>yd&$izO))p@M z8T0l`__FG#1*MnfM%#&1h*rHi{NWvM>etu*u6y`T>MKpdyyY(!C#P6lw~bUT*4ce1`^Bu6 zpO+V(_l;B4kgf9&`njF^orR117mqpbXU++owmxv@e)s2p`^wf$mT8vYHL!J)uikt| zRx?27GgC=E^TPV)%_7oaZ}r~0ivCII{LlF|>qucp)grrJOYcoQeErq6@6XPJ&df-9 z&~*C4*0mQ;ndXZ2FG}CtxBb2Oi2{osea!XqC%?0udAZ7{!!K&vy7{}q@8oxXKmFW< zn_pe+|B9FmPV=tMHIj6G^vdc~Fo$E$o^N}n?0N5~n4NoF@?gx{^HcuGF||x>SRA(Z zXWpY#XP6H@yZJ(~y8KVd*AM;M`wlO+z0u#7o;d$^jKPY2QK`{y;tOUi(9k) z-x>R2cW*A#)A(8|dg1%*|6z6-zc<`mVd1^6&VPgc@2x&J_X|ARJk^J>ywxgrmCanq z9G2(%o(SCe{@6c6tEcSr#wmpkPnxP8sU1p^&ikvX9Q7W|SNF3{nLU+B_CExld_vycfY~%Lliu0#8 z`lpv={a-47NyusVQ_D#ftCZFjOe=e(@#K*c``F~jB;v>>;KRe|a z$NrH!SHiO7`Q1NRXT5X&7({Gfi}-hGu5;b}#`_h0^NJQ#F|DmD6Pr+avF7+~zvIVj zj~efPIIH!|>bvXCvV2po%anNX|Kgk+{nu8%Q?GPJ|52Ayu@88qa_+$~V~?Mw-KI@% znsF*6HgJvllNzCEv%W7rX;q=SKRu*IyRCM~%%?3|XB$U8RDCt??Y+MIy~)b;=eb*^ zzPNtsx^11>PcxaX*B(q?^XfXQ$e~NSrY09wRc!lPFD2ps;GgVupMQ6moF4pnT4C1q zx#Gj`%1~#KSAh@j%5O3J9Cgiv(Qxu>qvsO;6~jnC&}e|rR(1&fBe=bH5baGkjo^ zxon5d=FgX3{!hH$KaV-B=)vc%YLR_ih4<259j=hk*E{;`4ATMTwMB=%Z=AAW()?vi z*QeBNUsx97yFm5#v!B_wF0Qb-^eWBug-`mHV@vmbtE=<8^m9|js}>ohOSgrW zm%leOetXbPym?*v#RDHBe$|>ieUfMMbaUVemV2>RU$3!$C${+g5vKe0*E2MHSbKQf zX4~nk-PfoWcjv6=>y64<2R{8jIEjzbcr9;D#No1Lo9@zElKz776S=cK+okE(uYcd1 zm3QvY4<@nIOiLzrP1akZ`DmrRt>oV8GEUpf<~R5xZJ3v|DgTD04~N-&!M3Tz-1p!9 z{usWcGRNNF{lN`8&n!Nbpd4~#{oW^gk6hW`Fu6^l`LUs8*quwN50-9?w(w3*Jifd& z{pn_=k`&v2ZadP}Gnr-Bd!N;uo_VBo)4s{o+>%>)l8Bqb;t6Cw(7#9mp=;vf~V+pmOaCx1ROu@28xZ!mYs06321qOnt?q zVqUe>opu{D=Ss@I+Za4S{>axLrpr~L>qBMFPN{mCavq;=MwJMd$c7ug;pLdiblL$YkgLQW^&5tcXjOvLI zTw?hzOBU>S5G19Q+;92%Z2F+h8Z7JHycPQ|Px3=B$ zeDUkGdv<6aZsIF^EcSlsY`@-L)r&-Y3vPIM6v-{Sx*}$E5Zl7(QglgpI@vqlq_aVTs`;v zhT~i7O5S#Tozz|Ad!KXiRgV{YKSsRqXpsJB`%dxuaUv8+0e73#I;#603T-W)IJcj=wcP>u+&S}NLakaePr+i9G z=-TCJH=Z_CeSUU^eXl^cLHF4WF${AH%`0WgpH*kch(5=V5-wtn>ZI^UMdyVAv%Km*P9!!|{vo1*g=Kb{Nf8M@66~Fg#oZ;zp{a#^n zzN~$*dy{3e{rL^wwB^(vYurCy8nn*+Ag5$=M{vd7Rh!Rbd+#Yddt=A^`K6j?O=UcI z4W+*Mu&-sRQA-Q!xpro5pYg8nnhRMD%Qi;6J*35dTDkV#^%YfYE2k%|6#hSR-mdGF znZfpdmxBy{sBz0^-Q-urXSbA=TJHZV_peNree$e5Yvg)n&R8R{cILfC4~#*?e)g?JNG)-Jbe~U$y_YlRMCY4Ru6uavfA{Q&yX;F2AC~pUQsyY>5-=eP!)!Z(=T9e|q?mX!X)1HIZMr?KWf` zTzsnGkB!o^i2X+Yyp4pJf2sGKzP{lEdq}$Jv)?OgBTi2{FP0hca@yYgEJr0KfBzZ$ zWZq8uM(_VCf6Qy0oUnpd>7@%Sv)c48I_&GyLh~ilXU*AXcj0e?wcVPA z#YM0GY?-r?*OuwrDR(xrLy=#F)FTUTcuX&8UwiJEEZZBCA2}(OCizE|*^FJhFY;8L z^?E$-->0%qe?5#(@-GpY=;-sdCieBry~fLaH#|tV-x__oomIwF&cmjkE1+=Q;U_I; z+EXPZ)~=iN_G(#OVn*W5t#5e_vEPU~xn*{`^{w|gMc?KfKfNzG^6;aWuSx~>8^X>h z=+`D~dwN>PFNiU1vsm9Ejl;*U+26ckQ*vo@?tTBHf}>9)muNdQ-K`0qm{jxP=Z22O zCzwx`RWkOds>yG8mX|-_@&AqI1?Bgga}1foC~(n)$ID3vVm4pWIg?)SkNxOG_Nd)|NEfjZ4mIDdfe>Uwv0Qr)4rv@X^TG=ie=p-dLTn&~1}xtzf&| zMVC7)bDwTH81GjuygKIhhEM;h9YY*4rs`gdO|2-OnXWqLdPevEI|q)LGtT&*wdQ9? zV4<3tyeRjM@ONjlPjl|?&s=P?*7iu$?o0QRX8(1Vckrio z!Og zTjtD9`@Jju@*CCt;+2*&wsE?P!w5N{Km1YRi~P-fSv5_uohMN7KSYJMG;?=dbub?=KIl zy8BDrVm%+z@0?qilKw9)@IN^xe_nxaYwP_@4r4_ zf6`#SqjySuz>ls^JEmsa?Y<{mdBxiLv-9cmYBerZFAl#eJi74hSttFl0=u=nuOCQ1 z(mEcr&$HHd>cn;VmuDB}%-cIn_)}AntcQ2*yqn+Bw@)pfY%2fPT8``RD(0WYLD@3d zeknFb;*9IA9bEMDMft?!zj+S=19*;3z2f*z@41+^@|k5KuWozKUwmWPyx3D!Z?E3Y z%ei9v_vERl=jWdm{XMQb^*E2dwfnl`Yxfy(h{x`ne*D3iM>77N%lKZeync{%=Z}SR zrflA){eFSvq<_Y%d-WgsA6xWZBW`Nmaw|>!t}l`7IyV2+TsG+W*mOy4u9=c~_TZXY z1N%STZ~k6Cdum=+p+zOzvE4RVu2YKb^4{K=clP3}m;kBs@#^PhR#bC;UG`Hz(k!oQ z!E{@#%W~&R6#5gNT3jo#jXtxAwH#2->kbu+&-S6q!^fB*e*nJ2qg_;KmyCEH@pSNxdJ_39S? zQIArC_D8O9_y70L>i?{ocwzsvExWu6b?lU{7V6}GEO31M@ZzEB47c|?SBi(%_nwtZ;{)dKLe_Nf@c{h7wLzURH_y_jqj{2&dc-%QzH^$<1<;m>^ru-HMrbfKC zs8F4xo%yiWZpphK8EsXMfCMwnRfRV%N*0$zNx-F?-P1w`u)`TmwB_{o|Ej7M_1=1_ebx| zdXUbVp7HA7)GLi{Wx0v_4$JKC4e!<5F=y9Q?nW0mjq4xd?(S>*f3x_7`1HrcU7L68 zd6&~z{jKM3$x#n}*SE_(b@iFw?p>hdFV^>V|GQPJ>RdcJlS>b zcmD8%tYMEoHO(+%zrTznyYu8{cIS+@ZR$V#XW#W1#kDezC#_}wQWAML<+@bN)(3Yp zC##ig-zZ_MV{_$c<(BzJ1E)MbWzeraEv`(AS$@gCCx%w)Pv>rbv}DthBlkkm|FUz; z%Xs{L`~L8w-*`ld^L3s-yLax7_S@FS$6a2({ABYfap4XHWA{(#o!ni|3q7su&#R_y zo-^;JpPc6L4NqR)x!$U6^5o%}{|UYq>i*O}Pux9&EqRyoaS5@y|2y2X-}TNeN%_A! zOsV|e|Cs92_Rh9e=jSbaP-*mDxGOs1x0#l~(v)6{hLXO^W`9zVWO z`Ki==o_F`8C4YPqSF5_865Ss4<5HTd$(b*CcE2A5UKe{7{@?A=1Dj}}b9vYFuO(M# zzFPbIU-pBQ*K?owPUM=W{@G5_edT@5_>B!64D0{Jt-k;E>(!;n0^cr+OIK7WZgt?> zIIrWCweme@<^C|{b61{b*zK%}`tYAOEYtq*o(avy=5JC>KI#7aJabQ4UBB1W-79y$ zeeZvc!+F*9Rc9n$MoRL;|C(JJ(!Y9r;j3w9jo)j`JhIj_!HYNF_^0gIf5jVKzT1D0ul+0U-L^%Wzj?~^MX#RO zYa|wU*!|McW0F97oIx6VgFF+;Sv#J9U0T){F?oV zOZWJldew5n+sZ{`qV(L~>zCO^)=Ye<_|NG^$&cF}Vb9#lZ(q(n_h6U*j8bER%o%IX zNk-X8~RJ}`2CbQQ;G$&zh3vex=s80 z&ba-1;#zv*cTStLA>j4Qq8}6Yt@|nBs(4<%ET;C?2b(Ds*9z3^=kD=brnDzs|M&_g zoz>e`-Cd#m`+jV6p3ObS^}jy+dHq#RXU&cG-(qr7Yj02gx!p$G`XwWm?1F5kh0W=$ zMM+AZ%+Gy|nRrx6P>;!P($h;iIa{{WACs`2HmUE}{~Ii~Ef=bEGT)k-Un?0WZKP@` zv^?me&c~H&SPKIu5r#3YRq<-{U1J)~ois zbN<`J)3S9XXRKdXCz!pmi<@hZV)MVU%pzq-+i`{ol>+c?!2M(1Of-`_8| zHbZaqjNrN9Pp|HYx#pnFZG82;<-<7B>6>5OXftSa+7tU?W=m_9eAr&LRnO{H1Yhfq z30U5*#vSoJ@sUa5t{IN%>-Xwjf4D}-=KqsfMirBue(Qa=`RL{q{}(jxOsq2f{CD1_ zrIXi9NUpiw^PKPeesz{jYF~P9&Q1@safp|dVVquMSk;<6b@fNrzxkWJBI<3W-RD*p z?^ttqyH$3IFHr;om7===|>XtfM>sXL(&} zoO8kE@YSu~W9*Ly?*4Sj{os-IU02NZ9;*mCG+`C<(qnU<3fIoO)%%?9eEq)zHP_?A zs$Si&zj#l?TgN`6^seM58>dhg*C(|tt3LJHx?fT(bOM`oIPkVo%$o$uDQ(I!(d986 z`Ku1jbSl-q?eBAO+Rjs3_)k~ZoLh9a`k3O<3)%k)zpaW$`egB>O6hnpt3}p?9rI7} zT8dA(=Bg`O(JLkAyzkpQ^Eq2LIX<>7*~GM9{mkbpGxBa8y#K}0wbHffYjFCEbmKP# zotJv=2^aiW!!=uP;_9k1^Ui0!(OdW6n510R1Ep(IALSXn)2h_J$=NHvjCp3ji4EpQ zg(e?Y)KfY>xlp7yK>XMGO?;BdPwP~D-0U=7yVUNDo4>Tc)YE)p;T=)K{H%p+=a$Ea zJKfo{pG{{~ZOn>!vrFdR*eZRw?n9nr>Y2yfm;3Ji*ZaC*o7Uf{D(3Veg;;`v5_+8KY6OiOm)38;Zezx{ge87 zZqD4QqBGS(anm`+Fl9?c`Ijdzy76<>c-@+?S-ZD#WnDREz~_x;I`96GKEJ=rd(*kY zf!$a6{)bqXxtSfRoY%0JOVC{9{)b&-=z|Cb)hNK`(`^8AO? z2OCD?hvhTt9<_b4(v1H-*C-)&$NcE$Q!}CtPWW(x$2c*^R8~B|uJ2x8*|y~u4(vD@ ze`xWAB;)H9d!me=U$NJzoE;dS{#!jlcUOOT`O(E}g5H0xXT@neIZ_QabL|$V3IofXRo0elOSdtb=lJl`v3RcV6NhK!zm4gN64=yxah=ck z#?2eIyOrje&tdp!9>DQ+&bI67v5_&J$sllu+u+3A*ttiq}MLb z{>o*08rl;6#K-5~d32ch!iBlhlfvWW_Zt?f+6tB~Xcc3Rdi+rO&1LaBHsL?rXT18T z`)N+^?sK{9d&4gsE$Nt)+|{}CQ&ry4Cl{)gN<5Z{mZ_I%wUBC_ZD4A($oAWcRokkc zCjI+3J74-ok!F^3y;=LZzbk%uf8M?5v+{BEbtOx=Vq8N19dN$j_aag*CwsIB>g_rbH3cP$cIuBDnio5lgs4$Y*!^+d7i(r zEcf{9)QR$z+I#k7?)i{o1RI3x#B%b}AV!LSFtFNl}jdQtn zD%32>IoS8%j*a5G^AQY%0;MNjp80Pu_oGN*;NA60lz)d`3$60Fe~_c^X{6Zxo0om& z#YdU!D>yM-rgw7KyL*$0mK#5N7C-BEX5Wz$EIWgqM|EhMPFwQdB3`J^{=o6fb)mOc z?%g?~WNmG`>GQDd-NF0T+-x`$G-rZj_2U|U=bVm0A6I$NzY#O}oAT0D*YNJ>J6g*1 zN#oYvKYMmD9GzCTrF@(9UGMBZm+W;e!r@sup8pN^U9r&N+E~17u6u2AO!3Y)FQlK| zkoYSxhdavfC~xAvp5?#v1LpXD%4VG}o?_LYy6=kYi&Nhu_kSqcZoc^T;oaKbwTtIH z`KYz^hUMkh^7;dbjnnIT?#x+vgO|_p^@AG!D0b0HjFBofrqxOM%%#Qm+?@kI)%Sk+ z>iyUK{m&Owl0SlS?umbp+F_HT0Kl>414-7~o3 zmOqo#>@)e4`lf|ZTKCOWjXdwXy{dQn*RQONuxvl)c4_JEg?U#Fmql8h^UvS-Sj%Lcd zzX$(bG3&0%NzLcrUZ7_?H|zW9#mwm}{f!YGG86AMUwS-I@a*%C7Bl%5<*hp|GT&O| zVtPQ#&HVe)ALnv!`KG_dbbiLA#=fuqx(9+I#Y*G~mwjLTwmnLqa(>V9T_11dPrO=~ zAbNebf4q=b(3HOT`D&T(-6#B9utd6E=fAkChsCmI@m+}<8#lA1)S@ZF<6Nak6Jl(tcXKHDsS10^@>-%54y;XWf+@G91bG2(9&DPt+&D-|B zB1Zf82BTxIO05pNslI=ltI+rIz}{nDb*v>S{>*y+@bA28tF?Y#a=#cV-c#Iu+57pw zptCP8E!#FVvVTqafuxH|OjjS3{~_c!ond?K{`Wio#BWJ;KKxu@PwS4LV-Mz>H2kAk znG!91cJ(H?RnCuAe6!K<*w%dfarf)(A3wElFrS^ajOod0E<5et`pE?;+Ldz?A5IXN z|Jd-f-Z^H?_3BdVzE|wqqkOK!zx06N`gQldXUD&N_^u~8Hh0gKGtnN8Pf9Fn^i$m> z&2v(J>WkAIidVAbBVr59%AVNiSBm7@UYxac!}VQUvB$jbvCW&ZIeFu^#pwr3{jZj0 zR!p^>r<@`CCif>(M_8yLxB845La$p}Zt<_zT$+#EBBg)KI#MewkR5--{Yc1-x$E68@6bCtwQu_IG}9POk&;KH zzmoQRTHD*tb<2P1DX*0l$Jh=OY-@k*JS{%x^P10VD(W`at$hCB!wiFp+NBo3bJm_; zo$T==rv1)5Yj>I21{IBlrCc(uejRUJuRX|}bUaDU_n7&XLZ8XE6B$GATW%FhdnEZ} z&3 zC+quL^FM0|8Wi`m$g$anpO~=j==AsV6TY1=T_C|c>He+Ci!yC&RwX*`dvczdKdU-_ zY^v4#_uO;c(q12$~i9%uK96l&%f4dpU)~v#;h^dOD(>b&SGqM-F@rN`HQB9 zl*Sx4^{qX8`PYSZ*BUyJZ*D-!PY4da562?;Y zD>LRA7p@PBIMVV&d>gym+~d<;?>H3nMRnH>K9Q~M!A9@aurG=`{?_)SCFi~c*Ka@S z&-~W=_x)YQ)#oMnl2)u*tK|0O#21B+D{i%U|BPZ&d;57-^wXLrNBH9{m)Aea|2bve z)Ah|u|Lk(e;=khf_E=5p@s!=|v88);XBA5JEsFOpRJs|zbX|Upz#*<`Nv3d-Bk4#DoKfH0v`Ru%@pC>l|uPm-O7#~--OrLM% z+a-s;rLSZ3WiQ^>!Z+vSy5!@*=Sn>1$K2Vw$M5c}qv`j&c4!lf}*I_DB2 zGx+MeJY*(?{UPclfPH| z`*v+Qr?Fu2%_w90?aGICTI_GL>X<0f>@2HsrRmu3;%PhCcD6=canBI0dTF_A{=Jf7 zjcH5gPAy4Yb?VORRJp0^cSOtB@$dF~`rq*U$@n$m|F>woD%kpU*7J$7+|O&yD7n_$gI?z1r7i^9%d^eK!|h7c-IE|8DX5>y?G^Wz{qOE`Gmn$Vo<|UBQ<}w(&H66tAf`CuHJJdxvuTPw#d*Vr7zA^O!|{x|IpeZf>%!UOw}^2pWbEVd%jtW6`P7+T{iW*rz7(u55&N`gl~QSWK>0Fu zPWKht3}4LDGT!q#&2+Z>v9)K|PhD5}uX6v&J+-yw8>Qo?ORfJC`A>QO)4QC^{GEXt zwO3#NX_Xd}c}{k+OXh{MQr|rE&b=}{_CRCV$^(H9YG0%u`O1^O=#I%t2D+&sKwP5w30QiXMk|Il&$e7DUH`B9ji4(v8yd?q-=|fcoO@rG zr>1vX+~Jk1mEpf-zem4Y&&0lI_N)n&?nh=DoN~VPaO1a#FP&L)9z{O!TKD%v)3V3Y z@BLX)ne~qS-=Q-p;h<`1a~sk$WD z0=v(iU+lhU&hme=(%|@Q#qZHCFIZfDct(Q1b8*R;nj3~0r`lH)%y|@fXzo^dIs5d| z(AcJQ<@1wk+r#F|iM#$wPg0A~HaxkdJ8}j4d&?(f7q+|o@jZU%+>%A5-%1KLnVf%F zX1?2Q&6Y(X5B;P97AJJqeN%|7wBld7Xw|kn|9tj&p|{IaCzVg^SFM|N{Pn*d`j@J| z{qpD1oBEGsDT96xep-ICdj8;_oBfBJpx z5`ORbvnS*z-3esgB$h6$-?T_4{!_u589PMx$d+Y=PStuItoSeWTS2y`Ij2OWPu^l% zk=np#E}VxCO}E%?btb*&+q#qbUFsA2Z}z=EGn4E1gIoQg1(8z8SCx-BYb^Rx` z%3OPn{7@@!ocTR)c4La|lJlRo3TEjiu`TT15qtf%^)Bg~g@x4@UbZebtK4Uhv^Fj5 z(%!G>5szYP;e*SD8O;+mAh7GyTO6{R?$Zj(*#F#{9-9-?#n3Y^kx= zw&^5?Ji1afFYNa2HI~oK9zBSu$vyriM(NuQkJ=wGubxYY$IY74y1qZka>t}B?G5U| z?0G>`9-1HMR_l(a;k4fLv+PmevE@_lKi|W3H>ElxboQg!06@WAc9N-RoQUFE2cIM~!+Eg<)@t536`(;e5#_L$(Oai-4 zOn>lIufW6nmWe{2%SS``x&1fiPxz-&=K9x7yI*39`TJ0@9aBCpJ=o00!@rTk*>`S| zmB-^BjuW5Fz4|#%Rp#jK%%!`|)EzprZLdnD)#0>^`u#hUn$uDrR@Ibk&(gV6J7u!) zR_UUp2fCT!i)=eAtcFl|P4E)Jue3SN0vJp-8?v`(=bM8I9b&j6< zW5(%4`<7TtEmVDAsBN*?EKVHjSX#k1&F>3jCC%2dna8+I|rHg3*3 zeD3uP<)S5(($h*C7Cm7NUv9tn<*CIt!nEe3|JYi!*YHv$=hu$5#m(10t}^GnWU)!@ z$@Bj&)UM0Ez3A6B>$}k8Y0q-*%zxuIuSiU0%Z}+Dt9M+J()_tW!u`!2w>XU>8@9Zc z%vdHwuPXkqv*I5Sz1O(jL{K+5_r0<`z!Kb@l8PZ0hoDJ~ z&rh;kx5+mDkt;7d@;IU=zqRnpXKsrrVkwLF+)8+H>QZvj(mPGpMg6?~9WMwvFt{-*!M#U6f7=3NiGF0~u=HIy0_a%@dr z=l`!#%`T{=_j`wUra52Vl&$j51J6yBnY@8x@`m<^Fv}GZuNiGc<$BLS-3{8HCE!rLBV6mHmg=yxbY*-pxM~yZ@BHnTi-Nv@-|$rNQ^ghSJN%ER}qc>G$l4gKB?x6 z#Gce6CbOEjw)o?`q5R_1yf=wi#s&Zy1Ku{#$h=X~9~?%O9F-lhMX^25fY`=MUiPK(I@J71hDXyKa_spuDGDYNFs{V*YBA0S>vIw+4I14|2g(2Uzn~}sN-C;r8u#? zSXZQQ%8$8P-;PBuOm;4^YcuPZI%$V$={xnpl{~jX4Hb{B+TxqYcs}1sCZH>IB6r~F z!uY4Z_~&0t*xsl9?jDnO`o^Qjt9tai=Dn@hTWThMe&VIi1$GA~AJacMdFn4s*24mY zcM9|mPct|?TavAE(_ihr+>(11?M1Syc82x;pZR^o%C5=hrmmYl|Ma)&of*#GR`~B% z^5JBW7yKyRr7p+IVYo)(^r6oI7m5zq>AtYPdobZ(-kFaT=FcuJO1!>&;|43y4+4cj z4CB~eBS+><(%K0I$U4YUDxGte&G2eq*pOyd5p}b zm74{d3)K?#X>a>EU+%rK&TA``IVM{-e%q?c?O*G8<9gNB)pfC=$M@|^imkrBDfZ2$ zBkLpVkMTK`-kPZ&lX<=N9almyx24!e72UOKE$*CIwZrF9vd>~pL!H9KJ&rb7#afq} z!gyD>Pn7!dpmpZskIs=HAN?%*D%$^FG@owC^2Sm(^U%UQ?iyyFSf@?0SRglV*PhIi z=Z@u73LSQsxUPupfU%rt(%FR#GG_bZ=QpVO?~_x+yE&grJrSH$l$E*B{h+t9sT;lxo-L!D>; zPZ|6AZLFE|R49CDj@>J}OO0HAo@ZaSP_r{Tu~Nt1T6dRG-jol&t?$ZxQ&R31x_(hl ztI~L#x1IdVKNf#P{>=QWny8qbHD_nzt(Eg$&$nn<+%i3l@m`ktH?GoYb1&^pA}FU4&u#pTBeOi5+!Kyz`=`AZ4G*UG?(xi0^FQSiieUuibQ3 zWsl0e%X zm&<(q(K0>deaHQj_f{Ky4tR$hh}!(tvSH$!&oj?oYPzAeIrXF5yeS75r&^ueblUc0 z?kPS1z3KrY9{(Vw~hmFS;C zJ;rm-)&(r;dTIYFvGc&xKHJdA?$HlEJUiFtIw^0?BfC2G+4lG5u8({kY<@TL-`R~K z*M+`C{9ktCVOO;*^Q(7HlG2!2|GIOt-aY$X{`%dei`1Wfy0Eb2QN$WHeXqM4 z3+%R*r{7Q#vrS%p^-R_Ex{x{7Cv$E1bvv3{be->ueXC`x?>wl~GK@QZ`{1UtOXazJ zHtoK4WA#7f&92sh^AFtNh*X+nM+p*(ZlFVzLR_hHr_1$bw9N+lLap%5T*3Q3M1OCdS{^326 zEAc$}WSXjM^`{uOeEr+&EDpr3k=v*5@caME%JgHPN$KlWmK|O1*PQw)U!<0J=rdRQ zqGcA3fAw4KuoGGDc{FtMLD&4!V~-tMYv$$zz8zW1BM`u=A}>e_8bH{X+tlBqW7@iYv~vXkA; zl+MKVbCdDW$x_$rmofj}yRF*yjn?w}y?R`qGyb|C_3e)2EUtetH!s`qjji6=qw*qa zG!vJE2J?Deyx90%(^dOL=h7wee1o%uQ;b#-_0+TxmTisoyh`OX)n&cE6caZP&m zqp35W73b_*zC|g^F2-ha6FakpKmV=i^Q?B*JdS=ktUfwRBiBf4}^&_Q+G0d&?hGzPZ)J=^cCROY+w@Y!56~o?l+H ze(ypbi&fhy`D4#^W+pXBoZe-2{%oV-{EDr->>n!s@!snT`Mks}Ihd#WYESCTM7=$o z&pjXfl`mc&-F0Y(VAsc}g{?cLCO@cMAHdz8_^{69Zu(Gpd;{tFu|CRcw&A2tO+|rDrS9ju;W{CblWk;hss|S9xc_C3~}oD@|`p6@zkYvWKQqA zX|=ZUltu7o)z=H^jmjT;wJkN3|6_MM^swWt{)ZFf?6S`U$?eb)lD3n+rc)X4dBs|0 z*&u!|-AkW?y7`VsZ>)7p;r{(~YTl2B|5gQ`?CjO*St23(P$Nm@E^DLir!J2>-(ojR zT=M=imxb4Np9{4uKh_Aw-}<3ve0nG6GmBkUnm+PH_@6t%_u+TW>bhJ(aW-f6KTI#} zPqJF^pOT#+7qae*iG1Rz^WLelCv2XU95}4oHg%J4pU#5IpX6>Hj1TSlzAn?Ad%wt| z947HCRVyB9B&ZZREnFVb^81b8N6QnR-xuhuc>nay4&ln0Nyk52iT-`PLggO2@YWmO zZr#v>5Z~DDnafWN{ z?n?eUCDTn5lY%85N0hOB|HTs(ZK`%muRm$(|5dZ%H}V;$ExNaJUuoG=`>&^>CY(Q< z(adhiS9m1mL+aYVciD?xU$Smkn!coIX^ix&;$?RnFEm)Ow_lC?9m#*)>C4ZEmp)5h zLp=h`2Zc61T@Of```aYr9VtYo%LpPC$D^nCjDhp%U?SQ^{$@vtY4|HbgD zpS&53Sz{MPyiTrP62Sed?1l7lzFUV*y~+8K(YD~eo=}N=iXi_|C-w;2WsEQ5qf@sm z;C}0F*QdWb?%J`Lo6kmFyx%YCx-@9Zx5HH*RUZd_it}dd6L}oEUH8`YyCS!HB75ZZ zSU#Go#qJNe_x5|a$6EdP*~i{kO4i7&+%}_6h2@uxKve2Rj$o;dc4>mk32TqD>y7@}Jk~!LJ@4!`rB{yLdtR+-{iyZ!@rEv5XDi-S zve%VAr$kMb`5|wY@A`JNk>Bzs4VUts&G>H2Fg^Kbp#81O-yaC<>wCKXa_RR~SGG*z z&z{~rf$PbdE5CjmsY?;6W;N+=j&NYUc#L_;-;~MscW)>OZ+ZKBM>o%g%41$p7YbBE zcYjmnxuafYR;qQRDwzFNdG+5To1DtKvU6Q~!VSOQ*rHG>uy@8k^=tpn%3aG9eCsD$ ze)((Q(#Y6jL02?ii#|_I+;XO_@8Ma=kDik^@xA`OH$-mH!?*k6Z+x?pwqc(tZDSeY z$-V1i`k&KPD=I=?EqIl4cKV)u$&o9qk8a(jbaeHNxi9U~FEs8C=YM}rDgWaNt%-Yc z{xeRTXZ!N!iVH%OISX06m+yC4mmHb)GV<-!rgzR?+dr<>6?c!Ca4TNs)_=PnA1-Ga zd&#_VxbIiv`E{*Qb$Oqn__>um#$RP~UKPu2sy%q~1OLPCr=71am^6>CXTRWcXPv1V zC;gB=CbFM@A;Z=)af~x16S^hViXDx#GdTVFw$70?R~nNy#K@di4r7lBT50!L<95+< z)=O`0d@h)D>&;G!M{a$J;)j%c`W!8k+^!hUkN6(iAMZMU>dm7)HjjRNx3nyfeYW-U znr~v)PS&lQ#@Dmo@Em)@ssmmR>V1qaRUEp$M(9Z1)T%@B-;Oq&UVhEx=I@33de)k4 zzY*imdqMj1)}xsskLGk%ZWo4Y?tT>D|TR%pw8(*?#yg-aK_R$nVv zW%X{`=6{<@(k+i(J{S~H9&@}SIZ!EqNBh{?LyB|hC5_@G$8aG}H=DfX*YPab96 zo%4IOYfp@lP|S#|zI3=|O+*I*R=bj+*-S)QayLuFTUFt(f-Pr_fAyVVr?< zx)9%UpPv<_>h}(rF0lUVzGFu48`(RroIW*V2!yQ<(|sI1ubcTDg%7M@n2yIf^VFVx@Rn|9l1!@N>X`JIw8m8|R5REjNJ z6w9vh*z>YCb-rTb zd|QuWzdp`et+79)d4+gk=-H1~j!*a+V*UE&>N7`+F8JR{>$N<0#y4r*@uxYpl{;8@ z53h?q{81psE^?Fd!qtY;e;8)kE9RM=cVs-g*xB=H#j@W{%t6-g6SSXozFxw3vV3El z&8eu6uXf${gZ&k5>^^>Q)snv~XWezzIR4)JCg|?;oo7#oF}_`{Y{ys9vTen)ic?|{ zTi%3zw~u``Pd4XVN93=WvYYfTrw6}t^Dh(GBL8ufu|Hq0qxHt+PfiOQKP45=6@RjQ zBS*QS?(!9kic%}9`qML8AHMzCeDqz8RgVql*C@xx|37VB@0$JQ_`h!!a{2MXx}NV~*7tNRY zI54_9X2I=P=3R}q&YK$EcWd5x`n=&;^#>QS)Sm4-{V8DHI>Q3i<%ik6uL()H{Kjx7A&oG$ZihLa-X*8Ei=n36$)zPb{vv< z?P0Rx&L$?VgXt<-vJx*{@9+AOx#RR7t517O>;Ii!AO7rFM(Q(j|Gc&mZ`iUH`gaZ(V8KHanZxI>pm$ zd8ao0ZEv|=5x@P!*~;9lFMp~Z+w|k7&yj`Y0_AdjwL)_YZd8AL@^stbr7yDH^A+mU z*q0qxlkoIO!S-!-6BBOro5;WSJEeSgb(mej6qDt3I<`U9bql|g2%dX&{NauD|1vDZ zAM8GIf7XO8YAL%WR9q1`yX=a?J^A-5Ue34omv|;?8lmbFx`6-n;~R&>^bCC1H#E)j zk^RCOUT&P}Sl*hqGiqwo#4n8pXWy({>HqFL|7u%K?yIaSd!~H#+@^Evp-xlp%Yc-B z&-dhfoV@S3M8AUgk7LiuPs}-QGC}W&jo0SIu8Z#^?pwT!Jy~Ld$oI#tsc{O5v4?DD ziljXcj=OVo>yJNX?B}NTKK@wO6KUAzDj!z*&r-@dZG#-Q^onbhh(qL_30wVc?)3U# z+x@xv@R`3S!j7Ji5_Miboo&jN1>$L|D<20Q;{3~g%fBn0b>9;SiQ`f4Jko>McTIQv zUudiGhx7NBKmYcA^;xR_(73nANiID?f%z%RrG&f zjf_}SV@&O#2lIO78QkCcZ^2={e;0G6>|4d z@;_U+bWE>hNQ1O^v*88Bo108l9F;lZwX>mN>KSgs;*zA|hN(_>3=Ah%UrLYvSUEdq zZUmFuru9`Trn@lN-kz2>|0Sw8)K}VCKY72|*qg6|mBZL``2qH`Wt-IN?r__hr7x_?ycfH6`YKo5 z9n+O##cxzDIQgGtPe^RCe*I?VzSg}AiiuY*m85UTWHwf<7psu7Z(eu2Ao(+sP=me9 z{o^lhp0D{Ls51ZO%L~_ykB0o8rcl1QUOuwejsLEB)0+7uFH)!ZdABnQDeIM~yl;~b zzakjBe(9-)*$WH4evGc`eeiW>lxbOY-`ulNwYoY}uT`p_IZ`3>(I)HSrr2f2pNjVt zz23Sf@to}Co=agn!t`6`|Jxk=V*fAgc@zG|YcBc!eqG(i^vVy}&K=C3LZ|H$I~D(6 z&-qz5Z+*>lD%z(Vs-2Kxdca2V=q?TIgslepdHWP{7uk3JW;S0Uxc?F=5-x@VMdG)&}P`!(G32e6)L1pOBCdlkxbJVz;41 z*nzAgyY5Jq7Mz)~af-p@4MK&JzAW;KYglvdh|dvkyK`RsZzPVDd#rt<=@Ps1*oHG- z{8Z$(%n+&lW!h>;(Vglq4QZ@ zhu+_wbwj%=`k4(=ik|8E)N7@WgStikpSc^#7%H;cAb6jd!K5ekTXt{JedYZ+hf99x zBa!;YbNJiNUw9K6|+h==g3Y&%~%*_a_@n=KAm`LDa#hTmaJ{#QUm2JBdw$fI9TKWBV4{QJXhw{X= z8m^zbq~BiNV^h3hkjSI#Im^{*rmgy1YjKKZow%>2VD@3D;~cW&1DqVpdrB&*8w+iG`Jg}&Zn^eiwiH*o$z#+}z& zW7B^$Ro$@Vt$A!&BbVmOZIy9g0^beZdFm0nLf&kNQ#`&YcAeSAz)Oms?d-y;ir(_? zPJI2WV`t8N9X&hu)^)B4`Ot z^pM-m^M&Ql8bhLAxA!ex_pBmwFaMqoPKC}{JO9*nyxw@tt#r4zJ3Vvm-x3**b=MSRdziJ%xu0^X`}!S!rSZpY{?>3yrR$5^YOC&+ z%@^;ze|E`>r5Ep~y->5(2|qr!I&aOH=1)H)7H@Of{q<>;p6c%@rvtl7q|@*B?%TUz z`pln|HkRL)b%dWiBr#W|%1dzVgQuHIXUYAVE8cvOP5jfDChjQpx~zleUiF?mWV4#L zHoWrjQQz$ArwzFe*lrX*Rb)M}Y`2`%72lWJu5 z-%fo`$~6A$MK?YL#O#b${^Ry3^wO3KI?Y?1{4f4X`X>2T)M?IYTb<@XkAX8*d!?cze{-IJMQl!$V1BAx=D{sBF&0z1|Gv4&_;$Jb zl$wC3%ISL-pJP3lFO&1QOIa=L)Yc2ea-Tb+9-G`RoLFpsWLewH3C_E|e6zQEJ@3lz zVqvj|GhZ#qF$|oz{HgVGGDn<#(UanxAQ-yKTYtx`ZB9*{=6q%=dYbCdX}RT z6K(!$!=+_@NiL5vM7ad`mpob!e8Bs-`TGfne<|l1Z&!>gGFUu&P4UrhJKDtAkH@^- zVdDO1Tg!9l{ZSR${C20^m+8)}*;nAr)*)k_dZ|L;dg3jgmlL=ORy<8tNnE;;|5`@# z??lE+uAXnzraju3!nduk;f62I+q$Jw?W9frUtq0!cUbb)U{jP6!d;PjN z>7x9zJ^g>qd%Vl%(H8V}JtK1aUQOG~>3e(&Q!Pzu?=SqnHhtG-nN2=bY#kvEU82kQjs#{MKli(!?ff^}k3mwB z`#-IeJnz? zD}#4px*40{TfgfPev2MWTYe|v=@!F(>AboRHzv{A(JyVC&g|q*|5AnPb{`c6eEphX; zkcR&|Hs9XxCg3cyZ_n$0Yd+lcWBs@MSgh>s2R{;;>o3fDU*l#ww=#WuY3KZPW z-BK#39oWufeDu+$yk{Awy8qAL_i^@p@u+}wr=8!w9Lvt1pYt>6&8$sPiQZr4PLJ4f zbXtq&*+fOQ34d3$&cE#QH-<;F%w~h&^Tmma_rE;ztWSNvTQF<;Qvc_N)Ss+odnaF| zZzFl-{PL|WKjagaOh{H`4vX@9 zC14n=m$zn5bcNRKoi*>K?F%)o4U~-HfAalTW!iS#gK~%7EoIy)zW%Xo^hc9lAJ0ZK zS6`gI^v5nX@hv6ZyH7H!{%&|2!K<0v=~h2Ee)@0io+}4^p481@w%W8ZT5s)ioygwh z85i#vyw195$(*_6CFhj9?F=s$UGXlKb&Yr;JnQAEonn(kriKR!-?(*Pw!L5dZjC?x zu0OkP>h);m-+Y;6Uc2)&=W-Ri{XOru?aorCXP;eu>|K^#xM}k#f%(j<<>o$mgGb%SE!2$`*(-OH2c?qV{TjA&HQ%@Y^t4cef}N6=7lC7 zdupohzTf=zU*m@b8FDRF8;+*-Oi3<2G{7}-VrMqD!Ph;bEL+=wR&$G6L{ob?ocUWxc%8fE#-Up;CrU+ zPRpQn{aM|z&CfHOG?#=%8gD#*tk&Z8^26DYo4>AUyPjPzD`A?_jSmU37yp&i&G~;U zaFV`u{kr>>$8OjkzpABM`|a3|0h3nQ(L?7b(EDp-{-G7pFUgMU%GyIkHDM+VLy&* zG7}0yJ_K)_ad;ND)9IQ{k>9bC{JY<`Pddu@Qa3I`F8QM4dPCMDUnd;?_-Ka8cI7iJ zIVxwSOqzH2Z^+5`sX4MK|E{L}VUjMJx!|nIr1jIL1wK;l-C}wCTuS4N5UU>?3NorS zPb|aMvd*9SCE_|)fnuOwosYH|@WB7jwve zyuHiQ%y0ghxyDYRx9lh1TYibZbKXM54|dz5YAcJ5ckbl;bMES$ywtqqjWe01hn(48 zrxF%*=+ianuS+C*i`}khDW!SUzt`y48EN_Ey|ijay_8McVyR78f99CH`&ttBg@@Pr z&8PFfj27-#$Z@=3>8$LetH0ByHMQ5J8GLbG*`V|+%~RSv^7I?gf*ON~e>JXs$+%YM zeDb@Tk&uTF zmrmBb{5(!e{qfRYawYeVc;8)^+!|~m-@k5qxYc(KUIW{05#Dw4cCJtFTWq+zXd`Q> zS?-7G8LX!=>&|EQ?0ne&a`P;EKbr~rK2Dlj@@$s;%f*k+2!8PVDCvC3adSr=qwJX} zZ*RQ+_t@w8On-k0HAk;cV!@6PsU?|V95s{OSfw`gD0N{KY9S$`Vu8!K$-HMY!{ zap`#R2bo=Ses*-tfBv8%`E6G42iEfjhr_1UhA_IXz2<4_CHG>f)19Kp>&;{A>$%&5 zX2+-AR(Yr1duZL^FQHdi1Gab0Tvd7NNMs*RQH^i%*~|GKVrz9gPDe~#CRkBu+iw!{ zyhO%5v~JDI{*XPrzqh>ky=a5&IaXG=jP&irSHo5w5sqx<%fED(Wd;AO4Qoy(%3n+V zw`$tbsO72=%UUA0-Sd>zVofe;eIoJc@dvK8k(L}Xs=@7c-%53&?oawRYaOfFv_{#> z*DWkwJh14h)2ZX`m&-rw|7&(;rh?px+3WgWNXDP3PT}XjD)F-W->RwiH}qFbX{?@f zPJ7S!f&e3Bi)r&^B7UdDys>r@>f@@@`JNrQr}uTi`KcEtaK}t|xZ?XMe$Rc)-y0WN zN4odAzIA$@zE3W5m5qMbo3&g*HA-)8nYN^zkoY^eil9DfpVhnn~OVaj%Uh;My4l;ud(}N znlF%V{JOjFu;D$mWBls&(`8VT!i>JD;?78Rl^Y=_X{qw-=h>E>=_xSG}?)&1qGQ5s& zwc`TjM{SWY%5@TTI)?*4Za%-~R{K-&pDX$17FWNJOGqocw(aHr#5CEfhxcV)lVscw zT2;3CptFqa&UtH?qs6938)Ss+ z7xHt@IUlgr*`m#@?Zn>*o{bx(h=+f0NSqs@-(KQ%oma0QB)O|&USV(||KB_QD%F+! z%?nE{E*bNGNs&^%%2QqV-sa`3eJ6`7&4jGa$gE@!mfp!!Bwe+u_vFNr>gIoEm`;9e za49M?<$6&2;b ztIipJUG!+*59^u76u&$QeIhxbE-_@$;^v!r){9#6o!U-CadmOkxm zb5sxHl^R@IKjjbO%~fah_9m(*f8wgzwCkMtS(6W1i~Em9EnFWTTl#wG1LiY^*FE}w zFO)0&^I@Tk?#k?cU;SDZiB4jFnW*pOe*X6@kGgr^U)s$-`F(YX-qGv5t8VNloH6^r zYR>BdjcNadix%vVv0qafH1BZfmmPCjrZ4M1UCO(ArN2v-@X3t~pB(yHTP%hCPu6L8 z9s1FQcbWHET?vs&gPWg%&d*6M)oa+h<$|L_YR_NU!!5;A)?TxU*_<$w{gF@h>P1)F zHuXmbtZtV(Z>qaAfoD_A?-{1So6>H@R`;+MZ>rn(UVg#;?B9y=c3&=i?JxdgaNV<% z+w1RZQ)Q)ne(McGCL*u#`NDsYVJn}QYcHmqQL7J4Jo!#AeKAjp^8bq0at{~S21w5= zNqn^AtM0Yn9(SuQLy6;i&9{Hb4*na(xBXyqzx*dHjZda`O-hye7V&<0|3z*2&&N~p zZghrA@!iUp^R_LZeU|s~d4H~^KTEm)xN)D(i-lX#Ud>9mQ+(e%_DbMS+36K+JKJ`D zvA-I0oL{_YYtY(im6+V{8!Nu4J>R`=slNBQu%FB4oIY}{Gx3@5tXC_=zbyG(YbP7K z!g1@QU22>4aw69OkO5i+kS{KKsxy>b&uZ`Va@U8b~kO=@$B}=t$gnaK7GH-zjV&^_m5wDRk4ZIC(rSe zX{^#{OE0P}zO2D_{bKj^%ih<2UEP~>mFeVvlk)W?-u#DsBxgIeKbv=iapiOCdn-x` z?>uDH$UC~$@iZS#s+@++<>x^GADs{D$Iejxxig1XqQv0-)oI`79iLMvC-(g6J1Y+< z&GM^D`X-&d6n@1%ZP{f8SI$fCOHWo+>Kojt?&3#R zJN8d__k7XXbDy`&3InrFoC%zSPrYb*^ij=dX@Dy4Ry>?L&DB&-D*Z zd{>rvZEt?Vq$owU>P~;5d1~Rd=$Hv5O4}b>Xsvy$_m#sYVCS;g5le3#@jCP6|6F^4 z)*6R*hl}D=6FH;W=ic2Dx8VNn#_vZ|!p=NjviNY{*SYEL$JZ1u{Hzc&rHtG4SL2TL$=U7UOp*3VSe6|6IKbXs|xKmG8CHc+@bR&ShQ(p z)Jpb^H;-!GJm{0BxZ-+q(sg^il-^6WH}@*_o^!MC6DdTexEcX-R!k9D(-lvb_{+nbl&%v`k3ec!4**2$VL7v^w9 zXYW+?|zqxd3$A9)c+^< zMUUp~+TQlC=GWO`g^%8uk0n;_ic2_FdZgO3J$^^rZ*M32HDRXD<$JGAIpBT5aQ$oT zJx^FI%%aM=?u#D1uJX7&il5j0=Juoa{Pt{A=048aGiAN_j6&Iuan};lANm}#uPkp} zs8&d z+RNA1O!zU=@$|xd*L-5u&;1y*xIyvd)N3}Kzdzo68JT+N-KR?VD_QHya<&)hZ`xUV z-eBWVo0(7ipS@|TI8->LYTt&A*O$H|KaBr2-;(`E@!K1`-)|rI%GkZ*mGbV=eJ9?& zd7HL(i)p~&S7&aR3K=IPRX)5|`T4@%ncK5g=RbU%ah5OdN4d|0cL!8*Cg$FWIe*u; zcwL#=*~*I-Hq89*9rx+a<2@I*H_fa6bJ@(Ws#fjJU5iI~(_enpNH>o<$rg9%>-(1J zOS;#!w=*U2MSm{QURP<6@g$GUdluvCv&6v7oN}&+<0?``{=9+&#BTW8G%Q75PYK zXRW*vIGM%yn;-9#x}-0X(J%g-c$=8J!?sdn=d4L5n|x%ynO~iiYj@k(EBNxnqssGr zua`A{Tb$l}?-bM5_YPC*mao6=W$~&!^+(@`D3C7m`xh z+jxW5R7QxTZwz0UKmE?^)pwKT2)~}iHRB~;xro7pH4#UABm_%p9d>`8vXXOOyM@-P zoT`%IE4xD(e$Ib2yXr-i=G$q^>91C-=c}_V_bc4ELF$Ry{qK7>cpdY2;&S9+&eMzz zt{-bpc23sno_22TdE?EZk1dlXFPF1_CsieLMf+*n;tX4OwhRUtrPpXgjZFG)(hm`%Iv+XJAayIoZ+S|A!!QFKKEO5 ztFe9iJwx=06tnP|qgL~u3VZI9{~dkRZu`P>pKo|y)>*On<9>%3uR7&E$#SnUSwDTd z#3HAP5byqFPb#DOC$3so_jPXXzofu(d36_mwTL^_uyyTTxcs|`W##%mHb<^bxwE0+ zz~3K#IS*~E>z3IeSD?rkzsJ{V-|BC9vu8P(Gdo;bwe@$H`5*72H_w>;+`!|VYIAbG zpum;xhxxBA&RmiH+WCLT`Q=ythM$Rvm;EEDapl&Rd1~zMr~Y5He_Pt(Ym+tx9pjB` zpTqpi^vHhY3-NQ#7;m!UUm|`*nJNB5@;c9A*(H-}*1r0+CSiwlf42QsQ_JM8CI8nv zpYSsGhYerH%bA8->tf?$pHDA5^iay=q4k^WqmM;4T1*Pd;fr+3o+U>?eAUooq z{wK?=cMMxHw(?v*u%A0%cJ|7}H(s$FdH7+a-?SUwz)3W8{eKT(!TmR^Q`fU?6P>- zOHyIy-4<;XZD8iIovEvmxX|+dtA}%Uu?F?OSHEAV&V6o+(Yn`X<2KK`@_VA$m)VO# zjTf$#6{vdVwU_zyXTE5YdT*`_C0dx`@0i$C+)r}RNd6)X}eA= z+RSo6fWy?}Zz{$duYF#!gl(2JQkOL5)GjPP=lCb+vxBIcuc5i=GM!f|7eD{A{q5;h z<)@Xe{BfLj@YqCS^YaIEwU#}exgsr3U*+B3#^7qU?dAsSOl*JbjIKB2eX;Vb@7twH zX+>*)?6o$#a+`n$tTY0NDy6lqgwDYTW8g{p< zUy7Gt+;Jk_;fzY6%tnLD+m}c$aX91B9q@jdtAc#U#;uHJC!AN@E?hWCG~l!Sfe1(c z7sXlSdJ3h2uNSYIxzA?Fd%pnp=W$KD%}Qiu+HT#h*mjZo#;b^!d-4XCJa<;KzgVbx z@3hhKnc=BltN-xteY$nt{^REJj2TNs&aL~PnHapC&t!Jbjq9)7bT0G=o1HuUH_Ua7 z@4tHv%;zuPzI*9pa>2EWZi-<>PjvY>VkX2Yvz58&F4!dWnzN;pY4cUBig|)!6Ux=^ zwf|U^sNb}d-)h45mmlrFtDKoqdhhOAE0)+rkJVlqDqRXba3_#)UF8*jzWOSXJ>`xX1AGvmH*{};N?QD@jdn`sllS=d|JO9UyrD#Y^=Yj;&fZs!`S91i*m=PxIIvW-Eh_6! zRJP_C78_~XGeO&z`E_>}Z}dOu{_mT~EwOt2=v>~5xq82^%*m1R<8Kn!ed^Np!+TcD z$+T^KVSl-~LhjXp{o>pYR&-8Z^q=edggMy@WBPYkuL}-%`*Nx6%4*jA*~LHCE$QcS zC@ga;PFJ&jJL)gGs9%i<$n`$LYWixoWd9S(ESu2Bx_#O=BQB~>l~hmI zpME=ImTHQAx=o~JZS0zvYCYz=ie2m3%&vJD%ghdXW1-?Nxyxl^WCKmS$f-&f9Zx&F1MPFqHl&sx8+PT>3tgGU)1x$fDUTW2m?YjiKYb5X&My)$0VyYVG`YMFkg z{b%RkD;GY!h`247x-Mec{Oyt9-xjKtiM{Zhy)ayJhjzhU$yX~RYwxV@=f75{=5|Q^ z$ol1kZJ_rF!GE5B^{=_nS)@yJ8BZ<^<&Gk{;VHZ|_Hy z-ZT1<+rGN(IQBK| zi}PWWv}6$6!Jp3sOFJ_{ESn68%rjr z=`0A2`Q-gIsh~wS(%+Tw>(<(+wWll>+|pm#A1l6f>#A*^_P@1E-QWL4c(!f#Ej8=Q zjfIC-{&lgR%K10cc-jrysKvdibN4*Gx?4N8C%-NrZhrKYuNQgOM<1?AV%+Pi{@40l zp|xYtUGt{J-=A_WjqS=kDA;1z`a-(rRq~pGORjcW_t%THGWks7>)Cr#^wkHymytXB zL_ci#)_icQ@avzIpWJuWxqiQzvo%gybRTDyt+d5>o;*--}i+-IxLQVKK8^ssjKsDR$hv_J0*5A{fIOZMB?Z5gvzwzYTgf;Q3PpTc-p6_Lz79`X6O?}OlxEG7w7gy{x z={$O_>)$(-v%wmI*lK`9#<&zv9;BO%EoTB~P=N#>sPf-wVF%Gs=;E*_yR27y=BwngX^iuGTw3@H0Ke|`QO>Ezs}zJANAJL=VoG+ZA1ez<%^ zZn0lkq+sp*FE(|@*|Qqwgtzv7jXO})xI<>$RkQfsxCigQq#t|uLO55W-n8IKg}~L7 z--L~Sa(ri=)Q!mNhpZ3h-l;dl`+}693juw5G)pSas&GL@-*(iZ>3Nf$ zCC&|gQ2%Cq-J)Ohm$GkZ|1Vn@9k7cNWom**D~fAYPu=)d&)&IuA0 zw(X*o_pO@GEw^3G&oOPss3uc-T*>(4!B_bi&jz3S4O;53(SeJ`zxpRJVUpD%Sk==>zRh@B!LX*} zpTh#6-w<(Ujx)zTo=@zd!BJ-%>#9xc&lP7(O zT)Urnf|B0y11qZyEw~LWuRF^=vNe8db^K@KsmlJgf_={zZ*i*lCE5F*Gm;FhS|ly@ z|MtZ{*W8=V`t!~++3|G>&pq`%k9%3C-Q@0u{1n@~bDi{?mp1d0_nw-!_x+xgI`<9T z!?jc9iKTNrE#LHSGRq>X4_p0TS{Wb9f8(`Wb$Qrxqpv^vrbKwA@K(&9vW$<>_~w1a z4*s~$qBl3S+=}{ospnwfzvD$NvdeCrZmadHbKUaNe&u(*sB1<){@(8o_#&t8{@i1m zyZVO}f=_Bb@3Uq4pL6VEZ!i46 z=2ZV``+a3oE2g}5&T3}OH+R$Zu)Gl}{(0|_JCEO3&D>}9<5afklIz#k8CUo`tB*Xb zB*2K8qA^-gRc``*Go9hg6Evs3olkT2! z|21XK-HX#L+t!qDv9q50bnE)5X|2+Cqym0g+wQy&CH;Q=#OOpR$vEDbU$<0LX`NlS zHZ^kwS6s5k zJhQRY-SfA>pBe1;cLv@2nY!hnwZVg_bF!a`%sY6r*~Hd(L7(%yBk$(uTe1}{yRmGQ zg=P51_O<7KnBJ({A0Pkl%)T>!h4yQIzPV!gwv=Q0&L98!yq>-S*ihFxAf2W zxbFW7*)9HWcYG?8J@HjB&E;)+s=nW&sk_vkzAsmeW8Nk)H>$(#vF|ent@rOgT$#IT zPrd!h_2;L2sQYvI|Fw@VYTnznf2oO_6}Zd$)4UCvTF)Hgd+NN0^M={o<*64o3HR+& zYS!Nz+xpw%ueDQy(~;0KLakAAUXX`FCuk?WZemRog@VODe4m|5&V2aPRT^KmTTJUh8uIb+~j>CGYCA z=cd0;S2t}g5*y|*8Kd@^8fSn;0QPwh<3F+AgtnozBO zwQ6n?3Hh_lDYMhx_7t->4%fffTin}gM{Bb7Xnd!5GhwWx($gj4) ztv>n6ne`ohwQEzGq~zZe&70Qz{z{$E^O4U9@qzcwO)?I$}%2KOu5^JY&N?d+?-jV;A=^BwGx|X-LF6h|J_I{CA z@0-UTCha|P#pq4X|FUZ>Hxgg`&O9+y>H0_i2aAg|H(r06Y%EZ%bML*Yvf1$;^Q+nR zO;>lyx?vol&Uanx&1H+H>(lFYG9UVVkM(NX<(ls7@SF9e@y9CWb{GD8YR2LhdTY0^ zT&3-4)p=_@9x>II&M&-ZmUAWB+UD}yOEufh32rV_nSZzV+v`6bp+`My*2T)^PugD+ zFP2?eF#o~6=}$j-^(wFA|2%cw64sr*nel!98a}VENsDOOU}xH!_x;hwpGyx%&zyUC zq4>MkA>I=4lRvDh?D&3h#az8Z>xy@+Z(I4J^6=6AZOm&F(ht13w?#a?xPtlH+t=2j zuZ~-k??@AP_y5WHs`suub8X*TU$H@@-lM13F*f?SXCC`bpX(V`?x&(AY~Qg}qVxOx z?+O|$C4D7F*Rxy|Ud1-|=hX!oMY-RiFWmZ=^x^8o?bj+V<+?wx3tYS~cdoLi?unll zB$75a-U@h_a%}pc2N#;x-)jHNQ}?Fz{EhAGitFOfZjpcP86;-$q|V#zbvL(Wc#*xj z&a$r|mHRes*zs?%?3_Idwao+;M)jY|yn6m;ETfQnk>67rt*NbB zuRPwmcc+|*hfbWO`ZlrGTMPI5{Mq`w?38&-P00MGHCnfw=RK|S4_{wnyL!9KyZtlQ z_?Q0Jc{Z8xd}7q+{qH8$ytaQ+S-oYBtZ>)f=v{n!>Rs$#uiPZ)vrBJw)OnFc<-6Zb z%D!oJe|so(^J~Z10+WJctJ81PTxCvRt9v)^eBOV1EB8fRmval_)m&ai)UE$Jf5Qgm zg@X61zTBFlZYlmj%uViTl>al2xacQ=k=(P6?>L+FJMYYw`JNj-E)w&}elGRw+;0Bk z-QOPGiTJ0IFh|`o{F7Fh+|vbp!SQ?!pWn0QhQ>PqWl^^F)|4d?&+!DSUdkp>L`qrA*f1dnf-QOL& zcDpW0-MV&tTU7k{)l%=o*I(_PS{dc(lePWy-)x0O}kOKZ1(ld zMQ5ZGxZg$Yza@L-*7?g1r0&jpu>DSG)&H44ZZutc{5s%VBhTioYZId5*gt<=v*(`a zt;xoog}(Rt_g6nZtdU)Ej@_2^zW=GmbM#j*WY1ZdZC~fR{j=^Zmvc{k=V#0>Uj58_ zP1#xX&l>hmZhkl~ZunDi?!ol?ORk3p@n6c;UHQ?X-^=W!%)6-DpY}UTymLEId$)Aa z$v6AnpEkT7nU!|lPUhS;y+!L^hg80s`c?jZ_L|?tQC&BtEGeIwK7ph9=a)G}=VsMP zoZtGpF#Uv^Sh|*;ojd0 zxo!KnHgwq>vbT9;yW;Pb9}ga9{fbwbS=0F=M?WkpZ)(lrb?dH+MGL=uZD!Gb%4}on z&leLPslPD1#l_#)$+@fTYST^SUsBVS-{`D~i%mRX^Kx%RMaSQZiFeP>-q{~gxcy*d z$TrOnY)iL0vUgSIwUqa6QP}=d{7i0q+~HRTukV$(BXh}UuCk^7sTjjY?(DfYZ%=sk z?TM_~y4NYUXMLNzBj{TFo_RH$KN>zqBv0uN*3m9kU(c*5clWvXE&aK_m(1M$-97H} z6C02D6P13hJF-~F{nO6tYizyaZ3JNdK1 zvLCbM1sl01DzANTD?Uch{gGwOmrB*`F^&%=oRi+qJ7*%N@+8YWzjuf{5m?p0DtG34 zdHjsx`D?EK5O`>6xLLV);W^c+N~7aS^Q(mH8kWCa7KMt-0}UI_8#RMQRcoiUKhTL zecZEi+tWQ8G90Q6pSyovuzZ1hQSR~F0==huPQATUaku$$b7%C#bk6wl=U0y$-~8b3 z<=RUg%MH0p_pdLWyNrEl_WVt1TNeE{IqOmB{;61J|8LG)H~zkub?i>?l4`e<_-ohJ z#IQd)xBr$`9p{FLcds7$vwKfmMEPHp3wHML($^2zd;hP@eJg%i!0GPsoqiXaA8qxI z6pp%3zbb9Xo@DiV!RqBZ%b9ApeNH?6@VHR?wq36K>!Fvw`u{9DzH!t4*{At3qOBj_QJmO>~a&;=fzvzOE+CPqQv&6qw1=}!`8_M*Md|GnU8zs3JHWUs-6enIWyZZd~nR;W#{_;cpW{L1PRzgsrTesMZi zdS}`Z`4HitKGXZocP!XXU%9^V&h=kABj(4hiFENjVL54ieCh0;=VkZasqCBeW&Rew zdDQ~vrR(MYe&LjTR{8YvaZ9CFMxX2wH!Jrr94l?gZM2`ErXrJ_$Y1zaChC~2#a~hN z?@nLmv;A5pd9T(!;a|wNW}kVF@0RcUx7fnkP{(5Ry@>pip93|D=frH@lDY2nns2j~ zZ;8ZFAX)KPxUi=B#`TFW+^%n#7qeGpdZu^j?c&(c{-u19KZ zeLmd#nZ0uMnr7F(>M`r>jxF4``n_bC^^5j9ZEFN)+g>nb&rbaF`c&H;nJl|Q4zeD< z_^m1mt(S_={OJ1r^LKbB_c23#FBH zd^_YG9t`c=`t8ZrJ^DZNf0s|R;`*afBzUsne%n8Oj&nSB__n_`*-~A!Px^i7|IL~& z?d96r>Z|^o&%Yb1d}C7X?CF^)&l4Z`F`hs0nEl(FCcRRRzjON7S4K>Wx8kkb>esbM Y1B#d!=mnm1VcPX!{fi6nzIVA901n?YPyhe` literal 0 HcmV?d00001 diff --git a/page/emulator.js b/page/emulator.js new file mode 100644 index 00000000..7a007d5e --- /dev/null +++ b/page/emulator.js @@ -0,0 +1,35 @@ +onmessage = async (event) => { + const data = event.data; + if (data.message == "run") { + runEmulation(data.data); + } +}; + +function logLine(text) { + postMessage(text); +} + +function runEmulation(filesystem) { + globalThis.Module = { + arguments: ["-b", "-c", "-e", "./root", "c:/lul.exe",], + onRuntimeInitialized: function () { + filesystem.forEach(e => { + if (e.name.endsWith("/")) { + FS.mkdir(e.name.slice(0, -1)); + } else { + const dirs = e.name.split("/") + const file = dirs.pop(); + const buffer = new Uint8Array(e.data); + FS.createDataFile("/" + dirs.join('/'), file, buffer, true, true); + } + }) + }, + print: logLine, + printErr: logLine, + postRun: () => { + self.close(); + }, + }; + + importScripts('./analyzer.js?1'); +} diff --git a/page/index.html b/page/index.html new file mode 100644 index 00000000..0256f824 --- /dev/null +++ b/page/index.html @@ -0,0 +1,431 @@ + + + + + + + Windows User Space Emulator + + + + + + +
+ + + +
+
+
+
+
+
+
+
+ Windows User Space Emulator +
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/page/noise.webp b/page/noise.webp new file mode 100644 index 0000000000000000000000000000000000000000..50fa598461e833741b635f25457513460578983d GIT binary patch literal 37576 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 literal 0 HcmV?d00001 diff --git a/page/why-eclipse.svg b/page/why-eclipse.svg new file mode 100644 index 00000000..e12b0893 --- /dev/null +++ b/page/why-eclipse.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/page/why-eclipse2.svg b/page/why-eclipse2.svg new file mode 100644 index 00000000..99d0621b --- /dev/null +++ b/page/why-eclipse2.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + From 4e836cef49a5b5bfaef0e5817f6e9973324813bb Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 17 Apr 2025 20:05:39 +0200 Subject: [PATCH 09/20] Maybe fix unicorn --- deps/unicorn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/unicorn b/deps/unicorn index b29e3445..6011de1c 160000 --- a/deps/unicorn +++ b/deps/unicorn @@ -1 +1 @@ -Subproject commit b29e3445a4694e3a1061c910906b57d7d2a05ed9 +Subproject commit 6011de1c1e31a4e4a10f4fe82a4ac063b71b55ed From 00353e9a162763b5644cab0115bd82c177d1253e Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 17 Apr 2025 20:31:33 +0200 Subject: [PATCH 10/20] Fix argument adapters --- deps/unicorn | 2 +- .../unicorn-emulator/function_wrapper2.hpp | 53 +++++++++---------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/deps/unicorn b/deps/unicorn index 6011de1c..6f2156df 160000 --- a/deps/unicorn +++ b/deps/unicorn @@ -1 +1 @@ -Subproject commit 6011de1c1e31a4e4a10f4fe82a4ac063b71b55ed +Subproject commit 6f2156dfac3abad316a4f02bf609ec1bb700d02e diff --git a/src/backends/unicorn-emulator/function_wrapper2.hpp b/src/backends/unicorn-emulator/function_wrapper2.hpp index f9628bda..e7471580 100644 --- a/src/backends/unicorn-emulator/function_wrapper2.hpp +++ b/src/backends/unicorn-emulator/function_wrapper2.hpp @@ -5,28 +5,26 @@ #include -uint32_t resolve_indexed_argument_part(uint32_t* args, size_t& index) -{ - return args[index++]; -} - template -T resolve_indexed_argument_internal(uint32_t* args, size_t& index) +T resolve_indexed_argument_internal(size_t* args, size_t& index) { - const auto a1 = resolve_indexed_argument_part(args, index); + const auto a1 = args[index++]; - if(sizeof(T) <= sizeof(a1)) { - return (T)a1; + if constexpr (sizeof(T) <= sizeof(a1) || sizeof(size_t) > 4) + { + return (T)(a1); } + else + { + const auto a2 = args[index++]; - const auto a2 = resolve_indexed_argument_part(args, index); - - const auto arg = (a1 | ((uint64_t)a2 << 32)); - return (T)arg; + const auto arg = (a1 | (static_cast(a2) << 32)); + return (T)(arg); + } } template -T resolve_indexed_argument(uint32_t* args, size_t& index) +T resolve_indexed_argument(size_t* args, size_t& index) { auto arg = resolve_indexed_argument_internal(args, index); return arg; @@ -49,27 +47,28 @@ class function_wrapper2 : public utils::object c_function_type* get_c_function() const { - return (c_function_type*)(void*)+[](uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,uint32_t a5,uint32_t a6,uint32_t a7,uint32_t a8,uint32_t a9,uint32_t a10,uint32_t a11,uint32_t a12)-> uint64_t { - - uint32_t real_args[] { - a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12 - }; + return (c_function_type*)(void*)+[](size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, + size_t a8, size_t a9, size_t a10, size_t a11, size_t a12) -> uint64_t { + size_t real_args[]{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12}; const auto lambda = +[](Args... args, user_data_pointer user_data) -> ReturnType { return (*static_cast(user_data))(std::forward(args)...); }; size_t index = 0; - std::tuple func_args{resolve_indexed_argument>>(real_args, index)..., resolve_indexed_argument(real_args, index)}; + std::tuple func_args{ + resolve_indexed_argument>>(real_args, index)..., + resolve_indexed_argument(real_args, index)}; - (void)index; + (void)index; - if constexpr(!std::is_void_v){ - return (uint64_t)std::apply(lambda, std::move(func_args)); - } - - std::apply(lambda, std::move(func_args)); - return 0; + if constexpr (!std::is_void_v) + { + return (uint64_t)std::apply(lambda, std::move(func_args)); + } + + std::apply(lambda, std::move(func_args)); + return 0; }; } From b170dac195523d8581af29ade7702813abece281 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 06:52:21 +0200 Subject: [PATCH 11/20] Fix warnings --- ..._wrapper2.hpp => function_wrapper_tcg.hpp} | 36 ++++++++++--------- .../unicorn-emulator/unicorn_x64_emulator.cpp | 20 +++++------ 2 files changed, 29 insertions(+), 27 deletions(-) rename src/backends/unicorn-emulator/{function_wrapper2.hpp => function_wrapper_tcg.hpp} (56%) diff --git a/src/backends/unicorn-emulator/function_wrapper2.hpp b/src/backends/unicorn-emulator/function_wrapper_tcg.hpp similarity index 56% rename from src/backends/unicorn-emulator/function_wrapper2.hpp rename to src/backends/unicorn-emulator/function_wrapper_tcg.hpp index e7471580..4cdaed8a 100644 --- a/src/backends/unicorn-emulator/function_wrapper2.hpp +++ b/src/backends/unicorn-emulator/function_wrapper_tcg.hpp @@ -1,55 +1,57 @@ #pragma once +#include #include #include #include -template -T resolve_indexed_argument_internal(size_t* args, size_t& index) +template +T resolve_indexed_argument_internal(const std::array& args, size_t& index) { const auto a1 = args[index++]; if constexpr (sizeof(T) <= sizeof(a1) || sizeof(size_t) > 4) { - return (T)(a1); + return T(a1); } else { const auto a2 = args[index++]; const auto arg = (a1 | (static_cast(a2) << 32)); - return (T)(arg); + return T(arg); } } -template -T resolve_indexed_argument(size_t* args, size_t& index) +template +T resolve_indexed_argument(const std::array& args, size_t& index) { - auto arg = resolve_indexed_argument_internal(args, index); + auto arg = resolve_indexed_argument_internal(args, index); return arg; } template -class function_wrapper2 : public utils::object +class function_wrapper_tcg : public utils::object { public: using user_data_pointer = void*; using c_function_type = ReturnType(Args..., user_data_pointer); using functor_type = std::function; - function_wrapper2() = default; + function_wrapper_tcg() = default; - function_wrapper2(functor_type functor) + function_wrapper_tcg(functor_type functor) : functor_(std::make_unique(std::move(functor))) { } c_function_type* get_c_function() const { - return (c_function_type*)(void*)+[](size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, - size_t a8, size_t a9, size_t a10, size_t a11, size_t a12) -> uint64_t { - size_t real_args[]{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12}; + auto* func = +[](const size_t a1, const size_t a2, const size_t a3, const size_t a4, const size_t a5, + const size_t a6, const size_t a7, const size_t a8, const size_t a9, const size_t a10, + const size_t a11, const size_t a12) -> uint64_t { + const std::array arguments = {a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12}; const auto lambda = +[](Args... args, user_data_pointer user_data) -> ReturnType { return (*static_cast(user_data))(std::forward(args)...); @@ -57,19 +59,21 @@ class function_wrapper2 : public utils::object size_t index = 0; std::tuple func_args{ - resolve_indexed_argument>>(real_args, index)..., - resolve_indexed_argument(real_args, index)}; + resolve_indexed_argument>>(arguments, index)..., + resolve_indexed_argument(arguments, index)}; (void)index; if constexpr (!std::is_void_v) { - return (uint64_t)std::apply(lambda, std::move(func_args)); + return uint64_t(std::apply(lambda, std::move(func_args))); } std::apply(lambda, std::move(func_args)); return 0; }; + + return reinterpret_cast(reinterpret_cast(func)); } void* get_function() const diff --git a/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp b/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp index 97cd07c3..5be03b90 100644 --- a/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp @@ -7,7 +7,7 @@ #include "unicorn_hook.hpp" #include "function_wrapper.hpp" -#include "function_wrapper2.hpp" +#include "function_wrapper_tcg.hpp" #include namespace unicorn @@ -386,7 +386,6 @@ namespace unicorn emulator_hook* hook_instruction(const int instruction_type, instruction_hook_callback callback) override { - unicorn_hook hook{*this}; auto container = std::make_unique(); @@ -400,19 +399,18 @@ namespace unicorn uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN_INVALID, wrapper.get_function(), wrapper.get_user_data(), 0, std::numeric_limits::max())); - container->add(std::move(wrapper), std::move(hook)); - } - else if(inst_type == x64_hookable_instructions::syscall){ - function_wrapper wrapper([c = std::move(callback)](uc_engine*) { - c(); - }); + container->add(std::move(wrapper), std::move(hook)); + } + else if (inst_type == x64_hookable_instructions::syscall) + { + function_wrapper wrapper([c = std::move(callback)](uc_engine*) { c(); }); const auto uc_instruction = map_hookable_instruction(inst_type); uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN, wrapper.get_function(), wrapper.get_user_data(), 0, std::numeric_limits::max(), uc_instruction)); - container->add(std::move(wrapper), std::move(hook)); + container->add(std::move(wrapper), std::move(hook)); } else { @@ -425,7 +423,7 @@ namespace unicorn wrapper.get_user_data(), 0, std::numeric_limits::max(), uc_instruction)); - container->add(std::move(wrapper), std::move(hook)); + container->add(std::move(wrapper), std::move(hook)); } auto* result = container->as_opaque_hook(); @@ -552,7 +550,7 @@ namespace unicorn c(address); // }; - function_wrapper2 wrapper(std::move(exec_wrapper)); + function_wrapper_tcg wrapper(std::move(exec_wrapper)); unicorn_hook hook{*this}; From 8fd6e4fe9e613796447bc367c3ca0b9f21b4ee05 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 07:16:40 +0200 Subject: [PATCH 12/20] Upload page --- .github/workflows/build.yml | 60 ++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c2bc13f..99ca26d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -481,10 +481,10 @@ jobs: arch: ${{matrix.architecture}} script: "adb push build/${{matrix.preset}}/artifacts/* /data/local/tmp && adb shell \"cd /data/local/tmp && export LD_LIBRARY_PATH=. && chmod +x ./analyzer && EMULATOR_ICICLE=${{ matrix.emulator == 'Icicle' }} ./analyzer -e ./root c:/test-sample.exe\"" - page: - name: Page + build-page: + name: Build Page runs-on: ubuntu-latest - #needs: [build] + needs: [create-emulation-root, build] permissions: contents: read pages: write @@ -495,6 +495,58 @@ jobs: with: submodules: recursive + - name: Download Emscripten Artifacts + uses: pyTooling/download-artifact@v4 + with: + name: Emscripten Release Artifacts + path: build/release/artifacts + + - name: Download Windows Artifacts + uses: pyTooling/download-artifact@v4 + with: + name: Windows x86_64 Release Artifacts + path: build/release/artifacts + + - name: Download Emulation Root + uses: pyTooling/download-artifact@v4 + with: + name: Windows 2022 Emulation Root + path: build/release/artifacts/root + + - name: Copy Sample + run: cp ./build/release/artifacts/test-sample.exe build/release/artifacts/root/filesys/c/ + + - name: Create Emulation Root zip + run: zip -r ./page/root.zip ./build/release/artifacts/test-sample.exe build/release/artifacts/root + + - name: Copy Files + run: | + cp ./build/release/artifacts/analyzer.js ./page/ + cp ./build/release/artifacts/analyzer.wasm ./page/ + + - name: Upload Page Artifacts + uses: pyTooling/upload-artifact@v4 + with: + name: Page Artifacts + working-directory: page/ + path: "*" + + deploy-page: + name: Deploy Page + runs-on: ubuntu-latest + needs: [build-page] + #if: github.repository_owner == 'momo5502' && github.event_name == 'push' && github.ref == 'refs/heads/main' + permissions: + contents: read + pages: write + id-token: write + steps: + - name: Download Page Artifacts + uses: pyTooling/download-artifact@v4 + with: + name: Page Artifacts + path: ./page/ + - name: Setup Pages uses: actions/configure-pages@v5 @@ -510,7 +562,7 @@ jobs: summary: name: Pipeline Summary runs-on: ubuntu-24.04 - needs: [clang-tidy, build-apiset-dumper, smoke-test-android, create-emulation-root, build, test, win-test, verify-formatting] + needs: [build-page, clang-tidy, build-apiset-dumper, smoke-test-android, create-emulation-root, build, test, win-test, verify-formatting] if: always() steps: - uses: geekyeggo/delete-artifact@v5 From baa2fc5fa6ee2808ade9a17a13c338e5db2c3417 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 07:57:30 +0200 Subject: [PATCH 13/20] Fix page --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99ca26d8..af27a526 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -517,7 +517,7 @@ jobs: run: cp ./build/release/artifacts/test-sample.exe build/release/artifacts/root/filesys/c/ - name: Create Emulation Root zip - run: zip -r ./page/root.zip ./build/release/artifacts/test-sample.exe build/release/artifacts/root + run: cd ./build/release/artifacts && zip -r "${{github.workspace}}/page/root.zip" ./root - name: Copy Files run: | From 4ac8d853a6b5715fe95900f679305e4d5d4c0312 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 08:15:17 +0200 Subject: [PATCH 14/20] Always use static socket factory for emscripten --- src/windows-emulator-test/emulation_test_utils.hpp | 2 +- .../network}/static_socket_factory.cpp | 0 .../network}/static_socket_factory.hpp | 2 +- src/windows-emulator/windows_emulator.cpp | 6 ++++++ 4 files changed, 8 insertions(+), 2 deletions(-) rename src/{windows-emulator-test => windows-emulator/network}/static_socket_factory.cpp (100%) rename src/{windows-emulator-test => windows-emulator/network}/static_socket_factory.hpp (73%) diff --git a/src/windows-emulator-test/emulation_test_utils.hpp b/src/windows-emulator-test/emulation_test_utils.hpp index a399702c..d972de71 100644 --- a/src/windows-emulator-test/emulation_test_utils.hpp +++ b/src/windows-emulator-test/emulation_test_utils.hpp @@ -4,7 +4,7 @@ #include #include -#include "static_socket_factory.hpp" +#include #define ASSERT_NOT_TERMINATED(win_emu) \ do \ diff --git a/src/windows-emulator-test/static_socket_factory.cpp b/src/windows-emulator/network/static_socket_factory.cpp similarity index 100% rename from src/windows-emulator-test/static_socket_factory.cpp rename to src/windows-emulator/network/static_socket_factory.cpp diff --git a/src/windows-emulator-test/static_socket_factory.hpp b/src/windows-emulator/network/static_socket_factory.hpp similarity index 73% rename from src/windows-emulator-test/static_socket_factory.hpp rename to src/windows-emulator/network/static_socket_factory.hpp index 6f162869..5b27faef 100644 --- a/src/windows-emulator-test/static_socket_factory.hpp +++ b/src/windows-emulator/network/static_socket_factory.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "socket_factory.hpp" namespace network { diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 4cb8b45f..99aef9cf 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -16,6 +16,8 @@ #include "exception_dispatch.hpp" #include "apiset/apiset.hpp" +#include "network/static_socket_factory.hpp" + constexpr auto MAX_INSTRUCTIONS_PER_TIME_SLICE = 100000; namespace @@ -257,7 +259,11 @@ namespace return std::move(interfaces.socket_factory); } +#ifdef OS_EMSCRIPTEN + return network::create_static_socket_factory(); +#else return std::make_unique(); +#endif } } From 31906fef2d896790d5436caeb5394e8700ce8eb8 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 08:30:41 +0200 Subject: [PATCH 15/20] Throw detailed exception --- src/windows-emulator/module/module_mapping.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows-emulator/module/module_mapping.cpp b/src/windows-emulator/module/module_mapping.cpp index 84c3ccd0..8f433809 100644 --- a/src/windows-emulator/module/module_mapping.cpp +++ b/src/windows-emulator/module/module_mapping.cpp @@ -259,7 +259,7 @@ mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path const auto data = utils::io::read_file(file); if (data.empty()) { - throw std::runtime_error("Bad file data"); + throw std::runtime_error("Bad file data: " + file.string()); } return map_module_from_data(memory, data, std::move(file)); From 11a19593d98da6a2cd9158226e3971cb6376157e Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 08:40:22 +0200 Subject: [PATCH 16/20] Load correct sample --- page/emulator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/page/emulator.js b/page/emulator.js index 7a007d5e..04ebf177 100644 --- a/page/emulator.js +++ b/page/emulator.js @@ -11,7 +11,7 @@ function logLine(text) { function runEmulation(filesystem) { globalThis.Module = { - arguments: ["-b", "-c", "-e", "./root", "c:/lul.exe",], + arguments: ["-b", "-c", "-e", "./root", "c:/test-sample.exe",], onRuntimeInitialized: function () { filesystem.forEach(e => { if (e.name.endsWith("/")) { From dda99b4d705f253929e548003cc52216a5690a2e Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 08:56:13 +0200 Subject: [PATCH 17/20] Set min height of the track --- page/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/page/index.html b/page/index.html index 0256f824..0b0f2fae 100644 --- a/page/index.html +++ b/page/index.html @@ -216,6 +216,7 @@ ::-webkit-scrollbar-thumb { background-color: rgba(97, 97, 97, 0.4); border-radius: 20px; + min-height: 50px; border: 6px solid transparent; background-clip: content-box; transition: all 0.1s linear; From 5147e258128f10f3325be26765ea880f8ca1d9ce Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 09:14:57 +0200 Subject: [PATCH 18/20] Cleanup compilation --- cmake/compiler-env.cmake | 3 --- deps/unicorn | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index 5f610950..c5b49138 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -51,9 +51,6 @@ if(UNIX) momo_add_c_and_cxx_compile_options( -fvisibility=hidden -ftrivial-auto-var-init=zero - #-Wbad-function-cast - #-Wcast-function-type - -Wno-int-conversion ) endif() diff --git a/deps/unicorn b/deps/unicorn index 6f2156df..41980a72 160000 --- a/deps/unicorn +++ b/deps/unicorn @@ -1 +1 @@ -Subproject commit 6f2156dfac3abad316a4f02bf609ec1bb700d02e +Subproject commit 41980a72746ae2c995454b465236bcf9ce7c1b71 From 9a2a6de16bc0ed52873811c38b7007359eea23aa Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 09:16:11 +0200 Subject: [PATCH 19/20] Only deploy page on main branch --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index af27a526..a6860204 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -534,8 +534,8 @@ jobs: deploy-page: name: Deploy Page runs-on: ubuntu-latest - needs: [build-page] - #if: github.repository_owner == 'momo5502' && github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: [build-page, summary] + if: github.repository_owner == 'momo5502' && github.event_name == 'push' && github.ref == 'refs/heads/main' permissions: contents: read pages: write From be89ba0c97f869d4999e43bc1dd7e6ba3daed051 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 18 Apr 2025 09:51:57 +0200 Subject: [PATCH 20/20] Fix unicorn --- deps/unicorn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/unicorn b/deps/unicorn index 41980a72..6b329651 160000 --- a/deps/unicorn +++ b/deps/unicorn @@ -1 +1 @@ -Subproject commit 41980a72746ae2c995454b465236bcf9ce7c1b71 +Subproject commit 6b32965144d4ff91eb303beed0ec938ad467f33b