diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..45dbf82 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,8 @@ +--- +name: Bug Report +about: For reporting an encountered issue +title: "[bug] Manufacturer Model" +labels: bug +assignees: '' + +--- diff --git a/.github/ISSUE_TEMPLATE/device-report.md b/.github/ISSUE_TEMPLATE/device-report.md new file mode 100644 index 0000000..14a2485 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/device-report.md @@ -0,0 +1,73 @@ +--- +name: Device Report +about: For reporting operation with a particular device +title: "[device-report] Manufacturer Model" +labels: device-report +assignees: '' + +--- + +## Device Info + +- Sinowealth Device: _example `SH68F90A`_ +- IC Label: _example `BYK916`_ +- Product Page: _example https://nuphy.com/products/air60_ + +## Part Info + +``` +plarform: sh68f90 +vendor_id: 0xdead +product_id: 0xcafe +firmware_size: 61440 # necessary if not default, otherwise remove this line +bootloader_size: 4096 # necessary if not default, otherwise remove this line +page_size: 2048 # necessary if not default, otherwise remove this line +isp_iface_num: 1 # necessary if not default, otherwise remove this line +isp_report_id: 5 # necessary if not default, otherwise remove this line +reboot: false # necessary if not default, otherwise remove this line +``` + +## Operations Tested + +- [ ] Read +- [ ] Write + +## Platforms Tested + +- [ ] linux +- [ ] macos +- [ ] windows + +## Checksums + +- Stock Firmware MD5: `deadbeefdeadbeefdeadbeefdeadbeef` +- Bootloader MD5: `beefcafebeefcafebeefcafebeefcafe` _(shown when running `sinowealth-kb-tool read -s bootloader ...`)_ + +## Device Info (HID Reports) + +Output when running `sinowealth-kb-tool list --vendor_id= --product_id=` + +
+Output + +``` +sinowealth-kb-tool list --vendor_id=0x05ac --product_id=0x024f +ID 05ac:024f manufacturer="contact@carlossless.io" product="SMK Keyboard" + path="DevSrvsID:4294974930" interface_number=0 + report_descriptor=[05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 75 08 95 01 81 01 05 07 19 00 29 FF 15 00 26 FF 00 75 08 95 06 81 00 05 08 19 01 29 05 15 00 25 01 75 01 95 05 91 02 75 03 95 01 91 01 C0] + feature_report_ids=[] + usage_page=0x0001 usage=0x0006 + path="DevSrvsID:4294974929" interface_number=1 + report_descriptor=[05 01 09 80 A1 01 85 01 19 81 29 83 15 00 25 01 75 01 95 03 81 02 95 05 81 01 C0 05 0C 09 01 A1 01 85 02 19 00 2A 3C 02 15 00 26 3C 02 75 10 95 01 81 00 C0 06 00 FF 09 01 A1 01 85 05 19 01 29 02 15 00 26 FF 00 75 08 95 05 B1 02 C0 05 01 09 06 A1 01 85 06 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 05 07 19 00 29 9F 15 00 25 01 75 01 95 A0 81 02 C0] + feature_report_ids=[5] + usage_page=0x0001 usage=0x0006 + usage_page=0x0001 usage=0x0080 + usage_page=0x000c usage=0x0001 + usage_page=0xff00 usage=0x0001 +``` + +
+ +## PCB Photos + +_If possible, include photos of your device PCB clearly showing MCU and wireless IC labels_ diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 4f203bc..d1d95dc 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,19 +1,142 @@ +name: Test & Build + on: [push] -name: CI +env: + CARGO_TERM_COLOR: always + +defaults: + run: + # necessary for windows + shell: bash jobs: - build_and_test: - name: Rust project + nix-build: + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: cachix/install-nix-action@v31 + with: + github_access_token: ${{ secrets.GITHUB_TOKEN }} + - uses: cachix/cachix-action@v14 + with: + name: sinowealth-kb-tool + authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} + - name: Build + run: nix build + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cargo cache + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ./target + key: test-cargo-registry + - name: Lint + run: cargo fmt -- --check + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cargo cache + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ./target + key: test-cargo-registry + - name: Install and configure dependencies + run: | + sudo apt-get install -qq libusb-1.0.0-dev + - name: Run tests + run: cargo test --bins --verbose + + build: + strategy: + fail-fast: false + matrix: + include: + - TARGET: x86_64-unknown-linux-gnu + OS: ubuntu-latest + - TARGET: x86_64-apple-darwin + OS: macos-latest + - TARGET: x86_64-pc-windows-msvc + OS: windows-latest + needs: test + runs-on: ${{ matrix.OS }} + env: + NAME: sinowealth-kb-tool + TARGET: ${{ matrix.TARGET }} + OS: ${{ matrix.OS }} + steps: + - uses: actions/checkout@v4 + - name: Cargo cache + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ./target + key: build-cargo-registry-${{matrix.TARGET}} + - name: Install and configure dependencies + run: | + # dependencies are only needed on ubuntu as that's the only place where + # we make cross-compilation + if [[ $OS =~ ^ubuntu.*$ ]]; then + sudo apt-get install -qq libusb-1.0-0-dev + fi + - name: Install rust target + run: rustup target add $TARGET + - name: Run build + run: cargo build --release --verbose --target $TARGET + - name: Compress + run: | + mkdir -p ./artifacts + # windows is the only OS using a different convention for executable file name + if [[ $OS =~ ^windows.*$ ]]; then + EXEC=$NAME.exe + else + EXEC=$NAME + fi + if [[ $GITHUB_REF_TYPE =~ ^tag$ ]]; then + TAG=$GITHUB_REF_NAME + else + TAG=$GITHUB_SHA + fi + mv ./target/$TARGET/release/$EXEC ./$EXEC + tar -czf ./artifacts/$NAME-$TARGET-$TAG.tar.gz $EXEC + - name: Archive artifact + uses: actions/upload-artifact@v4 + with: + name: result-${{ matrix.TARGET }} + path: | + ./artifacts + + release: + if: startsWith(github.ref, 'refs/tags/v') + needs: build runs-on: ubuntu-latest + permissions: + contents: write steps: - - uses: actions/checkout@v2 - - name: Install libudev - run: sudo apt-get install -y libudev-dev - - uses: actions-rs/toolchain@v1 + - name: Download artifacts + uses: actions/download-artifact@v4 with: - toolchain: stable - - uses: actions-rs/cargo@v1 + pattern: result-* + merge-multiple: true + path: ./artifacts + - name: Release + uses: softprops/action-gh-release@v2 with: - command: build - args: --release --all-features + draft: true + generate_release_notes: true + files: ./artifacts/*.tar.gz diff --git a/.gitignore b/.gitignore index 3129e44..b2f4c9f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ .DS_Store -/.direnv/ +/.direnv +/result /private - /target + +*.hex diff --git a/Cargo.lock b/Cargo.lock index c73798f..ddb41f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,164 +2,424 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" -version = "0.2.6" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", + "anstyle-query", "anstyle-wincon", - "concolor-override", - "concolor-query", - "is-terminal", + "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "0.3.5" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.1.1" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "anstyle-wincon" -version = "0.2.0" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", - "windows-sys 0.45.0", + "once_cell_polyfill", + "windows-sys 0.61.2", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anyhow" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" + +[[package]] +name = "assert_cmd" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "9c5bcfa8749ac45dd12cb11055aeeb6b27a3895560d60d71e3c23bf979e60514" dependencies = [ - "hermit-abi 0.1.19", + "anstyle", + "bstr", "libc", - "winapi", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", ] +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + [[package]] name = "bitflags" -version = "1.3.2" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "cc" -version = "1.0.79" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] [[package]] name = "clap" -version = "4.2.1" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" +checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806" dependencies = [ "clap_builder", ] +[[package]] +name = "clap-num" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822c4000301ac390e65995c62207501e3ef800a1fc441df913a5e8e4dc374816" +dependencies = [ + "num-traits", +] + [[package]] name = "clap_builder" -version = "4.2.1" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" +checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2" dependencies = [ "anstream", "anstyle", - "bitflags", "clap_lex", "strsim", ] [[package]] name = "clap_lex" -version = "0.4.1" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" + +[[package]] +name = "colorchoice" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "colored" -version = "2.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "atty", - "lazy_static", - "winapi", + "windows-sys 0.61.2", ] [[package]] -name = "concolor-override" -version = "1.0.0" +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "concolor-query" -version = "0.3.3" +name = "deranged" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "dialoguer" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" dependencies = [ - "windows-sys 0.45.0", + "console", + "shell-words", + "tempfile", + "thiserror 1.0.69", + "zeroize", ] +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" -version = "0.3.1" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "float-cmp" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" dependencies = [ - "cc", + "num-traits", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hidapi" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "565dd4c730b8f8b2c0fb36df6be12e5470ae10895ddcc4e9dcfbfb495de202b0" dependencies = [ + "cc", + "cfg-if", "libc", + "pkg-config", + "windows-sys 0.48.0", +] + +[[package]] +name = "hidparser" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb8ae90b8d0165be79ff98d845bebbbc9dfa0295ff2ce86beba525d93b9ba60" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", ] [[package]] -name = "hermit-abi" -version = "0.3.1" +name = "id-arena" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "ihex" @@ -168,98 +428,182 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2" [[package]] -name = "ihex_ext" -version = "1.0.0" +name = "indexmap" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96571d3f3e7bd5b9b0bb5de815243e8caf38f5bf40b52e023d61037ed2ec717d" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ - "ihex", - "log", - "thiserror", + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] -name = "io-lifetimes" -version = "1.0.10" +name = "indicatif" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", ] [[package]] -name = "is-terminal" -version = "0.4.7" +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys 0.48.0", + "either", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "js-sys" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +dependencies = [ + "once_cell", + "wasm-bindgen", +] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "leb128fmt" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] -name = "libusb1-sys" -version = "0.6.4" +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "lock_api" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", + "scopeguard", ] [[package]] -name = "linux-raw-sys" -version = "0.3.1" +name = "log" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] -name = "log" -version = "0.4.17" +name = "md5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "cfg-if", + "autocfg", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ + "cfg-if", "libc", + "redox_syscall", + "smallvec", + "windows-link", ] [[package]] name = "phf" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", @@ -267,9 +611,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand", @@ -277,50 +621,120 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "phf_shared" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "predicates" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" + +[[package]] +name = "predicates-tree" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -337,78 +751,240 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] -name = "rusb" -version = "0.9.2" +name = "redox_syscall" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44a8c36914f9b1a3be712c1dfa48c9b397131f9a75707e570a391735f785c5d1" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "libc", - "libusb1-sys", + "bitflags", ] +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" + [[package]] name = "rustix" -version = "0.37.11" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scc" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" +dependencies = [ + "sdd", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" -version = "1.0.159" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serial_test" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" +dependencies = [ + "futures-executor", + "futures-util", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shell-words" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simple_logger" -version = "4.1.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78beb34673091ccf96a8816fce8bfd30d1292c7621ca2bcb5f2ba0fae4f558d" +checksum = "291bee647ce7310b0ea721bfd7e0525517b4468eb7c7e15eb8bd774343179702" dependencies = [ - "atty", "colored", "log", "time", - "windows-sys 0.42.0", + "windows-sys 0.61.2", ] [[package]] name = "sinowealth-kb-tool" -version = "0.0.1" +version = "1.0.1" dependencies = [ + "assert_cmd", + "chrono", "clap", + "clap-num", + "dialoguer", + "hidapi", + "hidparser", "ihex", - "ihex_ext", + "indicatif", + "itertools", "log", + "md5", "phf", - "rusb", + "predicates", + "serial_test", "simple_logger", + "stdext", + "thiserror 2.0.18", ] [[package]] name = "siphasher" -version = "0.3.10" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stdext" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "4af28eeb7c18ac2dbdb255d40bee63f203120e1db6b0024b177746ebec7049c1" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" dependencies = [ "proc-macro2", "quote", @@ -416,127 +992,294 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.13" +name = "tempfile" +version = "3.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn", ] [[package]] name = "time" -version = "0.3.20" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ + "deranged", "itoa", "libc", + "num-conv", "num_threads", - "serde", + "powerfmt", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.8" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ + "num-conv", "time-core", ] [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "wait-timeout" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] [[package]] -name = "vcpkg" -version = "0.2.15" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] [[package]] -name = "winapi" -version = "0.3.9" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "wit-bindgen", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "wasm-bindgen" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "wasm-bindgen-macro" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] [[package]] -name = "windows-sys" -version = "0.42.0" +name = "wasm-bindgen-shared" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "unicode-ident", ] [[package]] -name = "windows-sys" -version = "0.45.0" +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-targets 0.42.2", + "windows-link", ] [[package]] @@ -545,119 +1288,244 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +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 = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index 8cf8f88..cdbad29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,23 +1,46 @@ [package] name = "sinowealth-kb-tool" -version = "0.0.1" +description = """ +A utility for reading and writing flash contents on Sinowealth 8051-based HID devices through the commonly found ISP bootloader +""" +repository = "https://github.com/carlossless/sinowealth-kb-tool" +version = "1.0.1" edition = "2021" license = "MIT" +rust-version = "1.88" [dependencies] clap = "4.1" -rusb = "0.9" +clap-num = "1.0" +dialoguer = "0.11.0" +hidparser = "1.0.3" ihex = "3.0" -ihex_ext = "1.0" +indicatif = "0.17.11" +itertools = "0.14.0" +md5 = "0.7" +thiserror = "2.0" + +[dependencies.hidapi] +version = "2.6" +default-features = false +features = ["linux-static-libusb"] [dependencies.log] version = "0.4" -features = ["max_level_debug", "release_max_level_info"] +features = ["max_level_debug"] [dependencies.simple_logger] -version = "4.1" -features = ["stderr", "colors"] +version = "5.1" +default-features = false +features = ["stderr", "colors", "timestamps"] [dependencies.phf] version = "0.11" features = ["macros"] + +[dev-dependencies] +assert_cmd = "2.0.17" +chrono = "0.4.41" +predicates = "3.1.3" +serial_test = "3.2.0" +stdext = "0.3.3" diff --git a/README.md b/README.md index a46240a..52317c2 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,164 @@ # sinowealth-kb-tool -A utility for reading and writing flash contents on Sinowealth 8051-based devices (keyboards and mice) since they all seem to have similar ISP bootloaders. +[![crate](https://img.shields.io/crates/v/sinowealth-kb-tool.svg)](https://crates.io/crates/sinowealth-kb-tool) [![ci](https://github.com/carlossless/sinowealth-kb-tool/actions/workflows/push.yml/badge.svg)](https://github.com/carlossless/sinowealth-kb-tool/actions/workflows/push.yml) + +A utility for reading and writing flash contents on Sinowealth 8051-based USB HID devices (keyboards and mice) through the commonly found ISP bootloader. ## Disclaimer -This is an experimental tool, so use it at your own risk. +I offer no guarantees that using this tool won't brick your device. Use this tool at your risk. + +## Usage + +### Reading + +⚠️ A read operation will set an LJMP (0x02) opcode at address `` if it's not already present there. When this opcode is set, the bootloader considers the main firmware enabled and jumps to it when the device is powered on. This opcode should already be set on most devices and therefore the read operation **should** not cause any issues. + +⚠️ During reading the ISP bootloader will redirect values in `0x0001 - 0x0002` to ` - `. Because of this, the produced payload will be different from how memory is actually laid out in the MCU flash. + +```sh +# reads firmware excluding isp bootloader +sinowealth-kb-tool read -d nuphy-air60 foobar.hex + +# reads only isp bootloader section +sinowealth-kb-tool read -d nuphy-air60 -s bootloader bootloader.hex + +# full dump including firmware and bootloader +sinowealth-kb-tool read -d nuphy-air60 -s full full.hex + +# custom device +sinowealth-kb-tool read \ + --platform sh68f90 \ + --vendor_id 0x05ac \ + --product_id 0x024f \ + --firmware_size 61440 \ # optional + --bootloader_size 4096 \ # optional + --page_size 2048 \ # optional + --isp_iface_num 1 \ # optional + --isp_report_id 5 \ # optional + --reboot false \ # optional + foobar.hex +``` + +### Writing + +⚠️ Same as the [read](#reading) operation, the ISP bootloader will write values meant for addresses `0x0001-0x0002` to ` - `. + +```sh +# overwrites firmware (does not touch the bootloader section) +sinowealth-kb-tool write -p nuphy-air60 foobar.hex + +# custom device +sinowealth-kb-tool write \ + --platform sh68f90 \ + --vendor_id 0x05ac \ + --product_id 0x024f \ + --firmware_size 61440 \ # optional + --bootloader_size 4096 \ # optional + --page_size 2048 \ # optional + --isp_iface_num 1 \ # optional + --isp_report_id 5 \ # optional + --reboot false \ # optional + foobar.hex +``` ## Supported Hardware -| Keyboard | ISP MD5 | MCU | Supported | -| -------- | ------- | --- | --------- | -| [NuPhy Air60](https://nuphy.com/products/air60) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A (labeled as BYK916) | ✅ | -| Xinmeng K916 | unknown | SH68F90 | ❓ | +### Keyboards + +| Model | ISP MD5 | MCU | MCU Label | Tested Read | Tested Write | +| ----- | ------- | --- | --------- | ----------- | ------------ | +| [Aula F75](https://www.aulastar.com/gaming-keyboard/176.html) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [Aula F87](https://www.aulastar.com/index.php/gaming-keyboard/157.html) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| Deltaco Gaming WK95R | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | BYK916 | ✅ | ✅ | +| Digital Alliance Meca Warrior X | 2d169670eae0d36eae8188562c1f66e8 | SH68F90 | SH68F90S | ✅ | ✅ | +| E-Yooso Z11 | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90? | BYK901 | ✅ | ✅ | +| E-Yooso Z82 | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [Genesis Thor 300 RGB](https://genesis-zone.com/product/thor-300-rgb-brown) | 2d169670eae0d36eae8188562c1f66e8 | SH68F90 | SH68F90S | ✅ | ✅ | +| [Genesis Thor 300](https://genesis-zone.com/product/thor-300-outemu-blue) | e57490acebcaabfcff84a0ff013955d9 | SH68F881 | SH68F881W | ✅ | ✅ | +| [Kzzi K68Pro](http://en.kzzi.com/product/37/) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | ❓ | ✅ | ✅ | +| Hykker X Range 2017 (RE-K70-BYK800) | 13df4ce2933f9654ffef80d6a3c27199 | SH68F881 | BYK801 | ✅ | ❓ | +| [Leobog Hi75](https://leobogtech.com/products/leobog-hi75) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [Machenike K500-B61](https://global.machenike.com/products/k500-b61) | 2d169670eae0d36eae8188562c1f66e8 | SH68F90? | BYK916 | ✅ | ✅ | +| [MageGee MK-STAR61](https://www.magegee.com/products2.html?pid=1644595&_t=1737191677) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [NuPhy Air60](https://nuphy.com/products/air60) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [NuPhy Air75](https://nuphy.com/products/air75) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [NuPhy Air96](https://nuphy.com/products/air96-wireless-mechanical-keyboard) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [NuPhy Halo65](https://nuphy.com/products/halo65) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [Portronics Hydra 10](https://www.portronics.com/products/hydra-10) | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | BYK916 | ✅ | ✅ | +| [Redragon K530 Draconic PRO](https://www.redragonzone.com/products/draconic-k530) | cfc8661da8c9d7e351b36c0a763426aa | SH68F90A | BYK916 | ✅ | ✅ | +| [Redragon K630 Single LED version](https://www.redragonzone.com/products/redragon-k630-gaming-mechanical-keyboard) | cfc8661da8c9d7e351b36c0a763426aa | SH68F90A | SH68F90AU | ✅ | ✅ | +| [Redragon K614 Anivia 60%](https://www.redragonzone.com/products/redragon-k614-anivia-60-ultra-thin-wired-mechanical-keyboard) | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | BYK916 | ✅ | ✅ | +| [Redragon K617 FIZZ 60%](https://www.redragonzone.com/collections/keyboard/products/redragon-k617-fizz-60-wired-rgb-gaming-keyboard-61-keys-compact-mechanical-keyboard) | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | BYK916 | ✅ | ✅ | +| [Redragon K618](https://www.redragonzone.com/products/redragon-k618-horus-wireless-rgb-mechanical-keyboard) | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | BYK916 | ✅ | ✅ | +| [Redragon K633 RYZE](https://www.redragonzone.com/products/redragon-k633-ryze-rgb-led-backlit-mechanical-gaming-keyboard-with-68-professional-keys-linear-red-switches) | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | BYK916 | ✅ | ✅ | +| [Redragon K641 SHACO PRO](https://www.redragonzone.com/products/redragon-k641-shaco-pro-65-aluminum-rgb-mechanical-keyboard) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [Redragon K652 PRO](https://www.redragonzone.com/products/redragon-k652-75-wireless-rgb-keyboard) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | ❓ | ✅ | ✅ | +| [Redragon K658 PRO SE](https://www.redragonzone.com/products/k658-pro-se-90-wireless-rgb-gaming-keyboard) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| [Royal Kludge RK100](http://en.rkgaming.com/product/14/) | cfc8661da8c9d7e351b36c0a763426aa | SH68F90? | BYK916 | ✅ | ✅ | +| [Royal Kludge RK61](http://en.rkgaming.com/product/11/) | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90? | BYK916 | ✅ | ✅ | +| Royal Kludge RK68 BT Dual | cfc8661da8c9d7e351b36c0a763426aa | SH68F90? | BYK901 | ✅ | ✅ | +| Royal Kludge RK68 ISO Return | ❓ | SH68F90? | BYK916 | ✅ | ❓ | +| [Royal Kludge RK71](http://en.rkgaming.com/product/12/) | cfc8661da8c9d7e351b36c0a763426aa | SH68F90? | ❓ | ✅ | ✅ | +| [Royal Kludge RK84](http://en.rkgaming.com/product/16/) | cfc8661da8c9d7e351b36c0a763426aa | SH68F90? | BYK916 | ✅ | ✅ | +| Royal Kludge RKG68 | cfc8661da8c9d7e351b36c0a763426aa | SH68F90A | SH68F90AS | ✅ | ✅ | +| Terport TR95 | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | BYK916 | ✅ | ✅ | +| Weikav Sugar65 | 2d169670eae0d36eae8188562c1f66e8 | SH68F90 | SH68F90S | ✅ | ✅ | +| Xinmeng K916 | cfc8661da8c9d7e351b36c0a763426aa | SH68F90 | ❓ | ✅ | ✅ | +| Xinmeng M66 | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | SH68F90AS | ✅ | ✅ | +| Xinmeng M71 | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | SH68F90AS | ✅ | ✅ | +| Xinmeng XM-RF68 | 2d169670eae0d36eae8188562c1f66e8 | SH68F90 | SH68F90U | ✅ | ✅ | +| Yinren R108 | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | BYK916 | ✅ | ✅ | +| Yunzii AL66 | 3e0ebd0c440af5236d7ff8872343f85d | SH68F90A | SH68F90AS | ✅ | ✅ | +| Yunzii AL71 | 2d169670eae0d36eae8188562c1f66e8 | SH68F90A | SH68F90AS | ✅ | ✅ | +| Dierya DK68SE | e611dacbc710b758a6fbcc3bcc648b7b | SH68F90A | BYK903 | ✅ | ✅ | + +### Mice + +| Model | ISP MD5 | MCU | MCU Label | Tested Read | Tested Write | +| ----- | ------- | --- | --------- | ----------- | ------------ | +| [Glorious Model O](https://web.archive.org/web/20220609205659mp_/https://www.gloriousgaming.com/products/glorious-model-o-black) | 46459c31e58194fa076b8ce8fb1f3eaa | SH68F89 | BY8948 | ✅ | ❓ | +| [Trust GXT 960](https://www.trust.com/en/product/23758-gxt-960-graphin-ultra-lightweight-gaming-mouse) | 620f0b67a91f7f74151bc5be745b7110 | ❓ | BY8801 | ✅ | ❓ | + +## Bootloader Support + +### Platforms + +| ISP MD5 | Windows | macOS | Linux | +| -------------------------------- | -------- | -------- | ----- | +| 13df4ce2933f9654ffef80d6a3c27199 | ? | ? | ok | +| 2d169670eae0d36eae8188562c1f66e8 | ok | ? | ok | +| 3e0ebd0c440af5236d7ff8872343f85d | ok | ok | ok | +| 46459c31e58194fa076b8ce8fb1f3eaa | ? | ? | ok | +| 620f0b67a91f7f74151bc5be745b7110 | ? | fail[^1] | ok | +| cfc8661da8c9d7e351b36c0a763426aa | ok | fail[^1] | ok | +| e57490acebcaabfcff84a0ff013955d9 | ok | fail[^1] | ok | + +[^1]: macOS does not recognize the composite device as an HID device + +## Prerequisites + +### Linux + +To enable running this tool without superuser privileges add the following udev rule with `xxxx` and `yyyy` replaced with your device Vendor ID and Product ID respectively. + +```udev +# /etc/udev/rules.d/plugdev.rules +SUBSYSTEMS=="usb", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", MODE="0660", GROUP="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0603", ATTRS{idProduct}=="1020", MODE="0660", GROUP="plugdev" +``` + +Make sure your user is part of the `plugdev` group. + +### macOS + +If you encounter errors like: +``` +hid_open_path: failed to open IOHIDDevice from mach entry... +``` + +Ensure that your terminal application has [access to input monitoring](https://support.apple.com/guide/mac-help/control-access-to-input-monitoring-on-mac-mchl4cedafb6/mac). ## Acknowledgments -* https://github.com/gashtaan/sinowealth-8051-dumper -* https://github.com/ayufan-rock64/pinebook-pro-keyboard-updater +Thanks to [@gashtaan](https://github.com/gashtaan) for analyzing and explaining the inner workings of the ISP bootloaders. Without his help, this tool wouldn't be here! diff --git a/flake.lock b/flake.lock index 0284c6a..72b1f88 100644 --- a/flake.lock +++ b/flake.lock @@ -1,41 +1,135 @@ { "nodes": { - "flake-utils": { + "fenix": { "inputs": { - "systems": "systems" + "nixpkgs": [ + "naersk", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "lastModified": 1752475459, + "narHash": "sha256-z6QEu4ZFuHiqdOPbYss4/Q8B0BFhacR8ts6jO/F/aOU=", + "owner": "nix-community", + "repo": "fenix", + "rev": "bf0d6f70f4c9a9cf8845f992105652173f4b617f", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "naersk": { + "inputs": { + "fenix": "fenix", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1763384566, + "narHash": "sha256-r+wgI+WvNaSdxQmqaM58lVNvJYJ16zoq+tKN20cLst4=", + "owner": "nix-community", + "repo": "naersk", + "rev": "d4155d6ebb70fbe2314959842f744aa7cabbbf6a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "naersk", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1682109806, - "narHash": "sha256-d9g7RKNShMLboTWwukM+RObDWWpHKaqTYXB48clBWXI=", + "lastModified": 1752077645, + "narHash": "sha256-HM791ZQtXV93xtCY+ZxG1REzhQenSQO020cu6rHtAPk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "be9e214982e20b8310878ac2baa063a961c1bdf6", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1766201043, + "narHash": "sha256-eplAP+rorKKd0gNjV3rA6+0WMzb1X1i16F5m5pASnjA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2362848adf8def2866fabbffc50462e929d7fffb", + "rev": "b3aad468604d3e488d627c0b43984eb60e75e782", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "NixOS", + "ref": "nixos-25.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, "root": { "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" + "naersk": "naersk", + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay", + "utils": "utils" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1752428706, + "narHash": "sha256-EJcdxw3aXfP8Ex1Nm3s0awyH9egQvB2Gu+QEnJn2Sfg=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "591e3b7624be97e4443ea7b5542c191311aa141d", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1766285238, + "narHash": "sha256-DqVXFZ4ToiFHgnxebMWVL70W+U+JOxpmfD37eWD/Qc8=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "c4249d0c370d573d95e33b472014eae4f2507c2f", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" } }, "systems": { @@ -52,6 +146,24 @@ "repo": "default", "type": "github" } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 77f72af..fd1bd40 100644 --- a/flake.nix +++ b/flake.nix @@ -1,12 +1,71 @@ { - inputs.flake-utils.url = "github:numtide/flake-utils"; - - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem - (system: - let pkgs = nixpkgs.legacyPackages.${system}; in - { - devShells.default = import ./shell.nix { inherit pkgs; }; - } - ); -} \ No newline at end of file + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + utils.url = "github:numtide/flake-utils"; + naersk.url = "github:nix-community/naersk"; + rust-overlay.url = "github:oxalica/rust-overlay"; + }; + + outputs = { self, nixpkgs, utils, naersk, rust-overlay }: + utils.lib.eachDefaultSystem ( + system: + let + overlays = [ (import rust-overlay) ]; + + pkgs = import nixpkgs { + inherit system overlays; + }; + + toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + + naersk' = pkgs.callPackage naersk { + cargo = toolchain; + rustc = toolchain; + clippy = toolchain; + }; + + buildInputs = with pkgs; [ + pkg-config + libusb1 + binutils + ] ++ + (lib.optionals (stdenv.hostPlatform.isLinux) [ + udev + ]) ++ + (lib.optionals (stdenv.hostPlatform.isDarwin) [ + apple-sdk + iconv + ]); + in + { + formatter = pkgs.nixpkgs-fmt; + + packages = { + # For `nix build` `nix run`, & `nix profile install`: + default = naersk'.buildPackage { + pname = "sinowealth-kb-tool"; + version = "latest"; + + src = ./.; + + doCheck = false; # integration tests from running since they require an attached specific device + + inherit buildInputs; + + meta = with pkgs.lib; { + description = "A utility for reading and writing flash contents on Sinowealth 8051-based devices"; + homepage = "https://github.com/carlossless/sinowealth-kb-tool"; + license = licenses.mit; + mainProgram = "sinowealth-kb-tool"; + maintainers = with maintainers; [ carlossless ]; + }; + }; + }; + + devShells.default = pkgs.mkShell { + inherit buildInputs; + nativeBuildInputs = with pkgs; [ rustup toolchain ]; + }; + } + ); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..bc2947d --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,11 @@ +[toolchain] +channel = "1.88" +components = [ + "rustfmt", + "rustc", + "rust-src", + "rust-analyzer", + "cargo", + "clippy", +] +profile = "minimal" diff --git a/shell.nix b/shell.nix deleted file mode 100644 index 233c23f..0000000 --- a/shell.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ pkgs ? import { } }: -with pkgs; -mkShell { - buildInputs = [ - rustc - cargo - ] ++ - (lib.optionals (stdenv.hostPlatform.isLinux) [ - udev - pkg-config - ]) ++ - (lib.optionals (stdenv.hostPlatform.isDarwin) [ - darwin.apple_sdk.frameworks.IOKit - darwin.apple_sdk.frameworks.AppKit - iconv - ]); - - shellHook = '' - echo "Entered the dev shell! $(rustc --version) $(cargo --version)" - ''; -} diff --git a/src/device_selector.rs b/src/device_selector.rs new file mode 100644 index 0000000..8ea3542 --- /dev/null +++ b/src/device_selector.rs @@ -0,0 +1,524 @@ +use core::time; +use std::{ffi::CStr, thread, time::Duration}; + +use hidapi::{BusType, DeviceInfo, HidDevice, HidError, MAX_REPORT_DESCRIPTOR_SIZE}; +use hidparser::parse_report_descriptor; +use indicatif::ProgressBar; +use itertools::Itertools; +use log::{debug, error, info}; +use thiserror::Error; + +use crate::{ + hid_tree::{DeviceNode, InterfaceNode}, + is_expected_error, DeviceSpec, ISPDevice, +}; + +#[cfg(any(target_os = "macos", target_os = "windows"))] +use crate::hid_tree::ItemNode; + +const REPORT_ID_ISP: u8 = 0x05; +const CMD_ISP_MODE: u8 = 0x75; + +const REPORT_ID_XFER: u8 = 0x06; + +const GAMING_KB_VENDOR_ID: u16 = 0x0603; +const GAMING_KB_PRODUCT_ID: u16 = 0x1020; +const GAMING_KB_V2_PRODUCT_ID: u16 = 0x1021; +const GAMING_KB_IFACE: i32 = 0; + +const COMMAND_LENGTH: usize = 6; + +#[derive(Debug, Error)] +pub enum DeviceSelectorError { + #[error("Device not found")] + NotFound, + #[error(transparent)] + HidError(#[from] HidError), + #[error("Failed to parse report descriptor {0:?}")] + ReportDescriptorError(hidparser::report_descriptor_parser::ReportDescriptorError), + #[error("Unexpected device count")] + UnexpectedDeviceCount, +} + +pub struct DeviceSelector { + api: hidapi::HidApi, +} + +impl DeviceSelector { + pub fn new() -> Result { + let api = hidapi::HidApi::new().map_err(DeviceSelectorError::from)?; + + #[cfg(target_os = "macos")] + api.set_open_exclusive(false); // macOS will throw a privilege violation error otherwise + + Ok(Self { api }) + } + + fn sorted_usb_device_list(&self) -> Vec<&DeviceInfo> { + let mut devices: Vec<_> = self + .api + .device_list() + .filter(|d| d.bus_type() as u32 == BusType::Usb as u32) + .collect(); + // TODO: move out the platform specific sorting + devices.sort_by_key(|d| { + #[cfg(not(target_os = "linux"))] + return ( + d.vendor_id(), + d.product_id(), + d.interface_number(), + d.path(), + d.usage_page(), + d.usage(), + ); + #[cfg(target_os = "linux")] + return ( + d.vendor_id(), + d.product_id(), + d.interface_number(), + d.path(), + ); + }); + devices + } + + fn unique_usb_device_list(&self) -> Vec<&DeviceInfo> { + let mut devices: Vec<_> = self.sorted_usb_device_list(); + devices.dedup_by_key(|d| { + ( + d.vendor_id(), + d.product_id(), + d.interface_number(), + d.path(), + ) + }); + devices + } + + fn get_feature_report_ids_from_path( + &self, + path: &CStr, + ) -> Result, DeviceSelectorError> { + let dev = self + .api + .open_path(path) + .map_err(DeviceSelectorError::from)?; + self.get_feature_report_ids_from_device(&dev) + } + + fn get_feature_report_ids_from_device( + &self, + dev: &HidDevice, + ) -> Result, DeviceSelectorError> { + let mut buf: [u8; MAX_REPORT_DESCRIPTOR_SIZE] = [0; MAX_REPORT_DESCRIPTOR_SIZE]; + let size: usize = dev + .get_report_descriptor(&mut buf) + .map_err(DeviceSelectorError::from)?; + let descriptor = buf[..size].to_vec(); + self.get_feature_report_ids_from_descriptor(&descriptor) + } + + fn get_feature_report_ids_from_descriptor( + &self, + descriptor: &[u8], + ) -> Result, DeviceSelectorError> { + let report_descriptor = parse_report_descriptor(descriptor) + .map_err(DeviceSelectorError::ReportDescriptorError)?; + let res = report_descriptor + .features + .iter() + .filter_map(|item| item.report_id) + .map(|report_id| report_id.into()) + .collect(); + Ok(res) + } + + fn get_report_descriptor(&self, dev: &HidDevice) -> Result, DeviceSelectorError> { + let mut buf: [u8; MAX_REPORT_DESCRIPTOR_SIZE] = [0; MAX_REPORT_DESCRIPTOR_SIZE]; + let size: usize = dev + .get_report_descriptor(&mut buf) + .map_err(DeviceSelectorError::from)?; + Ok(buf[..size].to_vec()) + } + + fn get_descriptor_with_features( + &self, + path: &CStr, + ) -> ( + Result, DeviceSelectorError>, + Result, DeviceSelectorError>, + ) { + let descriptor: Result, DeviceSelectorError>; + let feature_report_ids: Result, DeviceSelectorError>; + match self.api.open_path(path) { + Ok(ref dev) => { + descriptor = self.get_report_descriptor(dev); + match descriptor { + Ok(ref report) => { + feature_report_ids = self.get_feature_report_ids_from_descriptor(report); + } + Err(_) => { + feature_report_ids = Err(DeviceSelectorError::NotFound); + } + } + } + Err(err) => { + descriptor = Err(DeviceSelectorError::from(err)); + feature_report_ids = Err(DeviceSelectorError::NotFound); + } + } + (descriptor, feature_report_ids) + } + + #[cfg(target_os = "windows")] + fn get_devices_for_report_ids<'a, I: IntoIterator>( + &self, + devices: I, + report_ids: &[u32], + ) -> Result, DeviceSelectorError> { + let mut matched_devices: Vec> = vec![None; report_ids.len()]; + + for d in devices { + let retrieved_ids = self.get_feature_report_ids_from_path(d.path())?; + for id in retrieved_ids { + for (i, expected_id) in report_ids.iter().enumerate() { + if id == *expected_id { + if matched_devices[i].is_some() { + return Err(DeviceSelectorError::UnexpectedDeviceCount); + } + matched_devices[i] = Some(d); + } + } + } + } + + if matched_devices.iter().all(|d| d.is_some()) { + let matched_devices: Vec<&DeviceInfo> = + matched_devices.into_iter().map(|d| d.unwrap()).collect(); + Ok(matched_devices) + } else { + Err(DeviceSelectorError::NotFound) + } + } + + #[cfg(any(target_os = "macos", target_os = "linux"))] + fn get_device_for_report_ids<'a, I: IntoIterator>( + &self, + devices: I, + report_ids: &[u32], + ) -> Result<&'a DeviceInfo, DeviceSelectorError> { + let mut matching_devices = vec![]; + + for d in devices { + let retrieved_ids = self.get_feature_report_ids_from_path(d.path())?; + if report_ids.iter().all(|id| retrieved_ids.contains(id)) { + matching_devices.push(d); + } + } + + match matching_devices.len() { + 1 => Ok(matching_devices[0]), + len if len > 1 => Err(DeviceSelectorError::UnexpectedDeviceCount), + _ => Err(DeviceSelectorError::NotFound), + } + } + + fn find_isp_device(&self, device_spec: DeviceSpec) -> Result { + let sorted_devices = self.unique_usb_device_list(); + let isp_devices: Vec<_> = sorted_devices + .clone() + .into_iter() + .filter(|d| { + d.vendor_id() == GAMING_KB_VENDOR_ID + && matches!( + d.product_id(), + GAMING_KB_PRODUCT_ID | GAMING_KB_V2_PRODUCT_ID + ) + && d.interface_number() == GAMING_KB_IFACE + }) + .collect(); + + let device_count = isp_devices.len(); + if device_count == 0 { + return Err(DeviceSelectorError::NotFound); + } + + #[cfg(any(target_os = "macos", target_os = "linux"))] + return { + let device = self.get_device_for_report_ids( + isp_devices.clone(), + &[REPORT_ID_ISP as u32, REPORT_ID_XFER as u32], + )?; + debug!("ISP device: {}", device.info()); + + let handle = self + .api + .open_path(device.path()) + .map_err(DeviceSelectorError::from)?; + + Ok(ISPDevice::new(device_spec, handle)) + }; + + #[cfg(target_os = "windows")] + return { + let devices = self.get_devices_for_report_ids( + isp_devices.clone(), + &[REPORT_ID_ISP as u32, REPORT_ID_XFER as u32], + )?; + + let cmd_device = devices[0]; + debug!("ISP CMD device: {}", cmd_device.info()); + + let xfer_device = devices[1]; + debug!("ISP XFER device: {}", xfer_device.info()); + + let cmd_handle = self + .api + .open_path(cmd_device.path()) + .map_err(DeviceSelectorError::from)?; + let xfer_handle = self + .api + .open_path(xfer_device.path()) + .map_err(DeviceSelectorError::from)?; + + Ok(ISPDevice::new(device_spec, cmd_handle, xfer_handle)) + }; + } + + fn find_device(&self, device_spec: DeviceSpec) -> Result { + let filtered_devices = self.unique_usb_device_list().into_iter().filter(|d| { + d.vendor_id() == device_spec.vendor_id + && d.product_id() == device_spec.product_id + && d.interface_number() == device_spec.isp_iface_num + }); + + let mut cmd_device_info: Option<&DeviceInfo> = None; + for d in filtered_devices { + let ids = self + .get_feature_report_ids_from_path(d.path()) + .map_err(|_| DeviceSelectorError::NotFound)?; + for id in ids { + if id == device_spec.isp_report_id { + cmd_device_info = Some(d); + } + } + } + + let Some(cmd_device_info) = cmd_device_info else { + info!("Device didn't come up..."); + return Err(DeviceSelectorError::NotFound); + }; + + debug!("Opening: {:?}", cmd_device_info.path()); + let device = self + .api + .open_path(cmd_device_info.path()) + .map_err(DeviceSelectorError::from)?; + Ok(device) + } + + fn switch_to_isp_device( + &mut self, + device: HidDevice, + device_spec: DeviceSpec, + ) -> Result { + if let Err(err) = self.enter_isp_mode(&device) { + debug!("Error: {:}", err); + match err { + DeviceSelectorError::HidError(err) if is_expected_error(&err) => {} + _ => { + error!("Unexpected: {:}", err); + info!("Waiting..."); + thread::sleep(time::Duration::from_secs(2)); + return Err(err); + } + } + } + + info!("Waiting for ISP device..."); + thread::sleep(time::Duration::from_secs(2)); + + self.api.refresh_devices()?; + + let Ok(isp_device) = self.find_isp_device(device_spec) else { + info!("ISP device didn't come up..."); + return Err(DeviceSelectorError::NotFound); + }; + Ok(isp_device) + } + + pub fn try_fetch_isp_device( + &mut self, + device_spec: DeviceSpec, + retries: usize, + ) -> Result { + eprintln!( + "Looking for {:04x}:{:04x} (isp_iface_num={} isp_report_id={})", + device_spec.vendor_id, + device_spec.product_id, + device_spec.isp_iface_num, + device_spec.isp_report_id + ); + + let bar = ProgressBar::new_spinner() + .with_message(format!("Searching for device... Attempt {}/{}", 1, retries)); + bar.enable_steady_tick(Duration::from_millis(100)); + + for attempt in 1..retries + 1 { + if attempt > 1 { + bar.set_message(format!("Retrying... Attempt {}/{}", attempt, retries)); + info!("Retrying... Attempt {}/{}", attempt, retries); + self.api.refresh_devices()?; + thread::sleep(time::Duration::from_millis(1000)); + } + + match self.find_device(device_spec) { + Ok(device) => { + bar.set_message("Device found. Switching to ISP mode..."); + match self.switch_to_isp_device(device, device_spec) { + Ok(isp_device) => { + bar.finish_and_clear(); + eprintln!("Connected!"); + return Ok(isp_device); + } + Err(DeviceSelectorError::NotFound) => {} + Err(err) => { + return Err(err); + } + } + } + Err(DeviceSelectorError::NotFound) => {} + Err(err) => { + return Err(err); + } + } + + info!("Device not found. Trying ISP device..."); + match self.find_isp_device(device_spec) { + Ok(isp_device) => { + bar.finish_and_clear(); + eprintln!("Connected!"); + return Ok(isp_device); + } + Err(DeviceSelectorError::NotFound) => {} + Err(err) => { + return Err(err); + } + } + } + bar.finish_and_clear(); + Err(DeviceSelectorError::NotFound) + } + + fn enter_isp_mode(&self, handle: &HidDevice) -> Result<(), DeviceSelectorError> { + let cmd: [u8; COMMAND_LENGTH] = [REPORT_ID_ISP, CMD_ISP_MODE, 0x00, 0x00, 0x00, 0x00]; + handle.send_feature_report(&cmd)?; + Ok(()) + } + + pub fn connected_devices_tree(&self) -> Result, DeviceSelectorError> { + let devices: Vec<_> = self.sorted_usb_device_list(); + + let id_chunks = devices + .into_iter() + .chunk_by(|d| (d.vendor_id(), d.product_id())); + + let mut device_tree_devices: Vec = vec![]; + + for (key, devices) in &id_chunks { + let (vid, pid) = key; + + let mut interface_nodes: Vec = vec![]; + + // for some reason on linux-libusb the same device might not have the same manufacturer string in some cases + let mut manufacturer_string: Option = None; + let mut product_string: Option = None; + + let path_chunks = devices.chunk_by(|d| (d.path(), d.interface_number())); + + for (key, devices) in &path_chunks { + let (path, interface_number) = key; + + #[cfg(any(target_os = "macos", target_os = "windows"))] + let mut children: Vec = vec![]; + + for d in devices { + if manufacturer_string.is_none() { + manufacturer_string = d.manufacturer_string().map(str::to_string); + } + if product_string.is_none() { + product_string = d.product_string().map(str::to_string); + } + #[cfg(target_os = "macos")] + children.push(ItemNode { + usage_page: d.usage_page(), + usage: d.usage(), + }); + #[cfg(target_os = "windows")] + { + let (descriptor, feature_report_ids) = + self.get_descriptor_with_features(path); + children.push(ItemNode { + path: path.to_str().unwrap().to_string(), + usage_page: d.usage_page(), + usage: d.usage(), + descriptor, + feature_report_ids, + }); + } + } + + #[cfg(any(target_os = "macos", target_os = "linux"))] + let (descriptor, feature_report_ids) = self.get_descriptor_with_features(path); + let interface_node = InterfaceNode { + #[cfg(any(target_os = "macos", target_os = "linux"))] + path: path.to_str().unwrap().to_string(), + interface_number, + #[cfg(any(target_os = "macos", target_os = "linux"))] + descriptor, + #[cfg(any(target_os = "macos", target_os = "linux"))] + feature_report_ids, + #[cfg(any(target_os = "macos", target_os = "windows"))] + children, + }; + + interface_nodes.push(interface_node); + } + + device_tree_devices.push(DeviceNode { + vendor_id: vid, + product_id: pid, + manufacturer_string: manufacturer_string.clone().unwrap_or("None".to_string()), + product_string: product_string.clone().unwrap_or("None".to_string()), + children: interface_nodes, + }); + } + Ok(device_tree_devices) + } +} + +trait PlatformSpecificInfo { + fn info(&self) -> String; +} + +impl PlatformSpecificInfo for DeviceInfo { + fn info(&self) -> String { + #[cfg(not(target_os = "linux"))] + return format!( + "{:#06x} {:#06x} {:?} {} {:#06x} {:#06x}", + self.vendor_id(), + self.product_id(), + self.path(), + self.interface_number(), + self.usage_page(), + self.usage() + ); + #[cfg(target_os = "linux")] + format!( + "{:#06x} {:#06x} {:?}", + self.vendor_id(), + self.product_id(), + self.path() + ) + } +} diff --git a/src/device_spec.rs b/src/device_spec.rs new file mode 100644 index 0000000..f2c9a86 --- /dev/null +++ b/src/device_spec.rs @@ -0,0 +1,362 @@ +use phf::{phf_map, Map}; + +use crate::platform_spec::{PlatformSpec, PLATFORM_SH68F881, PLATFORM_SH68F90}; + +const DEFAULT_ISP_IFACE_NUM: i32 = 1; +const DEFAULT_ISP_REPORT_ID: u32 = 5; +const DEFAULT_REBOOT: bool = true; + +#[derive(Clone, Copy, PartialEq)] +pub struct DeviceSpec { + pub vendor_id: u16, + pub product_id: u16, + + pub platform: PlatformSpec, + + /// USB interface number with the ISP report + pub isp_iface_num: i32, + /// HID report ID + pub isp_report_id: u32, + + pub reboot: bool, +} + +pub const DEVICE_BASE_SH68F90: DeviceSpec = DeviceSpec { + vendor_id: 0x0000, + product_id: 0x0000, + platform: PLATFORM_SH68F90, + isp_iface_num: DEFAULT_ISP_IFACE_NUM, + isp_report_id: DEFAULT_ISP_REPORT_ID, + reboot: DEFAULT_REBOOT, +}; + +pub const DEVICE_BASE_SH68F881: DeviceSpec = DeviceSpec { + vendor_id: 0x0000, + product_id: 0x0000, + platform: PLATFORM_SH68F881, + isp_iface_num: DEFAULT_ISP_IFACE_NUM, + isp_report_id: DEFAULT_ISP_REPORT_ID, + reboot: DEFAULT_REBOOT, +}; + +pub const DEVICE_NUPHY_AIR60: DeviceSpec = DeviceSpec { + vendor_id: 0x05ac, + product_id: 0x024f, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_LEOBOG_HI75: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x010c, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_AULA_F75: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x010c, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_AULA_F87: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x010c, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_XINMENG_K916: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x00a1, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_XINMENG_XM_RF68: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x002a, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_XINMENG_M71: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x010c, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_RE_K70_BYK800: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x001a, + ..DEVICE_BASE_SH68F881 +}; + +pub const DEVICE_TERPORT_TR95: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_FIZZ_K617: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_K618: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_ANIVIA_K614: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_K641_SHACO_PRO: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_GENESIS_THOR_300: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x001f, + ..DEVICE_BASE_SH68F881 +}; + +pub const DEVICE_GENESIS_THOR_300_RGB: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0090, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_ROYALKLUDGE_RK61: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x00c7, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_ROYALKLUDGE_RK68_ISO_RETURN: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x00a9, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_ROYALKLUDGE_RK68_BT_DUAL: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x008b, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_ROYALKLUDGE_RKG68: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_ROYALKLUDGE_RK71: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x00ea, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_ROYALKLUDGE_RK84_ISO_RETURN: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x00f4, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_ROYALKLUDGE_RK100: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0056, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_DELTACO_WK95R: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_DIGITALALLIANCE_MECA_WARRIOR_X: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0090, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_KZZI_K68PRO: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0186, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_WEIKAV_SUGAR65: DeviceSpec = DeviceSpec { + vendor_id: 0x05ac, + product_id: 0x024f, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_TRUST_GXT_960: DeviceSpec = DeviceSpec { + vendor_id: 0x145f, + product_id: 0x02b6, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_GLORIOUS_MODEL_O: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0036, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_MACHENIKE_K500_B61: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_MAGEGEE_MKSTAR61: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x010c, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_K658_PRO_SE: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_K652_PRO: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_K530_DRACONIC_PRO: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_K630_NO_RGB: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x002a, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_EWEADN_V20: DeviceSpec = DeviceSpec { + vendor_id: 0x05ac, + product_id: 0x024f, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_EYOOSO_Z11: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x002a, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_EYOOSO_Z82: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x010c, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_PORTRONICS_HYDRA10: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_REDRAGON_K633_RYZE: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_YINREN_R108: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x0049, + ..DEVICE_BASE_SH68F90 +}; + +pub const DEVICE_DIERYA_DK68SE: DeviceSpec = DeviceSpec { + vendor_id: 0x258a, + product_id: 0x013b, + ..DEVICE_BASE_SH68F90 +}; + +pub static DEVICES: Map<&'static str, DeviceSpec> = phf_map! { + "aula-f75" => DEVICE_AULA_F75, + "aula-f87" => DEVICE_AULA_F87, + "deltaco-wk95r" => DEVICE_DELTACO_WK95R, + "dierya-dk68se" => DEVICE_DIERYA_DK68SE, + "digitalalliance-meca-warrior-x" => DEVICE_DIGITALALLIANCE_MECA_WARRIOR_X, + "eweadn-v20" => DEVICE_EWEADN_V20, + "eyooso-z11" => DEVICE_EYOOSO_Z11, + "eyooso-z82" => DEVICE_EYOOSO_Z82, + "genesis-thor-300-rgb" => DEVICE_GENESIS_THOR_300_RGB, + "genesis-thor-300" => DEVICE_GENESIS_THOR_300, + "glorious-model-o" => DEVICE_GLORIOUS_MODEL_O, + "kzzi-k68pro" => DEVICE_KZZI_K68PRO, + "leobog-hi75" => DEVICE_LEOBOG_HI75, + "machenike-k500-b61" => DEVICE_MACHENIKE_K500_B61, + "magegee-mkstar61" => DEVICE_MAGEGEE_MKSTAR61, + "nuphy-air60" => DEVICE_NUPHY_AIR60, + "nuphy-air75" => DEVICE_NUPHY_AIR60, // same as nuphy-air60 + "nuphy-air96" => DEVICE_NUPHY_AIR60, // same as nuphy-air60 + "nuphy-halo65" => DEVICE_NUPHY_AIR60, // same as nuphy-air60 + "portronics-hydra10" => DEVICE_PORTRONICS_HYDRA10, + "re-k70-byk800" => DEVICE_RE_K70_BYK800, + "redragon-k530-draconic-pro" => DEVICE_REDRAGON_K530_DRACONIC_PRO, + "redragon-k630-norgb" => DEVICE_REDRAGON_K630_NO_RGB, + "redragon-k614-anivia" => DEVICE_REDRAGON_ANIVIA_K614, + "redragon-k617-fizz" => DEVICE_REDRAGON_FIZZ_K617, + "redragon-k618" => DEVICE_REDRAGON_K618, + "redragon-k633-ryze" => DEVICE_REDRAGON_K633_RYZE, + "redragon-k641-shaco-pro" => DEVICE_REDRAGON_K641_SHACO_PRO, + "redragon-k652-pro" => DEVICE_REDRAGON_K652_PRO, + "redragon-k658-pro-se" => DEVICE_REDRAGON_K658_PRO_SE, + "royalkludge-rk100" => DEVICE_ROYALKLUDGE_RK100, + "royalkludge-rk61" => DEVICE_ROYALKLUDGE_RK61, + "royalkludge-rk68-bt-dual" => DEVICE_ROYALKLUDGE_RK68_BT_DUAL, + "royalkludge-rk68-iso-return" => DEVICE_ROYALKLUDGE_RK68_ISO_RETURN, + "royalkludge-rk71" => DEVICE_ROYALKLUDGE_RK71, + "royalkludge-rk84-iso-return" => DEVICE_ROYALKLUDGE_RK84_ISO_RETURN, + "royalkludge-rkg68" => DEVICE_ROYALKLUDGE_RKG68, + "terport-tr95" => DEVICE_TERPORT_TR95, + "trust-gxt-960" => DEVICE_TRUST_GXT_960, + "weikav-sugar65" => DEVICE_WEIKAV_SUGAR65, + "xinmeng-k916" => DEVICE_XINMENG_K916, + "xinmeng-m66" => DEVICE_XINMENG_M71, + "xinmeng-m71" => DEVICE_XINMENG_M71, + "xinmeng-xm-rf68" => DEVICE_XINMENG_XM_RF68, + "yinren-r108" => DEVICE_YINREN_R108, + "yunzii-al66" => DEVICE_XINMENG_M71, // same as xinmeng-m71 + "yunzii-al71" => DEVICE_XINMENG_M71, // same as xinmeng-m71 +}; + +impl DeviceSpec { + pub fn available_devices() -> Vec<&'static str> { + let mut device_names = DEVICES.keys().copied().collect::>(); + device_names.sort(); + device_names + } + + pub fn num_pages(&self) -> usize { + self.platform.firmware_size / self.platform.page_size + } + + pub fn total_flash_size(&self) -> usize { + self.platform.firmware_size + self.platform.bootloader_size + } +} + +#[test] +fn test_device_num_pages() { + assert_eq!(DEVICE_NUPHY_AIR60.num_pages(), 30) +} + +#[test] +fn test_device_total_flash_size() { + assert_eq!(DEVICE_NUPHY_AIR60.total_flash_size(), 65536) +} diff --git a/src/hid.rs b/src/hid.rs deleted file mode 100644 index 02e5888..0000000 --- a/src/hid.rs +++ /dev/null @@ -1,62 +0,0 @@ -use rusb::*; -use std::time; - -pub struct HidDevice { - handle: DeviceHandle, - interface_number: u8 -} - -impl HidDevice { - - pub fn open(vendor_id: u16, product_id: u16) -> Option { - let Some(mut handle) = open_device_with_vid_pid(vendor_id, product_id) else { - return None; - }; - - let interface_number = handle.device().config_descriptor(0).unwrap().interfaces() - .map(|i| i.descriptors()) - .flatten() - .filter(|i| i.class_code() == constants::LIBUSB_CLASS_HID) - .map(|i| i.interface_number()) - .last() - .unwrap(); - - #[cfg(any(target_os = "linux"))] - if handle.kernel_driver_active(interface_number).unwrap() { - handle.detach_kernel_driver(interface_number).unwrap(); - } - - return Some(HidDevice { - handle: handle, - interface_number: interface_number - }); - } - - pub fn get_feature_report(self: &Self, buf: &mut [u8]) -> Result { - let report_number = buf[0] as u16; - - return self.handle.read_control( - constants::LIBUSB_REQUEST_TYPE_CLASS | constants::LIBUSB_RECIPIENT_INTERFACE | constants::LIBUSB_ENDPOINT_IN, - 0x01, - (3/*HID feature*/ << 8) | report_number, - self.interface_number as u16, - buf, - time::Duration::from_millis(1000) - ); - } - - pub fn send_feature_report(self: &Self, buf: &[u8]) -> Result { - let report_number = buf[0] as u16; - - return self.handle.write_control( - constants::LIBUSB_REQUEST_TYPE_CLASS | constants::LIBUSB_RECIPIENT_INTERFACE | constants::LIBUSB_ENDPOINT_OUT, - 0x09, - (3/*HID feature*/ << 8) | report_number, - self.interface_number as u16, - buf, - time::Duration::from_millis(1000) - ); - } - - -} \ No newline at end of file diff --git a/src/hid_tree.rs b/src/hid_tree.rs new file mode 100644 index 0000000..097d504 --- /dev/null +++ b/src/hid_tree.rs @@ -0,0 +1,175 @@ +use crate::{device_selector::DeviceSelectorError, to_hex_string}; + +pub struct DeviceNode { + pub product_id: u16, + pub vendor_id: u16, + pub product_string: String, + pub manufacturer_string: String, + pub children: Vec, +} + +pub struct InterfaceNode { + pub interface_number: i32, + #[cfg(any(target_os = "macos", target_os = "linux"))] + pub path: String, + #[cfg(any(target_os = "macos", target_os = "linux"))] + pub descriptor: Result, DeviceSelectorError>, + #[cfg(any(target_os = "macos", target_os = "linux"))] + pub feature_report_ids: Result, DeviceSelectorError>, + #[cfg(any(target_os = "macos", target_os = "windows"))] + pub children: Vec, +} + +#[cfg(any(target_os = "macos", target_os = "windows"))] +pub struct ItemNode { + #[cfg(target_os = "windows")] + pub path: String, + #[cfg(any(target_os = "macos", target_os = "windows"))] + pub usage_page: u16, + #[cfg(any(target_os = "macos", target_os = "windows"))] + pub usage: u16, + #[cfg(target_os = "windows")] + pub descriptor: Result, DeviceSelectorError>, + #[cfg(target_os = "windows")] + pub feature_report_ids: Result, DeviceSelectorError>, +} + +const INDENT_SIZE: usize = 4; + +pub trait TreeDisplay { + fn to_tree_string(self, level: usize) -> String; +} + +impl TreeDisplay for T +where + T: Iterator, + I: TreeDisplay, +{ + fn to_tree_string(self, level: usize) -> String { + let indent = " ".repeat(INDENT_SIZE).repeat(level); + let mut s: Vec = vec![]; + for item in self { + s.push(format!("{}{}", indent, item.to_tree_string(level))); + } + s.join("\n") + } +} + +impl TreeDisplay for DeviceNode { + fn to_tree_string(self, level: usize) -> String { + let indent = " ".repeat(INDENT_SIZE).repeat(level); + let mut s: Vec = vec![]; + s.push(format!( + "{indent}ID {:04x}:{:04x} manufacturer=\"{:}\" product=\"{:}\"", + self.vendor_id, self.product_id, self.manufacturer_string, self.product_string + )); + for child in self.children { + s.push(child.to_tree_string(level + 1)); + } + s.join("\n") + } +} + +impl TreeDisplay for InterfaceNode { + fn to_tree_string(self, level: usize) -> String { + let indent = " ".repeat(INDENT_SIZE).repeat(level); + let mut s: Vec = vec![]; + #[cfg(any(target_os = "macos", target_os = "linux"))] + s.push(format!( + "{indent}path=\"{}\" interface_number={}", + self.path, self.interface_number + )); + #[cfg(target_os = "windows")] + s.push(format!( + "{indent}interface_number={}", + self.interface_number + )); + #[cfg(any(target_os = "macos", target_os = "linux"))] + { + let descriptor = self.descriptor.as_ref(); + match descriptor { + Ok(descriptor) => { + s.push(format!( + "{indent}report_descriptor=[{}]", + to_hex_string(descriptor) + )); + } + Err(e) => { + s.push(format!("{indent}report_descriptor=error: {}", e)); + } + } + let feature_report_ids = self.feature_report_ids.as_ref(); + match feature_report_ids { + Ok(feature_report_ids) => { + s.push(format!( + "{indent}feature_report_ids=[{}]", + feature_report_ids + .iter() + .map(|rid| format!("{}", rid)) + .collect::>() + .join(", ") + )); + } + Err(e) => { + s.push(format!("{indent}feature_report_ids=error: {}", e)); + } + } + } + #[cfg(any(target_os = "macos", target_os = "windows"))] + { + for child in self.children { + s.push(child.to_tree_string(level + 1)); + } + } + s.join("\n") + } +} + +#[cfg(any(target_os = "macos", target_os = "windows"))] +impl TreeDisplay for ItemNode { + fn to_tree_string(self, level: usize) -> String { + let indent = " ".repeat(INDENT_SIZE).repeat(level); + let mut s: Vec = vec![]; + #[cfg(target_os = "macos")] + s.push(format!( + "{indent}usage_page={:#06x} usage={:#06x}", + self.usage_page, self.usage + )); + #[cfg(target_os = "windows")] + { + s.push(format!( + "{indent}path=\"{}\" usage_page={:#06x} usage={:#06x}", + self.path, self.usage_page, self.usage + )); + let descriptor = self.descriptor.as_ref(); + match descriptor { + Ok(descriptor) => { + s.push(format!( + "{indent}report_descriptor=[{}]", + to_hex_string(descriptor) + )); + } + Err(e) => { + s.push(format!("{indent}report_descriptor=error: {}", e)); + } + } + let feature_report_ids = self.feature_report_ids.as_ref(); + match feature_report_ids { + Ok(feature_report_ids) => { + s.push(format!( + "{indent}feature_report_ids=[{}]", + feature_report_ids + .iter() + .map(|rid| format!("{}", rid)) + .collect::>() + .join(", ") + )); + } + Err(e) => { + s.push(format!("{indent}feature_report_ids=error: {}", e)); + } + } + } + s.join("\n") + } +} diff --git a/src/ihex.rs b/src/ihex.rs new file mode 100644 index 0000000..accbc66 --- /dev/null +++ b/src/ihex.rs @@ -0,0 +1,128 @@ +use ihex::{create_object_file_representation, Reader, ReaderError, Record, WriterError}; +use thiserror::Error; + +#[derive(Debug, Error, PartialEq)] +pub enum UnpackingError { + #[error("Unsupported record type")] + UnsupportedRecordType(Record), + #[error("Error while parsing IHEX records")] + Parsing(#[from] ReaderError), + #[error("Address {addr:#06x} greater than binary size {size:#06x}")] + AddressTooHigh { addr: usize, size: usize }, +} + +#[derive(Debug, Error, PartialEq)] +pub enum ConversionError { + #[error("Error while unpacking IHEX into array {0:?}")] + Unpacking(#[from] UnpackingError), + #[error("Errow while writing IHEX to string {0:?}")] + Serializing(#[from] WriterError), +} + +pub fn to_ihex(byte_array: &[u8]) -> Result { + let mut result: Vec = vec![]; + for (i, chunk) in byte_array.chunks(16).enumerate() { + result.push(Record::Data { + offset: (i as u16) * 16, + value: chunk.to_vec(), + }); + } + result.push(Record::EndOfFile); + create_object_file_representation(&result).map_err(ConversionError::from) +} + +pub fn from_ihex(ihex_string: &str, max_length: usize) -> Result, ConversionError> { + let mut reader = Reader::new(ihex_string); + unpack_records(&mut reader, max_length).map_err(ConversionError::from) +} + +fn unpack_records( + records: &mut impl Iterator>, + max_length: usize, +) -> Result, UnpackingError> { + let mut result: Vec = vec![]; + for rec in records { + match rec { + Ok(rec) => match rec { + Record::Data { offset, value } => { + let end_addr = offset as usize + value.len(); + if end_addr > max_length { + return Err(UnpackingError::AddressTooHigh { + addr: end_addr, + size: max_length, + }); + } + if end_addr > result.len() { + result.resize(end_addr, 0); + } + + for (n, b) in value.iter().enumerate() { + result[offset as usize + n] = *b; + } + } + Record::ExtendedSegmentAddress(_base) => { + return Err(UnpackingError::UnsupportedRecordType(rec)) + } + Record::ExtendedLinearAddress(_base) => { + return Err(UnpackingError::UnsupportedRecordType(rec)) + } + Record::EndOfFile => break, + Record::StartLinearAddress(_) | Record::StartSegmentAddress { .. } => {} + }, + Err(err) => return Err(UnpackingError::Parsing(err)), + } + } + Ok(result) +} + +#[test] +fn test_from_ihex() { + let result = from_ihex( + ":100000000200660227BD010A32646402CB9053DA13\n:00000001FF", + 16, + ) + .unwrap(); + let expected = vec![ + 2, 0, 102, 2, 39, 189, 1, 10, 50, 100, 100, 2, 203, 144, 83, 218, + ]; + assert_eq!(result, expected); +} + +#[test] +fn test_from_ihex_address_start_at_0x0001() { + let result = from_ihex( + ":100010000200660227BD010A32646402CB9053DA03\n:00000001FF", + 32, + ); + let mut expected: Vec = Vec::new(); + expected.resize(16, 0); + expected.extend_from_slice(&[ + 2, 0, 102, 2, 39, 189, 1, 10, 50, 100, 100, 2, 203, 144, 83, 218, + ]); + assert_eq!(result, Ok(expected)); +} + +#[test] +fn test_from_ihex_err_checksum_mismatch() { + let result = from_ihex( + ":100000000200660227BD010A32646402CB9053DA00\n:00000001FF", + 16, + ); + let expected = Err(ConversionError::Unpacking(UnpackingError::Parsing( + ReaderError::ChecksumMismatch(0x13, 0x00), + ))); + assert_eq!(result, expected); +} + +#[test] +fn test_from_ihex_err_address_too_high() { + let result = from_ihex( + ":100010000200660227BD010A32646402CB9053DA03\n:00000001FF", + 16, + ); + let expected = Err(ConversionError::Unpacking(UnpackingError::AddressTooHigh { + addr: 0x20, + size: 0x10, + })); + assert_eq!(result, expected); +} diff --git a/src/isp_device.rs b/src/isp_device.rs new file mode 100644 index 0000000..9b1a03b --- /dev/null +++ b/src/isp_device.rs @@ -0,0 +1,300 @@ +use core::panic; +use std::{str::FromStr, thread, time}; + +use indicatif::ProgressBar; +use log::{debug, error}; +use thiserror::Error; + +use crate::{device_spec::*, is_expected_error, util, VerificationError}; + +extern crate hidapi; + +use hidapi::{HidDevice, HidError}; + +const COMMAND_LENGTH: usize = 6; + +const REPORT_ID_CMD: u8 = 0x05; +const REPORT_ID_XFER: u8 = 0x06; + +const CMD_ENABLE_FIRMWARE: u8 = 0x55; +const CMD_INIT_READ: u8 = 0x52; +const CMD_INIT_WRITE: u8 = 0x57; +const CMD_ERASE: u8 = 0x45; +const CMD_REBOOT: u8 = 0x5a; + +const XFER_READ_PAGE: u8 = 0x72; +const XFER_WRITE_PAGE: u8 = 0x77; + +pub struct ISPDevice { + cmd_device: HidDevice, + #[cfg(target_os = "windows")] + xfer_device: HidDevice, + device_spec: DeviceSpec, +} + +#[derive(Debug, Error)] +pub enum ISPError { + #[error(transparent)] + HidError(#[from] HidError), + #[error(transparent)] + VerificationError(#[from] VerificationError), + #[error("Read/Write operation mistmatch")] + ReadWriteMismatch, +} + +#[derive(Debug, Clone)] +pub enum ReadSection { + Firmware, + Bootloader, + Full, +} + +impl ReadSection { + pub fn to_str(&self) -> &'static str { + match self { + ReadSection::Firmware => "firmware", + ReadSection::Bootloader => "bootloader", + ReadSection::Full => "full", + } + } + + pub fn available_sections() -> Vec<&'static str> { + vec![ + ReadSection::Firmware.to_str(), + ReadSection::Bootloader.to_str(), + ReadSection::Full.to_str(), + ] + } +} + +impl FromStr for ReadSection { + type Err = (); + fn from_str(section: &str) -> Result { + Ok(match section { + "bootloader" => ReadSection::Bootloader, + "full" => ReadSection::Full, + "firmware" => ReadSection::Firmware, + _ => panic!("Invalid read section: {}", section), + }) + } +} + +impl ISPDevice { + #[cfg(not(target_os = "windows"))] + pub fn new(device_spec: DeviceSpec, device: HidDevice) -> Self { + Self { + cmd_device: device, + device_spec, + } + } + + #[cfg(target_os = "windows")] + pub fn new(device_spec: DeviceSpec, cmd_device: HidDevice, xfer_device: HidDevice) -> Self { + Self { + cmd_device, + xfer_device, + device_spec, + } + } + + pub fn read_cycle(&self, read_fragment: ReadSection) -> Result, ISPError> { + self.enable_firmware()?; + + let (start_addr, length) = match read_fragment { + ReadSection::Firmware => (0, self.device_spec.platform.firmware_size), + ReadSection::Bootloader => ( + self.device_spec.platform.firmware_size, + self.device_spec.platform.bootloader_size, + ), + ReadSection::Full => ( + 0, + self.device_spec.platform.firmware_size + self.device_spec.platform.bootloader_size, + ), + }; + + let firmware = self.read(start_addr, length)?; + + if self.device_spec.reboot { + self.reboot(); + } + + Ok(firmware) + } + + pub fn write_cycle(&self, firmware: &mut [u8]) -> Result<(), ISPError> { + // ensure that the address at is the same as the reset vector + firmware.copy_within(1..3, self.device_spec.platform.firmware_size - 4); + + self.erase()?; + self.write(0, firmware)?; + + // cleanup the address at + firmware[self.device_spec.platform.firmware_size - 4 + ..self.device_spec.platform.firmware_size - 2] + .fill(0); + + let read_back = self.read(0, self.device_spec.platform.firmware_size)?; + + eprintln!("Verifying..."); + util::verify(firmware, &read_back).map_err(ISPError::from)?; + + self.enable_firmware()?; + + if self.device_spec.reboot { + self.reboot(); + } + + Ok(()) + } + + fn xfer_device(&self) -> &HidDevice { + #[cfg(target_os = "windows")] + return &self.xfer_device; + #[cfg(not(target_os = "windows"))] + &self.cmd_device + } + + fn read(&self, start_addr: usize, length: usize) -> Result, ISPError> { + let page_size = self.device_spec.platform.page_size; + let num_page = length / page_size; + let mut result: Vec = vec![]; + + eprintln!("Reading..."); + let bar = ProgressBar::new(num_page as u64); + + self.init_read(start_addr)?; + + for i in 0..num_page { + bar.inc(1); + debug!( + "Reading page {} @ offset {:#06x}", + i, + start_addr + i * page_size + ); + self.read_page(&mut result)?; + } + bar.finish(); + Ok(result) + } + + fn write(&self, start_addr: usize, buffer: &[u8]) -> Result<(), ISPError> { + eprintln!("Writing..."); + let bar = ProgressBar::new(self.device_spec.num_pages() as u64); + self.init_write(start_addr)?; + + let page_size = self.device_spec.platform.page_size; + for i in 0..self.device_spec.num_pages() { + bar.inc(1); + debug!("Writing page {} @ offset {:#06x}", i, i * page_size); + self.write_page(&buffer[(i * page_size)..((i + 1) * page_size)])?; + } + bar.finish(); + Ok(()) + } + + /// Initializes the read operation / sets the initial read address + fn init_read(&self, start_addr: usize) -> Result<(), ISPError> { + let cmd: [u8; COMMAND_LENGTH] = [ + REPORT_ID_CMD, + CMD_INIT_READ, + (start_addr & 0xff) as u8, + (start_addr >> 8) as u8, + 0, + 0, + ]; + self.cmd_device + .send_feature_report(&cmd) + .map_err(ISPError::from)?; + Ok(()) + } + + /// Initializes the write operation / sets the initial write address + fn init_write(&self, start_addr: usize) -> Result<(), ISPError> { + let cmd: [u8; COMMAND_LENGTH] = [ + REPORT_ID_CMD, + CMD_INIT_WRITE, + (start_addr & 0xff) as u8, + (start_addr >> 8) as u8, + 0, + 0, + ]; + self.cmd_device + .send_feature_report(&cmd) + .map_err(ISPError::from)?; + Ok(()) + } + + /// Reads one page of flash contents + fn read_page(&self, buf: &mut Vec) -> Result<(), ISPError> { + let page_size = self.device_spec.platform.page_size; + let mut xfer_buf: Vec = vec![0; page_size + 2]; + xfer_buf[0] = REPORT_ID_XFER; + self.xfer_device() + .get_feature_report(&mut xfer_buf) + .map_err(ISPError::from)?; + buf.extend_from_slice(&xfer_buf[2..(page_size + 2)]); + if xfer_buf[1] != XFER_READ_PAGE { + return Err(ISPError::ReadWriteMismatch); + } + Ok(()) + } + + /// Writes one page to flash + /// + /// Note: The first 3 bytes at address 0x0000 (first-page) are skipped. Instead the second and + /// third bytes (firmware's reset vector LJMP destination address) are written to address + /// and will later be part of the LJMP instruction after the firmware is + /// enabled (`enable_firmware`). This only works once after an erase operation. + fn write_page(&self, buf: &[u8]) -> Result<(), ISPError> { + let length = buf.len() + 2; + let mut xfer_buf: Vec = vec![0; length]; + xfer_buf[0] = REPORT_ID_XFER; + xfer_buf[1] = XFER_WRITE_PAGE; + xfer_buf[2..length].clone_from_slice(buf); + self.xfer_device() + .send_feature_report(&xfer_buf) + .map_err(ISPError::from)?; + if xfer_buf[1] != XFER_WRITE_PAGE { + return Err(ISPError::ReadWriteMismatch); + } + Ok(()) + } + + /// Sets a LJMP (0x02) opcode at . + /// This enables the main firmware by making the bootloader jump to it on reset. + /// + /// Side-effect: enables reading the firmware without erasing flash first. + /// Credits to @gashtaan for finding this out. + fn enable_firmware(&self) -> Result<(), ISPError> { + eprintln!("Enabling firmware..."); + let cmd: [u8; COMMAND_LENGTH] = [REPORT_ID_CMD, CMD_ENABLE_FIRMWARE, 0, 0, 0, 0]; + + self.cmd_device.send_feature_report(&cmd)?; + Ok(()) + } + + /// Erases everything in flash, except the ISP bootloader section itself and initializes the + /// reset vector to jump to ISP. + fn erase(&self) -> Result<(), ISPError> { + eprintln!("Erasing..."); + let cmd: [u8; COMMAND_LENGTH] = [REPORT_ID_CMD, CMD_ERASE, 0, 0, 0, 0]; + self.cmd_device + .send_feature_report(&cmd) + .map_err(ISPError::from)?; + thread::sleep(time::Duration::from_millis(2000)); + Ok(()) + } + + /// Causes the device to start running the main firmware + fn reboot(&self) { + eprintln!("Rebooting..."); + let cmd: [u8; COMMAND_LENGTH] = [REPORT_ID_CMD, CMD_REBOOT, 0, 0, 0, 0]; + if let Err(err) = self.cmd_device.send_feature_report(&cmd) { + debug!("Error: {:}", err); + if !is_expected_error(&err) { + error!("Unexpected error: {:}", err); + } + } + thread::sleep(time::Duration::from_millis(2000)); + } +} diff --git a/src/main.rs b/src/main.rs index fd13d8b..71db5ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,95 +1,194 @@ -use clap::*; -use ihex::*; -use ihex_ext::*; +use std::{ + env, fs, + io::{self, Read}, + path::Path, + process::ExitCode, + str::FromStr, +}; + +use clap::{arg, value_parser, ArgMatches, Command}; +use clap_num::maybe_hex; +use device_selector::{DeviceSelector, DeviceSelectorError}; +use dialoguer::Confirm; +use hid_tree::TreeDisplay; +use log::error; +use platform_spec::PlatformSpec; use simple_logger::SimpleLogger; -use std::fs; +use thiserror::Error; + +mod device_selector; +mod device_spec; +mod hid_tree; +mod ihex; +mod isp_device; +mod platform_spec; +mod util; -mod part; -pub use part::*; +pub use crate::{device_spec::*, ihex::*, isp_device::*, util::*}; -mod programmer; -pub use programmer::*; +const DEFAULT_RETRY_COUNT: &str = "5"; -mod util; -pub use util::*; +#[derive(Debug, Error)] +pub enum CLIError { + #[error(transparent)] + IOError(#[from] io::Error), + #[error(transparent)] + ISPError(#[from] ISPError), + #[error(transparent)] + IHEXError(#[from] ConversionError), + #[error(transparent)] + PayloadConversionError(#[from] PayloadConversionError), + #[error(transparent)] + DeviceSelectorError(#[from] DeviceSelectorError), +} + +#[derive(Clone, Copy)] +enum Format { + IntelHex, + Binary, +} + +impl Format { + pub fn to_str(self) -> &'static str { + match self { + Format::IntelHex => "ihex", + Format::Binary => "bin", + } + } + + pub fn available_formats() -> Vec<&'static str> { + vec![Format::IntelHex.to_str(), Format::Binary.to_str()] + } +} + +impl FromStr for Format { + type Err = (); + fn from_str(format: &str) -> Result { + Ok(match format { + "ihex" => Format::IntelHex, + "bin" => Format::Binary, + _ => panic!("Invalid format: {}", format), + }) + } +} -mod hid; -pub use hid::*; +fn main() -> ExitCode { + match err_main() { + Ok(_) => ExitCode::SUCCESS, + Err(err) => { + eprintln!("{:}", err); + ExitCode::FAILURE + } + } +} fn cli() -> Command { - return Command::new("sinowealth-kb-tool") - .about("A programming tool for Sinowealth Gaming KB devices") - .version("0.0.1") + Command::new("sinowealth-kb-tool") + .about("A tool to read and write flash for SinoWealth ISP devices") + .version(env!("CARGO_PKG_VERSION")) .subcommand_required(true) .arg_required_else_help(true) .author("Karolis Stasaitis") + .subcommand( + Command::new("list") + .about("List all connected usb hid devices and info about them.") + .arg(arg!(--vendor_id ).value_parser(maybe_hex::)) + .arg(arg!(--product_id ).value_parser(maybe_hex::)), + ) .subcommand( Command::new("read") - .short_flag('r') - .about("Read flash contents. (ihex)") + .about("Read flash into a file.") .arg(arg!(output_file: "file to write flash contents to")) + .arg(arg!(--format ).value_parser(Format::available_formats())) .arg( - arg!(-p --part ) - .value_parser(PARTS.keys().map(|&s| s).collect::>()) - .required(true), + arg!(-s --section
"firmware section to read") + .value_parser(ReadSection::available_sections()) + .default_value(ReadSection::Firmware.to_str()), ) .arg( - arg!(-b --bootloader "read only booloader") - .conflicts_with("full") + arg!(-r --retry "number of attempts trying to find device") + .value_parser(value_parser!(usize)) + .default_value(DEFAULT_RETRY_COUNT), ) - .arg( - arg!(-f --full "read complete flash (including the bootloader)") - .conflicts_with("bootloader") - ), + .device_args(), ) .subcommand( Command::new("write") - .short_flag('w') - .about("Write file into flash.") + .about("Write a file into flash.") .arg(arg!(input_file: "payload to write into flash")) + .arg(arg!(-f --force "ignore firmware size check")) + .arg(arg!(--format ).value_parser(Format::available_formats())) .arg( - arg!(-p --part ) - .value_parser(PARTS.keys().map(|&s| s).collect::>()) + arg!(-r --retry "number of attempts trying to find device") + .value_parser(value_parser!(usize)) + .default_value(DEFAULT_RETRY_COUNT), + ) + .device_args(), + ) + .subcommand( + Command::new("convert") + .about("Convert payload from ISP to JTAG and vice versa.") + .arg( + arg!(--direction "direction of conversion") + .value_parser(["to_jtag", "to_isp"]) .required(true), - ), - ); + ) + .arg(arg!(--input_format ).value_parser(Format::available_formats())) + .arg(arg!(--output_format ).value_parser(Format::available_formats())) + .arg(arg!(input_file: "file to convert")) + .arg(arg!(output_file: "file to write results to")) + .device_args(), // TODO: not all of these args are needed and should be removed + ) } -fn main() { - SimpleLogger::new().init().unwrap(); +fn err_main() -> Result<(), CLIError> { + SimpleLogger::new() + .with_utc_timestamps() + .with_level(log::LevelFilter::Off) + .env() + .init() + .unwrap(); let matches = cli().get_matches(); match matches.subcommand() { Some(("read", sub_matches)) => { - let part_name = sub_matches - .get_one::("part") - .map(|s| s.as_str()) - .unwrap(); - let output_file = sub_matches .get_one::("output_file") .map(|s| s.as_str()) .unwrap(); - let full = sub_matches.get_flag("full"); + let retry_count = sub_matches + .get_one::("retry") + .map(|s| s.to_owned()) + .unwrap(); + + let section = sub_matches + .get_one::("section") + .map(|s| s.as_str()) + .map(|s| ReadSection::from_str(s).unwrap()) + .unwrap(); - let bootloader = sub_matches.get_flag("bootloader"); + let format = get_format_from_matches(sub_matches, output_file, "format"); - let part = PARTS.get(part_name).unwrap(); + let device_spec = get_device_spec_from_matches(sub_matches); - let read_type = match (full, bootloader) { - (true, _) => ReadType::Full, - (_, true) => ReadType::Bootloader, - _ => ReadType::Normal - }; + let mut ds = DeviceSelector::new().map_err(CLIError::DeviceSelectorError)?; + let device = ds + .try_fetch_isp_device(device_spec, retry_count) + .map_err(CLIError::from)?; + let firmware = device.read_cycle(section).map_err(CLIError::from)?; - let result = Programmer::new(part).read_cycle(read_type); + let digest = md5::compute(&firmware); + eprintln!("MD5: {:x}", digest); - let ihex = result.to_ihex(); + write_with_format(output_file, &firmware, format)?; - let obj = create_object_file_representation(&ihex).unwrap(); - fs::write(output_file, obj).expect("Unable to write file"); + eprintln!( + "Successfully read {} bytes - {}", + firmware.len(), + output_file + ); } Some(("write", sub_matches)) => { let input_file = sub_matches @@ -97,27 +196,298 @@ fn main() { .map(|s| s.as_str()) .unwrap(); - let part_name = sub_matches - .get_one::("part") - .map(|s| s.as_str()) + let retry_count = sub_matches + .get_one::("retry") + .map(|s| s.to_owned()) .unwrap(); - let part = PARTS.get(part_name).unwrap(); + let force = sub_matches.get_flag("force"); + + let format = get_format_from_matches(sub_matches, input_file, "format"); + + let device_spec = get_device_spec_from_matches(sub_matches); + + let mut firmware = read_with_format(input_file, format)?; + + if firmware.len() < device_spec.platform.firmware_size { + eprintln!( + "Warning: firmware size is less than expected ({}). It will be resized to {} and filled with 0", + firmware.len(), + device_spec.platform.firmware_size + ); + if !force { + eprintln!("Use --force skip confirmation"); + let confirmation = Confirm::new() + .with_prompt("Are you sure you want to continue?") + .default(false) + .interact() + .unwrap(); + + if !confirmation { + return Ok(()); + } + } + firmware.resize(device_spec.platform.firmware_size, 0); + } - let (mut firmware, _) = load_file_vec(input_file, part.flash_size, 0).unwrap(); + let mut ds = DeviceSelector::new().map_err(CLIError::DeviceSelectorError)?; + let device = ds + .try_fetch_isp_device(device_spec, retry_count) + .map_err(CLIError::from)?; + device.write_cycle(&mut firmware).map_err(CLIError::from)?; - Programmer::new(part).write_cycle(&mut firmware); + eprintln!("Successfully wrote {} bytes", firmware.len()); } - Some(("erase", sub_matches)) => { - let part_name = sub_matches - .get_one::("part") + Some(("list", sub_matches)) => { + let vendor_id = sub_matches.get_one::("vendor_id"); + let product_id = sub_matches.get_one::("product_id"); + + let ds = DeviceSelector::new().map_err(CLIError::DeviceSelectorError)?; + let devices = ds + .connected_devices_tree() + .map_err(CLIError::DeviceSelectorError)?; + let tree = devices + .into_iter() + .filter(|device| { + if let Some(vendor_id) = vendor_id { + if device.vendor_id != *vendor_id { + return false; + } + } + if let Some(product_id) = product_id { + if device.product_id != *product_id { + return false; + } + } + true + }) + .to_tree_string(0); + + println!("{}", tree); + } + Some(("convert", sub_matches)) => { + let input_file = sub_matches + .get_one::("input_file") + .map(|s| s.as_str()) + .unwrap(); + + let output_file = sub_matches + .get_one::("output_file") + .map(|s| s.as_str()) + .unwrap(); + + let direction = sub_matches + .get_one::("direction") .map(|s| s.as_str()) .unwrap(); - let part = PARTS.get(part_name).unwrap(); + let input_format = get_format_from_matches(sub_matches, input_file, "input_format"); + let output_format = get_format_from_matches(sub_matches, output_file, "output_format"); - Programmer::new(part).erase_cycle(); + let device_spec = get_device_spec_from_matches(sub_matches); + + let mut firmware = read_with_format(input_file, input_format)?; + + if firmware.len() < device_spec.platform.firmware_size { + log::warn!( + "Firmware size is less than expected ({}). Increasing to {}", + firmware.len(), + device_spec.platform.firmware_size + ); + firmware.resize(device_spec.platform.firmware_size, 0); + } + + match direction { + "to_jtag" => { + convert_to_jtag_payload(&mut firmware, device_spec).map_err(CLIError::from)?; + if firmware.len() < device_spec.total_flash_size() { + eprintln!( + "Firmware is smaller ({} bytes) than expected ({} bytes). This payload might not be suitable for JTAG flashing.", + firmware.len(), + device_spec.total_flash_size() + ); + } + } + "to_isp" => { + convert_to_isp_payload(&mut firmware, device_spec).map_err(CLIError::from)?; + if firmware.len() > device_spec.platform.firmware_size { + eprintln!( + "Firmware size is larger ({} bytes) than expected ({} bytes). This payload might not be suitable for ISP flashing.", + firmware.len(), + device_spec.platform.firmware_size + ); + } + } + _ => unreachable!(), + } + + write_with_format(output_file, &firmware, output_format)?; } _ => unreachable!(), } + Ok(()) +} + +trait DeviceCommand { + fn device_args(self) -> Command; +} + +impl DeviceCommand for Command { + fn device_args(self) -> Command { + self.arg( + arg!(-d --device ) + .required_unless_present_all(["platform", "vendor_id", "product_id"]) + .value_parser(DeviceSpec::available_devices()), + ) + .arg( + arg!(-p --platform ) + .value_parser(PlatformSpec::available_platforms()) + .required_unless_present("device"), + ) + .arg( + arg!(--vendor_id ) + .required_unless_present("device") + .value_parser(maybe_hex::), + ) + .arg( + arg!(--product_id ) + .required_unless_present("device") + .value_parser(maybe_hex::), + ) + .arg( + arg!(--firmware_size ) + .required_unless_present_any(["device", "platform"]) + .value_parser(maybe_hex::), + ) + .arg(arg!(--bootloader_size ).value_parser(maybe_hex::)) + .arg(arg!(--page_size ).value_parser(maybe_hex::)) + .arg(arg!(--isp_iface_num ).value_parser(clap::value_parser!(i32))) + .arg(arg!(--isp_report_id ).value_parser(maybe_hex::)) + .arg(arg!(--reboot ).value_parser(value_parser!(bool))) + } +} + +fn get_format_from_matches( + sub_matches: &ArgMatches, + file_path: &str, + format_option: &str, +) -> Format { + let input_ext = Path::new(file_path).extension(); + + let assumed_format = input_ext + .map(|ext| { + if ext == "ihex" || ext == "ihx" || ext == "hex" { + Format::IntelHex + } else { + Format::Binary + } + }) + .unwrap_or(Format::Binary); + + let format = sub_matches + .get_one::(format_option) + .map(|s| s.as_str()) + .map(|f| Format::from_str(f).unwrap()) + .unwrap_or(assumed_format); + + match (assumed_format, format) { + (Format::IntelHex, Format::Binary) => { + eprintln!( + "Warning: binary file has {} extension. This might be unintended.", + input_ext.unwrap().to_string_lossy() + ); + } + (Format::Binary, Format::IntelHex) => { + eprintln!("Warning: ihex file does not have .ihex or .ihx or .hex extension. This might be unintended."); + } + _ => {} + } + + format +} + +fn get_device_spec_from_matches(sub_matches: &ArgMatches) -> DeviceSpec { + let device_name = sub_matches.get_one::("device").map(|s| s.as_str()); + let platform_name = sub_matches + .get_one::("platform") + .map(|s| s.as_str()); + + let vendor_id = sub_matches.get_one::("vendor_id"); + let product_id = sub_matches.get_one::("product_id"); + + let firmware_size = sub_matches.get_one::("firmware_size"); + let bootloader_size = sub_matches.get_one::("bootloader_size"); + let page_size = sub_matches.get_one::("page_size"); + + let isp_iface_num = sub_matches.get_one::("isp_iface_num"); + let isp_report_id = sub_matches.get_one::("isp_report_id"); + let reboot = sub_matches.get_one::("reboot"); + + let mut device_spec = None; + if let Some(device_name) = device_name { + device_spec = Some(*DEVICES.get(device_name).unwrap()); + } + + if let Some(platform_name) = platform_name { + device_spec = match platform_name { + "sh68f90" => Some(DEVICE_BASE_SH68F90), + "sh68f881" => Some(DEVICE_BASE_SH68F881), + _ => panic!("Invalid platform"), + } + } + + let mut device_spec = device_spec.unwrap(); + + if let Some(vendor_id) = vendor_id { + device_spec.vendor_id = *vendor_id; + } + if let Some(product_id) = product_id { + device_spec.product_id = *product_id; + } + + if let Some(firmware_size) = firmware_size { + device_spec.platform.firmware_size = *firmware_size; + } + if let Some(bootloader_size) = bootloader_size { + device_spec.platform.bootloader_size = *bootloader_size; + } + if let Some(page_size) = page_size { + device_spec.platform.page_size = *page_size; + } + + if let Some(isp_iface_num) = isp_iface_num { + device_spec.isp_iface_num = *isp_iface_num; + } + if let Some(isp_report_id) = isp_report_id { + device_spec.isp_report_id = *isp_report_id; + } + if let Some(reboot) = reboot { + device_spec.reboot = *reboot; + } + + device_spec +} + +fn read_with_format(file: &str, format: Format) -> Result, CLIError> { + let mut file = fs::File::open(file).map_err(CLIError::from)?; + let mut file_buf = Vec::new(); + file.read_to_end(&mut file_buf).map_err(CLIError::from)?; + + match format { + Format::IntelHex => { + let file_str = String::from_utf8_lossy(&file_buf[..]); + from_ihex(&file_str, 0x10000).map_err(CLIError::from) + } + Format::Binary => Ok(file_buf), + } +} + +fn write_with_format(file: &str, data: &[u8], format: Format) -> Result<(), CLIError> { + match format { + Format::IntelHex => { + let ihex = to_ihex(data).map_err(CLIError::from)?; + fs::write(file, ihex).map_err(CLIError::from) + } + Format::Binary => fs::write(file, data).map_err(CLIError::from), + } } diff --git a/src/part.rs b/src/part.rs deleted file mode 100644 index 101d689..0000000 --- a/src/part.rs +++ /dev/null @@ -1,36 +0,0 @@ -use phf::*; - -pub struct Part { - pub flash_size: usize, - pub bootloader_size: usize, - pub page_size: usize, - pub vendor_id: u16, - pub product_id: u16, -} - -pub const PART_NUPHY_AIR60: Part = Part { - flash_size: 61440, // 61440 until bootloader - bootloader_size: 4096, - page_size: 2048, - vendor_id: 0x05ac, - product_id: 0x024f, -}; - -pub const PART_XINMENG_K916: Part = Part { - flash_size: 61440, // 61440 until bootloader - bootloader_size: 4096, - page_size: 2048, - vendor_id: 0x258a, - product_id: 0x00a1, -}; - -pub static PARTS: phf::Map<&'static str, Part> = phf_map! { - "nuphy-air60" => PART_NUPHY_AIR60, - "xinmeng-k916" => PART_XINMENG_K916 -}; - -impl Part { - pub fn num_pages(&self) -> usize { - return self.flash_size / self.page_size; - } -} diff --git a/src/platform_spec.rs b/src/platform_spec.rs new file mode 100644 index 0000000..4f21adc --- /dev/null +++ b/src/platform_spec.rs @@ -0,0 +1,40 @@ +use phf::{phf_map, Map}; + +const DEFAULT_BOOTLOADER_SIZE: usize = 4096; +const DEFAULT_PAGE_SIZE: usize = 2048; + +#[derive(Clone, Copy, PartialEq)] +pub struct PlatformSpec { + pub firmware_size: usize, + pub bootloader_size: usize, + pub page_size: usize, +} + +const PLATFORM_DEFAULT: PlatformSpec = PlatformSpec { + firmware_size: 0, + bootloader_size: DEFAULT_BOOTLOADER_SIZE, + page_size: DEFAULT_PAGE_SIZE, +}; + +pub const PLATFORM_SH68F90: PlatformSpec = PlatformSpec { + firmware_size: 65536 - PLATFORM_DEFAULT.bootloader_size, // 61440 until bootloader + ..PLATFORM_DEFAULT +}; + +pub const PLATFORM_SH68F881: PlatformSpec = PlatformSpec { + firmware_size: 32768 - PLATFORM_DEFAULT.bootloader_size, // 28672 until bootloader + ..PLATFORM_DEFAULT +}; + +pub static PLATFORMS: Map<&'static str, PlatformSpec> = phf_map! { + "sh68f90" => PLATFORM_SH68F90, + "sh68f881" => PLATFORM_SH68F881, +}; + +impl PlatformSpec { + pub fn available_platforms() -> Vec<&'static str> { + let mut platforms = PLATFORMS.keys().copied().collect::>(); + platforms.sort(); + platforms + } +} diff --git a/src/programmer.rs b/src/programmer.rs deleted file mode 100644 index 494fb8e..0000000 --- a/src/programmer.rs +++ /dev/null @@ -1,234 +0,0 @@ -use log::*; -use std::{thread, time}; - -use crate::HidDevice; - -use super::part::*; -use super::util; - -pub struct Programmer<'a> { - device: HidDevice, - part: &'a Part, -} - -const MAX_RETRIES: usize = 10; - -const GAMING_KB_VENDOR_ID: u16 = 0x0603; -const GAMING_KB_PRODUCT_ID: u16 = 0x1020; - -const COMMAND_LENGTH: usize = 6; - -const REPORT_ID_CMD: u8 = 0x05; -const REPORT_ID_XFER: u8 = 0x06; - -const CMD_ISP_MODE: u8 = 0x75; -const CMD_MAGIC_SAUCE: u8 = 0x55; // unsure how this command works, hence the name -const CMD_INIT_READ: u8 = 0x52; -const CMD_INIT_WRITE: u8 = 0x57; -const CMD_ERASE: u8 = 0x45; - -const XFER_READ_PAGE: u8 = 0x72; -const XFER_WRITE_PAGE: u8 = 0x77; - -#[derive(Debug, Clone)] -pub enum ReadType { - Normal, - Bootloader, - Full -} - -impl Programmer<'static> { - pub fn new(part: &'static Part) -> Self { - let device = Self::find_isp_device(part); - return Self { - device: device, - part: &part, - }; - } - - fn find_isp_device(part: &Part) -> HidDevice { - for attempt in 1..MAX_RETRIES+1 { - if attempt > 1 { - info!("Retrying... Attempt {}/{}", attempt, MAX_RETRIES); - } - - let kb_device_info = HidDevice::open(part.vendor_id, part.product_id); - - let Some(device_info) = kb_device_info else { - info!("No KB found. Trying bootloader directly..."); - let device = HidDevice::open(GAMING_KB_VENDOR_ID, GAMING_KB_PRODUCT_ID).unwrap(); - info!("Connected!"); - return device; - }; - - info!("Found Device. Entering ISP mode..."); - Self::enter_isp_mode(&device_info); - - info!("Waiting for bootloader device..."); - thread::sleep(time::Duration::from_millis(1000)); - - let kb_device_info = HidDevice::open(GAMING_KB_VENDOR_ID, GAMING_KB_PRODUCT_ID); - - let Some(_) = kb_device_info else { - info!("Device didn't come up..."); - continue; - }; - - let device = HidDevice::open(GAMING_KB_VENDOR_ID, GAMING_KB_PRODUCT_ID).unwrap(); - info!("Connected!"); - - return device; - } - panic!("Couldn't find ISP device"); - } - - fn enter_isp_mode(handle: &HidDevice) { - let cmd: [u8; COMMAND_LENGTH] = [REPORT_ID_CMD, CMD_ISP_MODE, 0x00, 0x00, 0x00, 0x00]; - let _ = handle.send_feature_report(&cmd); // ignore errors, many might be encountered here - } - - pub fn read_cycle(&self, read_type: ReadType) -> Vec { - self.magic_sauce(); - - return match read_type { - ReadType::Normal => self.read(0, self.part.flash_size), - ReadType::Bootloader => self.read(self.part.flash_size, self.part.bootloader_size), - ReadType::Full => self.read(0, self.part.flash_size + self.part.bootloader_size) - }; - } - - pub fn write_cycle(&self, firmware: &mut Vec) { - let length = firmware.len(); - - assert_eq!( - self.part.flash_size, length, - "Wrong firmware size. Expected {}, but got {}", - self.part.flash_size, length - ); - - // this is a bit of an arcane part and I'm not certain why this happens - firmware.copy_within(0..3, length - 5); - firmware[(length - 5)..(length - 2)].fill(0); - - self.erase(); - self.write(&firmware); - let written = self.read(0, self.part.flash_size); - - info!("Verifying..."); - match util::verify(&firmware, &written) { - Err(e) => { - error!("{}", e.to_message()); - return; - } - Ok(_) => {} - }; - self.finalize(); - } - - pub fn erase_cycle(&self) { - info!("Erasing..."); - self.erase(); - self.finalize(); - } - - /// Allows firmware to be read prior to erasing it - fn magic_sauce(&self) { - let cmd: [u8; COMMAND_LENGTH] = [ - REPORT_ID_CMD, - CMD_MAGIC_SAUCE, - 0x00, - 0x00, - (self.part.flash_size & 0xff) as u8, - (self.part.flash_size >> 8) as u8, - ]; - - self.device.send_feature_report(&cmd).unwrap(); - } - - fn read(&self, start_addr: usize, length: usize) -> Vec { - let cmd: [u8; COMMAND_LENGTH] = [ - REPORT_ID_CMD, - CMD_INIT_READ, - (start_addr & 0xff) as u8, - (start_addr >> 8) as u8, - (length & 0xff) as u8, - (length >> 8) as u8, - ]; - self.device.send_feature_report(&cmd).unwrap(); - - let page_size = self.part.page_size; - let num_page = length / page_size; - let mut result: Vec = vec![]; - for i in 0..num_page { - debug!("Reading page {} @ offset {:#06x}", i, start_addr + i * page_size); - self.read_page(&mut result); - } - return result; - } - - fn read_page(&self, buf: &mut Vec) { - let page_size = self.part.page_size; - let mut xfer_buf: Vec = vec![0; page_size + 2]; - xfer_buf[0] = REPORT_ID_XFER; - xfer_buf[1] = XFER_READ_PAGE; - self.device.get_feature_report(&mut xfer_buf).unwrap(); - buf.extend_from_slice(&xfer_buf[2..(page_size + 2)]); - } - - fn write(&self, buffer: &Vec) { - info!("Writing..."); - let cmd: [u8; COMMAND_LENGTH] = [ - REPORT_ID_CMD, - CMD_INIT_WRITE, - 0, - 0, - (self.part.flash_size & 0xff) as u8, - (self.part.flash_size >> 8) as u8, - ]; - - self.device.send_feature_report(&cmd).unwrap(); - - let page_size = self.part.page_size; - for i in 0..self.part.num_pages() { - debug!("Writting page {} @ offset {:#06x}", i, i * page_size); - self.write_page(&buffer[(i * page_size)..((i + 1) * page_size)]); - } - } - - fn write_page(&self, buf: &[u8]) { - let page_size = self.part.page_size; - let mut xfer_buf: Vec = vec![0; page_size + 2]; - xfer_buf[0] = REPORT_ID_XFER; - xfer_buf[1] = XFER_WRITE_PAGE; - xfer_buf[2..page_size + 2].clone_from_slice(&buf); - self.device.send_feature_report(&xfer_buf).unwrap(); - } - - fn erase(&self) { - info!("Erasing..."); - let cmd: [u8; COMMAND_LENGTH] = [ - REPORT_ID_CMD, - CMD_ERASE, - CMD_ERASE, - CMD_ERASE, - CMD_ERASE, - CMD_ERASE, - ]; - self.device.send_feature_report(&cmd).unwrap(); - thread::sleep(time::Duration::from_millis(2000)); - } - - // TODO: verify what this command does and if it's actually needed - fn finalize(&self) { - info!("Finalizing..."); - let cmd: [u8; COMMAND_LENGTH] = [ - REPORT_ID_CMD, - CMD_MAGIC_SAUCE, - CMD_MAGIC_SAUCE, - CMD_MAGIC_SAUCE, - CMD_MAGIC_SAUCE, - CMD_MAGIC_SAUCE, - ]; - self.device.send_feature_report(&cmd).unwrap(); - } -} diff --git a/src/util.rs b/src/util.rs index f9ceb60..50694c4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,59 +1,178 @@ -use ihex::*; +use crate::DeviceSpec; +use hidapi::HidError; +use log::error; +use thiserror::Error; -pub trait IHexConversion { - // fn from_ihex() -> Self; - fn to_ihex(&self) -> Vec; +#[cfg(test)] +use crate::device_spec::DEVICE_BASE_SH68F90; + +#[derive(Debug, Clone, Error, PartialEq)] +pub enum VerificationError { + #[error("Firmware Mismatch @ {addr:#06x} --- {expected:#04x} != {actual:#04x}")] + ByteMismatch { + addr: usize, + expected: u8, + actual: u8, + }, + #[error("Length Mismatch {expected} {actual}")] + LengthMismatch { expected: usize, actual: usize }, } -impl IHexConversion for Vec { - fn to_ihex(&self) -> Vec { - let mut result: Vec = vec![]; - for (i, chunk) in self.chunks(16).enumerate() { - result.push(Record::Data { - offset: (i as u16) * 16, - value: chunk.to_vec(), +pub fn verify(expected: &[u8], actual: &[u8]) -> Result<(), VerificationError> { + if expected.len() != actual.len() { + return Err(VerificationError::LengthMismatch { + expected: expected.len(), + actual: actual.len(), + }); + } + + for i in 0..expected.len() { + if expected[i] != actual[i] { + return Err(VerificationError::ByteMismatch { + addr: i, + expected: expected[i], + actual: actual[i], }); } - result.push(Record::EndOfFile); - return result; } + + Ok(()) } -#[derive(Debug, Clone)] -pub enum VerificationError { - ByteMismatch(usize, u8, u8), - LengthMismatch(usize, usize), +#[derive(Debug, Error)] +pub enum PayloadConversionError { + #[error("Expected LJMP not found at {addr:#06x}")] + LJMPNotFoundError { addr: u16 }, + #[error("Unexpected addr at {source_addr:#06x} pointing to {target_addr:#06x}")] + UnexpectedAddressError { source_addr: u16, target_addr: u16 }, } -impl VerificationError { - pub fn to_message(&self) -> String { - return match self { - Self::LengthMismatch(expected, actual) => { - format!("LENGTH MISMATCH {} {}", expected, actual) - } - Self::ByteMismatch(addr, expected, actual) => { - format!( - "FIRMWARE MISMATCH @ 0x{:04x} --- {:02x} != {:02x}", - addr, expected, actual - ) - } - }; +pub fn convert_to_jtag_payload( + input: &mut [u8], + device_spec: DeviceSpec, +) -> Result<(), PayloadConversionError> { + if input[0] != 0x02 { + return Err(PayloadConversionError::LJMPNotFoundError { addr: 0x0000 }); + } + + let main_fw_address = u16::from_be_bytes(input[1..3].try_into().unwrap()); + if main_fw_address > 0xefff { + return Err(PayloadConversionError::UnexpectedAddressError { + source_addr: 0x0001, + target_addr: main_fw_address, + }); } + + let bootloader_ljmp_addr = (device_spec.platform.firmware_size as u16).to_be_bytes(); + let ljmp_addr = device_spec.platform.firmware_size - 5; + + input[1..3].copy_from_slice(&bootloader_ljmp_addr); + input[ljmp_addr] = 0x02; + input[ljmp_addr + 1..ljmp_addr + 3].copy_from_slice(&main_fw_address.to_be_bytes()); + + Ok(()) } -pub fn verify(expected: &Vec, actual: &Vec) -> Result<(), VerificationError> { - if expected.len() != actual.len() { - return Err(VerificationError::LengthMismatch( - expected.len(), - actual.len(), - )); +pub fn convert_to_isp_payload( + input: &mut [u8], + device_spec: DeviceSpec, +) -> Result<(), PayloadConversionError> { + if input[0] != 0x02 { + return Err(PayloadConversionError::LJMPNotFoundError { addr: 0 }); } - for i in 0..expected.len() { - if expected[i] != actual[i] { - return Err(VerificationError::ByteMismatch(i, expected[i], actual[i])); - } + let ljmp_addr = device_spec.platform.firmware_size - 5; + if input[ljmp_addr] != 0x02 { + return Err(PayloadConversionError::LJMPNotFoundError { addr: 0x0000 }); + } + + let main_fw_address = + u16::from_be_bytes(input[ljmp_addr + 1..ljmp_addr + 3].try_into().unwrap()); + if main_fw_address > 0xefff { + return Err(PayloadConversionError::UnexpectedAddressError { + source_addr: (ljmp_addr + 1) as u16, + target_addr: main_fw_address, + }); } - return Ok(()); + input[1..3].copy_from_slice(&main_fw_address.to_be_bytes()); + input[ljmp_addr..ljmp_addr + 3].fill(0x00); + + Ok(()) +} + +pub fn to_hex_string(bytes: &[u8]) -> String { + let strs: Vec = bytes.iter().map(|b| format!("{:02X}", b)).collect(); + strs.join(" ") +} + +pub fn is_expected_error(err: &HidError) -> bool { + match err { + #[cfg(target_os = "macos")] + HidError::HidApiError { ref message } if message == "IOHIDDeviceSetReport failed: (0xE0005000) unknown error code" => true, + #[cfg(target_os = "linux")] + HidError::HidApiError { ref message } if message == "hid_error is not implemented yet" => true, + #[cfg(target_os = "windows")] + HidError::HidApiError { ref message } if message == "HidD_SetFeature: (0x0000001F) A device attached to the system is not functioning." => true, + _ => false, + } +} + +#[test] +fn test_verify_success() { + assert!(verify(&vec![1, 2, 3, 4], &vec![1, 2, 3, 4]).is_ok()); +} + +#[test] +fn test_verify_error_length_mismatch() { + assert_eq!( + verify(&vec![1, 2, 3, 4], &vec![1, 2, 3]), + Err(VerificationError::LengthMismatch { + expected: 4, + actual: 3 + }) + ); +} + +#[test] +fn test_verify_error_byte_mismatch() { + assert_eq!( + verify(&vec![1, 2, 3, 4], &vec![1, 2, 4, 3]), + Err(VerificationError::ByteMismatch { + addr: 2, + expected: 3, + actual: 4 + }) + ); +} + +#[test] +fn test_convert_to_jtag_payload() { + let device_spec = DEVICE_BASE_SH68F90; + let mut firmware: [u8; 65536] = [0; 65536]; + firmware[0] = 0x02; + firmware[1] = 0x00; + firmware[2] = 0x66; + + convert_to_jtag_payload(&mut firmware, device_spec).unwrap(); + + assert_eq!(firmware[0..3], [0x02, 0xf0, 0x00]); + assert_eq!(firmware[0xeffb..0xeffe], [0x02, 0x00, 0x66]); +} + +#[test] +fn test_convert_to_isp_payload() { + let device_spec = DEVICE_BASE_SH68F90; + let mut firmware: [u8; 65536] = [0; 65536]; + firmware[0] = 0x02; + firmware[1] = 0xf0; + firmware[2] = 0x00; + firmware[0xeffb] = 0x02; + firmware[0xeffc] = 0x00; + firmware[0xeffd] = 0x66; + + convert_to_isp_payload(&mut firmware, device_spec).unwrap(); + + assert_eq!(firmware[0..3], [0x02, 0x00, 0x66]); + assert_eq!(firmware[0xeffb..0xeffe], [0x00, 0x00, 0x00]); } diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..674dcd7 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,23 @@ +macro_rules! test_filename { + ($format:expr) => {{ + let date = chrono::Utc::now().to_rfc3339().replace(":", "-"); + let mut path = std::env::temp_dir(); + path.push(format!( + "sinowealth-kb-tool-{}-{}.{}", + date, + stdext::function_name!() + .replace(":", "_") + .replace("__{{closure}}", ""), + $format + )); + path.display().to_string() + }}; +} + +pub fn get_fixture_path(filename: &str) -> String { + let mut path = std::env::current_dir().unwrap(); + path.push("tests"); + path.push("fixtures"); + path.push(filename); + path.display().to_string() +} diff --git a/tests/convert_test.rs b/tests/convert_test.rs new file mode 100644 index 0000000..a9330fc --- /dev/null +++ b/tests/convert_test.rs @@ -0,0 +1,78 @@ +use std::fs; + +use assert_cmd::Command; +use serial_test::serial; + +#[macro_use] +pub mod common; + +use common::get_fixture_path; + +#[test] +#[serial] +fn test_convert_to_jtag() { + let input_file = get_fixture_path("nuphy-air60_smk.hex"); + let output_file = test_filename!("hex"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("convert") + .args(&["--device", "nuphy-air60"]) + .args(&["--direction", "to_jtag"]) + .arg(&input_file) + .arg(&output_file) + .assert(); + + assert.success(); + + let computed_md5 = md5::compute(fs::read(&output_file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "3bbd99f81678fc11fdf1ba9eaaac2bd1" + ); +} + +#[test] +#[serial] +fn test_convert_to_isp() { + let input_file = get_fixture_path("nuphy-air60_smk_jtag.hex"); + let output_file = test_filename!("hex"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("convert") + .args(&["--device", "nuphy-air60"]) + .args(&["--direction", "to_isp"]) + .arg(&input_file) + .arg(&output_file) + .assert(); + + assert.success(); + + let computed_md5 = md5::compute(fs::read(&output_file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "6594e5a1ab671deb40f36483a84ad61f" + ); +} + +#[test] +#[serial] +fn test_convert_to_jtag_bin() { + let input_file = get_fixture_path("nuphy-air60_smk.hex"); + let output_file = test_filename!("bin"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("convert") + .args(&["--device", "nuphy-air60"]) + .args(&["--direction", "to_jtag"]) + .arg(&input_file) + .arg(&output_file) + .assert(); + + assert.success(); + + let computed_md5 = md5::compute(fs::read(&output_file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "df1ff7b247ae12dda37aa69730f090af" + ); +} diff --git a/tests/fixtures/nuphy-air60_smk.bin b/tests/fixtures/nuphy-air60_smk.bin new file mode 100644 index 0000000..d56720e Binary files /dev/null and b/tests/fixtures/nuphy-air60_smk.bin differ diff --git a/tests/fixtures/nuphy-air60_smk.hex b/tests/fixtures/nuphy-air60_smk.hex new file mode 100644 index 0000000..44bf2c2 --- /dev/null +++ b/tests/fixtures/nuphy-air60_smk.hex @@ -0,0 +1,3841 @@ +:100000000200713200000000000000320000000019 +:10001000000000320000000000000032000000007C +:10002000000000320000000000000032000000006C +:100030000000003200000000000000021329000050 +:10004000000000020F5E000000000032000000000F +:10005000000000320000000000000032000000003C +:100060000000003200000000000000020FDA020170 +:10007000F7758185123BFBE582600302006E79040F +:10008000E94400601B7A0190413F78A775A002E423 +:1000900093F2A308B8000205A0D9F4DAF275A0FF24 +:1000A000E478FFF6D8FD7800E84400600A7900752E +:1000B000A000E4F309D8FC78A7E84402600C7903B7 +:1000C000900000E4F0A3D8FCD9FA750D00750E007D +:1000D00075337575343E75357F75363EE4F51AF522 +:1000E0001BE4F540F54102006EAF82BFA502800A15 +:1000F000BFA6028009BFA70E8008900001229000D1 +:1001000002229000042290000022AF82BFA800507B +:10011000030201CFEF243D50030201CFEF2458FF2B +:10012000240A83F582EF241F83F583E47363676BEE +:100130006F737F878B838F9397A3A7ABAFB3B7C33F +:10014000777BBBBF9B9FC7CB01010101010101016F +:10015000010101010101010101010101010101018F +:100160000101019000E2229000E9229000EA229031 +:1001700000B5229000B6229000B3229000B42290E5 +:1001800000B7229000CC229000CD229001832290D3 +:10019000018A22900192229001942290019F229044 +:1001A00001CB22900221229002232290022422904D +:1001B000022522900226229002272290006F229090 +:1001C00000702290022A2290029F229002A0229088 +:1001D000000022120F5A120EDD120F9D1229C212B8 +:1001E0000483120ECE1210D543B54043B94043B537 +:1001F0004085B9B9D2AF221201D374FFC0E0743B7D +:10020000C0E07480C0E012344115811581158174FD +:100210000CC0E0743CC0E07480C0E0123441158131 +:10022000158115819003E8120EF4122C3B121FCF9A +:10023000122DE29003E8120EF475B100122C4C124C +:100240002DB41207F280F2AF82BFA502800ABFA6CA +:10025000028009BFA70E80089000012290000222B0 +:100260009000042290000022AF82BFA80050030239 +:10027000032DEF243D500302032DEF2458FF240AE1 +:1002800083F582EF241F83F583E473C1C5C9CDD103 +:10029000DDE5E9E1EDF1F50105090D111521D5D9EE +:1002A000191DF9FD252902020202020202020202C0 +:1002B0000202030303030303030202030302020314 +:1002C000039000E2229000E9229000EA229000B51B +:1002D000229000B6229000B3229000B4229000B782 +:1002E000229000CC229000CD229001832290018A9E +:1002F00022900192229001942290019F229001CBA2 +:100300002290022122900223229002242290022590 +:1003100022900226229002272290006F22900070E5 +:100320002290022A2290029F229002A02290000096 +:1003300022022D5D022D7AAE82AF839002A7E0FCEF +:10034000A3E0FDEEB50405EFB50501229002A7EE8E +:10035000F0EFA3F09000007401F0900001EEF0EFD8 +:10036000A3F0900000022D97AE82AF839002A9E027 +:10037000FCA3E0FDEEB50405EFB50501229002A94E +:10038000EEF0EFA3F09000007402F0900001EEF0A8 +:10039000EFA3F0900000022D97AF82BFA502800A64 +:1003A000BFA6028009BFA70E80089000012290001E +:1003B00002229000042290000022AF82BFA80050C9 +:1003C0000302047FEF243D500302047FEF2458FF13 +:1003D000240A83F582EF241F83F583E47313171B2C +:1003E0001F232F373B333F434753575B5F6367738D +:1003F000272B6B6F4B4F777B040404040404040425 +:1004000004040404040404040404040404040404AC +:100410000404049000E2229000E9229000EA229075 +:1004200000B5229000B6229000B3229000B4229032 +:1004300000B7229000CC229000CD22900183229020 +:10044000018A22900192229001942290019F229091 +:1004500001CB22900221229002232290022422909A +:10046000022522900226229002272290006F2290DD +:1004700000702290022A2290029F229002A02290D5 +:10048000000022750800750900750A007E007F00D3 +:10049000C3EE9410EF64809480501FEE2403F58225 +:1004A000EF3400F583E4F0EE2413F582EF3400F529 +:1004B00083E4F00EBE00D90F80D622E5822403F536 +:1004C00082E43400F583E0F5822285098222E58208 +:1004D000C42354E0FF24B4FDE4343EFEE50B250BB9 +:1004E000FC2DF582E43EF583E493FDA3E493FEE561 +:1004F0000C60067A3C7B3C80047A3F7B3C8B017B22 +:1005000080C007C006C005C004C002C001C003C04F +:1005100005C006742BC0E0743CC0E0EBC0E01234B0 +:1005200041E58124F8F581D004D005D006D0078DAF +:10053000028E03C3EA9420EB9452403F743F9A74B6 +:10054000529B4037E50C60098D03741F5BF50A80F0 +:100550000C90002575F000120E3C750A00AA0A7B6B +:1005600000C002C0037444C0E0743CC0E07480C0AA +:10057000E0123441E58124FBF58122E50A6033E590 +:100580000A75F0A0A424B4FA743E35F0FBEF2AFA01 +:10059000E43BFBEC2AF582E43BF583E493FCA3E423 +:1005A00093FF8C028F03BA0105BB000280048C0507 +:1005B0008F06850C198D828E83C006C005122D1FF3 +:1005C000E582D005D006700122850C1C8D828E83B9 +:1005D000C006C005123230E582D005D00670012277 +:1005E0008D048E07C3EC94E0EF9400403E74E79CCA +:1005F000E49F4037E50C60198D0374075BF5F00547 +:10060000F07401800225E0D5F0FBF582120E8B809C +:10061000178D0374075BF5F005F07401800225E087 +:10062000D5F0FBF582120E90020A00C3EC9404EFA1 +:100630009400402674A49CE49F401FE50C600D8D3F +:100640001290002575F000120DCC800B8D139000D8 +:100650002575F000120E04020A00C3EC94A5EF9475 +:1006600000403F74A79CE49F4038E50C602E8D034A +:10067000BBA502800ABBA602800BBBA714800C7A24 +:10068000017B0080107A027B00800A7A047B008064 +:10069000047A007B008A828B830203379000000279 +:1006A0000337C3EC94A8EF940050030207D8C37437 +:1006B000C29CE49F50030207D8E50C70030207D1E7 +:1006C0008D07BFA80050030207C4EF243D5003026A +:1006D00007C4EF2458FF240A83F582EF241F83F513 +:1006E00083E4731920272E354A585E51646A70825C +:1006F000888E949AA0B23C43A6AC767CB8BE07071D +:100700000707070707070707070707070707070779 +:100710000707070707070707077CE27F000207C8EC +:100720007CE97F000207C87CEA7F000207C87CB52D +:100730007F000207C87CB67F000207C87CB37F0039 +:100740000207C87CB47F000207C87CB77F0002079D +:10075000C87CCC7F000207C87CCD7F00806A7C8388 +:100760007F0180647C8A7F01805E7C927F0180585B +:100770007C947F0180527C9F7F01804C7CCB7F01E9 +:1007800080467C217F0280407C237F02803A7C244B +:100790007F0280347C257F02802E7C267F02802889 +:1007A0007C277F0280227C6F7F00801C7C707F0012 +:1007B00080167C2A7F0280107C9F7F02800A7CA0AA +:1007C0007F0280047C007F008C828F83120368800C +:1007D0000690000002036822C005C0067458C0E0FD +:1007E000743CC0E07480C0E0123441E58124FBF524 +:1007F00081221204CAE5827003F58222900023E46C +:10080000F0FFBF10005039900023E0FEE07031EFA0 +:100810002413F582E43400F583E0FD8F82C007C025 +:1008200006C0051204BBAC82D005D006D007EC622E +:1008300005EE4205900023ED24FFE433F00F80C263 +:10084000900023E0FFE07005F5098F82227F00BF52 +:100850001000506C8F82C0071204BBAE82D007EF2D +:100860002413F582E43400F583E0FDEE6205ED60CB +:100870004C9000247401F07C00BC050050339000C3 +:1008800024E0FB5D6021EE5203EB24FFE433F50C22 +:100890008F0B8C82C007C006C005C0041204CED0E6 +:1008A00004D005D006D0070C900024E025E0F080AD +:1008B000C8EF2413F582E43400F583EEF00F808F47 +:1008C000750900900023E0F58222122DE5E50970FC +:1008D000238508821229398508821229A3AF82C094 +:1008E000071229B5D007E5082403F582E43400F5A2 +:1008F00083EFF4F085084290006175F000122DF747 +:1009000074F125084007E50804F50880067508001D +:1009100075090102300BAF82BFA502800ABFA60293 +:100920008009BFA70E80089000012290000222904B +:1009300000042290000022AF82BFA80050030209E9 +:10094000FCEF243D50030209FCEF2458FF240A83E6 +:10095000F582EF241F83F583E4739094989CA0ACF8 +:10096000B4B8B0BCC0C4D0D4D8DCE0E4F0A4A8E8EB +:10097000ECC8CCF4F80909090909090909090909A8 +:1009800009090909090909090909090909090909D7 +:100990009000E2229000E9229000EA229000B52225 +:1009A0009000B6229000B3229000B4229000B722AB +:1009B0009000CC229000CD229001832290018A22C7 +:1009C000900192229001942290019F229001CB22CB +:1009D00090022122900223229002242290022522BA +:1009E000900226229002272290006F22900070220F +:1009F00090022A2290029F229002A02290000022C0 +:100A00001211C5AF82BF0109900063E06003020AC2 +:100A100062020A14900025E50DF0E50D450E9000E8 +:100A200025F075752D7576007577007578087579E0 +:100A30000090002575F000123383E5828583F04530 +:100A4000F0601E75752575760075770075780875E8 +:100A5000790090002D75F00012329A900025020363 +:100A600031229000357406F0900036E50DF0E50D6A +:100A7000450E900036F075754B75760075770075EC +:100A8000781675790090003575F000123383E58291 +:100A90008583F045F0601E757535757600757700B5 +:100AA00075781675790090004B75F00012329A90A7 +:100AB000003502033422AD82AE83AFF074022DFD07 +:100AC000E43EFE7C06C007C006C005C0041211C586 +:100AD000AB82D004D005D006D007BB010E900063D6 +:100AE000E060087D377E007F007C147B008C021C58 +:100AF000EA60158D828E838FF0123BA9FAA3AD8236 +:100B0000AE83EA60E80B80E58B8222AD82AE83AFD4 +:100B1000F0C007C006C0051211C5AC82D005D006D2 +:100B2000D007BC0142900063E0603C7C00BC140034 +:100B30005012EC2437FAE43400FB8A828B83E07095 +:100B4000030C80E98C03EBC40354F8FBEC2437F569 +:100B500082E43400F583E0F582C003120EA2AC8279 +:100B6000D003EC4BF5822274022DFDE43EFE8D8213 +:100B70008E838FF0123BA9F58222AD82AE83AFF057 +:100B8000E50F7003F58222C007C006C0051211C52B +:100B9000AC82D005D006D007BC014B900063E0606A +:100BA00045E50FC423541FFCBC14005035EC24371A +:100BB000F582E43400F583E50F5407FC8CF005F072 +:100BC0007C017B008006EC2CFCEB33FBD5F0F7E0DE +:100BD000F97A00E95204EA5203EC4B24FFE433F5BE +:100BE00082227582002274022DFDE43EFE7B007C91 +:100BF00000C3EB9406EC64809480501FEB2DF8EC5E +:100C00003EF98F02888289838AF0123BA9B50F04CE +:100C1000758201220BBB00D90C80D675820022851B +:100C2000827685837785F0787CFF74022576F9E4F7 +:100C30003577FAAB7889798A7A8B7B7800C3E86458 +:100C40008094865033E829FDE43AFE8B078D828E2E +:100C5000838FF0123BA9B57502801DBCFF17E825F4 +:100C600079FDE4357AFEAF7B8D828E838FF0123B67 +:100C7000A9700288040880C5B80622BCFF0122744E +:100C8000022576FDE43577FEAF78EC2DFCE43EFBE3 +:100C90008F028C828B838AF0E57502330E22AD823F +:100CA000AE83AFF074022DFDE43EFE8D778E788F1B +:100CB0007975760074FA25764044C005C006C007F1 +:100CC000E5762577F8E43578F9AF79888289838FDE +:100CD000F0123BA9B575028008D007D006D0058078 +:100CE00019D007D006D005E5762DF8E43EF98F043B +:100CF000888289838CF0E412330E057680B622ADAB +:100D000082AE83AFF0E510C423541FFCBC14005026 +:100D10003674022DFDE43EFEEC2DFCE43EFB8F021A +:100D2000E5105407F5F005F07401800225E0D5F0D8 +:100D3000FBFF8C828B838AF0123BA942078C828B4B +:100D4000838AF0EF02330EAE107F00C006C0077436 +:100D500073C0E0743CC0E07480C0E0123441E581AF +:100D600024FBF58122AD82AE83AFF0E511C423549C +:100D70001FFCBC1400503774022DFDE43EFEEC2D28 +:100D8000FCE43EFB8F02E5115407F5F005F0740119 +:100D9000800225E0D5F0FBF4FF8C828B838AF01271 +:100DA0003BA952078C828B838AF0EF02330EAE117F +:100DB0007F00C006C0077491C0E0743CC0E074803E +:100DC000C0E0123441E58124FBF58122AD82AE837F +:100DD000AFF0C007C006C0051211C5AC82D005D067 +:100DE00006D007BC0112900063E0600C85121090E1 +:100DF000003575F000020CFF8512758D828E838F91 +:100E0000F0020C1FAD82AE83AFF0C007C006C00574 +:100E10001211C5AC82D005D006D007BC01129000DB +:100E200063E0600C85131190003575F000020D65CC +:100E30008513758D828E838FF0020C9EAD82AE83FA +:100E4000AFF0C007C006C0051211C5AC82D005D0F6 +:100E500006D007BC0118900063E06012757500753C +:100E6000761475770090003775F0000232EF740247 +:100E70002DFDE43EFE7575007576067577008D8252 +:100E80008E838FF00232EF850D8222E582420D22A1 +:100E9000E582F4520D2285820D22750D0022850E09 +:100EA0008222AF827E00EFC4540FFD60048D077E66 +:100EB00004EF0303543FFD60088D078E0574022D77 +:100EC000FEEFC31360058E07EF04FE8E82229000B2 +:100ED00061E4F0900062F090006304F02275B208C3 +:100EE00075BC02E5BC20E20575B10080F643BC018B +:100EF00043B20422AE82AF837C007D00C3EC9EED42 +:100F00009F501D9003E8C007C006C005C004120F23 +:100F100021D004D005D006D0070CBC00DF0D80DC4A +:100F200022AE82AF837C007D00C3EC9EED9F501FFC +:100F300075B100000000000000000000000000008B +:100F400000000000000000000CBC00DD0D80DA2273 +:100F5000C2AF75F0A5745A02FF00758F0122C0213F +:100F6000C0E0C0F0C082C083C007C006C005C00496 +:100F7000C003C002C001C000C0D075D0001208CAB2 +:100F8000D0D0D000D001D002D003D004D005D006FC +:100F9000D007D083D082D0F0D0E0D0213275D840B5 +:100FA00075ADFF75AEE675AF0075870075AB007562 +:100FB000AC0053A9BFC20010D902800010D8028033 +:100FC0000043A94022AF8253A9BFD2008FAA43A9F0 +:100FD0004030000575B10080F82253A9BF10D90236 +:100FE0008002C20043A94032020FC5AF82BFA502F2 +:100FF000800ABFA6028009BFA70E800890000122C8 +:10100000900002229000042290000022AF82BFA82C +:101010000050030210D1EF243D50030210D1EF2401 +:1010200058FF240A83F582EF241F83F583E4736558 +:10103000696D717581898D85919599A5A9ADB1B5B8 +:10104000B9C5797DBDC19DA1C9CD1010101010107A +:101050001010101010101010101010101010101090 +:1010600010101010109000E2229000E9229000EA87 +:10107000229000B5229000B6229000B3229000B4D6 +:10108000229000B7229000CC229000CD22900183C4 +:101090002290018A22900192229001942290019F35 +:1010A000229001CB2290022122900223229002243E +:1010B0002290022522900226229002272290006F81 +:1010C000229000702290022A2290029F229002A079 +:1010D0002290000022900264E4F0900265F09002F9 +:1010E00066F0900267F0900268F0C20190026AE434 +:1010F000F0900269F0F522F523F524F525F526F5A3 +:101100009675945F7595117591C043A90122AE82C1 +:10111000AF837D00BDFF00501AE59930E2159000C5 +:1011200028C007C006C005120F21D005D006D00781 +:101130000D80E17D007531088E828F838DF0121D48 +:1011400066539CE0439C0843990422AE82AF837DA2 +:1011500000BDFF00501AE59A30E215900028C00744 +:10116000C006C005120F21D005D006D0070D80E1C2 +:101170007D007532168E828F838DF0121DCF539DA8 +:1011800080439D16439A0422AE82AF837D00BDFF4B +:1011900000501AE59A30E215900028C007C006C03A +:1011A00005120F21D005D006D0070D80E17D007516 +:1011B00032038E828F838DF0121DCF539D80439D0D +:1011C00003439A0422900267E0F58222C2AF9002A4 +:1011D0006B75F000121D48D2AF90026BE0FF9002D9 +:1011E0006CE0FE8F05BD0002802CBD01030212766B +:1011F000BF02030212ABBF21030212D8BF800280DC +:1012000050BF8103021286BF82030212C8BFA1032E +:10121000021300021322BE01028014BE03028015D5 +:10122000BE05028016BE07028017BE091D801590FC +:10123000026B02144090026B02146E90026B021457 +:10124000050215EE90026B0215484397084397027A +:1012500022BE0002800ABE0602800BBE0811800C6E +:1012600090026B0215F590026B02171B021AD04315 +:10127000970843970222BE0B0690026B0215A0430B +:10128000970843970222BE0002800ABE0602800B26 +:10129000BE0A11800C90026B02163090026B02178E +:1012A0001B021AE843970843970222BE01028005F9 +:1012B000BE030E800690026B02149C90026B021417 +:1012C000FA43970843970222BE000690026B02166B +:1012D0007343970843970222BE0902800ABE0A029E +:1012E000800BBE0B14800C90026B021B0490026BEF +:1012F000021B5F90026B021B8143970843970222F7 +:10130000BE0102800ABE02028008BE030E800602F1 +:101310001AFD021B6F90026B021BB643970843979E +:10132000022243970843970222C021C0E0C0F0C0C8 +:1013300082C083C007C006C005C004C003C002C08D +:1013400001C000C0D075D000AF92AE93EF6056EFF1 +:1013500030E3065392F70213E85392EF53929FEF54 +:1013600030E70953927F1210D50213E8EF30E408FA +:101370005392EF1211CC8070EF30E2055392FB8054 +:1013800067EF30E1055392FD805EEF30E05A5392F3 +:10139000FE4391200000000000005391DF1210D5A1 +:1013A0004397018043EE6040EE30E6085393BF431D +:1013B0009A018034EE30E5055393DF802BEE30E464 +:1013C0000B5393EF121BE4439701801CEE30E205B0 +:1013D0005393FB8013EE30E1055393FD800AEE300A +:1013E000E0065393FE121C27D0D0D000D001D002CB +:1013F000D003D004D005D006D007D083D082D0F05F +:10140000D0E0D02132AE82AF8390026AE4F0740261 +:101410002EFEE43FFF8E828F83E0FCA3E04C600849 +:101420009002647401F08005900264E4F08E828F73 +:1014300083E0900265F0539BF043970243970422A8 +:10144000AE82AF8390026AE4F08E828F83E0540F05 +:10145000600280138E828F83A3A3E0FEA3E0FFBE11 +:101460000105BF0002C201539BF043970422AE82E4 +:10147000AF8390026AE4F08E828F83E0540F6002A3 +:1014800080138E828F83A3A3E0FEA3E0FFBE01053D +:10149000BF0002D201539BF043970422AE82AF8378 +:1014A00090026AE4F08E828F83E0FD53050FBD0247 +:1014B000428E828F83A3A3E0FCA3E04C70358E8222 +:1014C0008F83A3A3A3A3E0FEA3E0FF4E700853976E +:1014D000F75397FD801DBE8108BF00055399F78023 +:1014E00012BE8208BF0005539AF78007439708434E +:1014F000970222539BF043970422AE82AF8390025F +:101500006AE4F08E828F83E0FD53050FBD022B8EBF +:10151000828F83A3A3A3A3E0FEA3E0FFBE8108BF45 +:101520000005439908801ABE8208BF0005439A0847 +:10153000800F439708439702800743970843970219 +:1015400022539BF043970422AE82AF8390026AE459 +:10155000F0E596603E8E828F83A3A3E0FEA3E0FFBA +:101560004E600A8E048F05BC0121BD001E900266EC +:10157000EEF0EE60089002647402F080069002645F +:101580007401F0539BF0439704800E4397084397F0 +:10159000028006439708439702539BF04397042227 +:1015A000AE82AF8390026AE4F08E828F83A3A3E0C1 +:1015B000FCA3E04C70318E828F83A3A3A3A3E0FE33 +:1015C000A3E0FF4E700A539BF04397044397022217 +:1015D000BE010DBF000A539BF043970443970222BC +:1015E0004397084397022243970843970222439761 +:1015F0000843970222AE82AF8390026A7402F08E93 +:10160000828F83E0540F6002801F30010890110820 +:101610007402F08005901108E4F0901109E4F05391 +:101620009BF0439B0243970422439708439702226F +:10163000AE82AF83E0FD53050FBD01308E828F83F4 +:10164000A3A3A3A3E0FEA3E0FF4E6006BE0116BF66 +:101650000013901108E4F0901109F0539BF0439BA4 +:101660000243970422439708439702224397084373 +:10167000970222AE82AF83E0FD53050FBD020280C8 +:10168000030217148E828F83A3A3A3A3E0FEA3E01B +:10169000FFBE801BBF0018AC97530402E4A2E713FF +:1016A000CC13CC901108ECF0901109E4F0805BBEF3 +:1016B0008127BF0024AC99530408E423CCC42354ED +:1016C0001F6CCC541FCC6CCC30E40244E090110869 +:1016D000ECF0901109E4F08031BE8227BF0024AE07 +:1016E0009A530608E423CEC423541F6ECE541FCE53 +:1016F0006ECE30E40244E0901108EEF0901109E45F +:10170000F0800743970843970222539BF0439B02C4 +:1017100043970422439708439702228582278583B3 +:1017200028A3A3E0FCA3E0FBBB0141903DD0E493E0 +:10173000FAA3E493FD8A758D767577808A828D830E +:10174000E493FA8A7875790090006475F00012329B +:101750009A9002737464F07400A3F0E4A3F0900014 +:1017600064E0900276F0E4A3F0021A8DBB020280DE +:101770000302188A903DD4E493FDC3EC9D4003021C +:10178000188A903DD5E493FAA3E493FDEC75F0023A +:10179000A42AF582ED35F0F583E493FAA3E493FDF2 +:1017A00074092AF529E43DF52A8A008D0188758996 +:1017B000767577808A828D83E493F98978757900CC +:1017C00090006475F000C005C00212329AD002D0B9 +:1017D000058A828D83E4932464F52BE43400F52C90 +:1017E000A829A92A852B2D852C2E752F0088828962 +:1017F00083E493FAA3E493FF8A758F767577808AE2 +:10180000828F83E493FA8A78757900852D82852EFC +:1018100083852FF0C001C00012329AD000D0018819 +:10182000828983E493FEA3E493FF8E828F83E49303 +:10183000252BF52BE4352CF52C740228F8E439F926 +:1018400088828983E493FEA3E4934E7097900066A8 +:10185000E0FEA3E04E7013E52BC39464FEE52C94E8 +:1018600000FF900066EEF0EFA3F09002737464F056 +:101870007400A3F0E4A3F0900066E0FEA3E0FF9004 +:101880000276EEF0EFA3F0021A8DE4BB030104FF31 +:10189000603BEC70387575C675763D757780903D08 +:1018A000C6E493FE8E7875790090006475F000129E +:1018B000329A9002737464F07400A3F0E4A3F09081 +:1018C0000064E0900276F0E4A3F0021A8DEF70035A +:1018D00002197F7F00EC24FFFDEF34FFFE903DD71F +:1018E000E493F97A00C3ED99EE64808AF063F080A6 +:1018F00095F0400302197F903DD8E493FDA3E49353 +:10190000FE1CBCFF011FEC2CFCEF33FFEC2DF5821D +:10191000EF3EF583E493FEA3E493FF90006474022A +:10192000F090006504F074012465FCE43400FD8E41 +:10193000828F83E493FA602C0EBE00010F8C828D9F +:1019400083EAF074012CF9E43DFA89828A83E4F099 +:101950000429FCE43AFD900064E0FA0A0A9000646D +:10196000EAF080CB9002737464F07400A3F0E4A3F7 +:10197000F0900064E0900276F0E4A3F0021A8DBBD0 +:101980002276852782852883A3A3A3A3E0FE702F58 +:101990009002767444F0E4A3F07575AF75763C75EB +:1019A0007780757844F579900064F5F012329A905A +:1019B00002737464F07400A3F0E4A3F0021A8DBE05 +:1019C000012F9002767476F0E4A3F07575F37576C6 +:1019D0003C757780757876F579900064F5F0123271 +:1019E0009A9002737464F07400A3F0E4A3F0021AF6 +:1019F0008D43970843970222BB21028003021A8677 +:101A0000852782852883A3A3A3A3E0FE703775757D +:101A10008475763D757780903D84E493FF8F78756B +:101A2000790090006475F00012329A900273746429 +:101A3000F07400A3F0E4A3F0900064E0900276F06C +:101A4000E4A3F08048BE013775759D75763D7577C6 +:101A500080903D9DE493FF8F7875790090006475C8 +:101A6000F00012329A9002737464F07400A3F0E4F0 +:101A7000A3F0900064E0900276F0E4A3F0800E43BF +:101A800097084397022243970843970222852782AB +:101A9000852883A3A3A3A3A3A3E0FEA3E0FF900252 +:101AA00076E0FCA3E0FDC3EE9CEF9D40048C068D28 +:101AB00007900273E0FBA3E0FCA3E0FD8E758F7638 +:101AC0008B828C838DF0121C50121C604397042271 +:101AD00090026A7402F0900266E0901108F0539B45 +:101AE000F0439B014397042290026A7402F0901124 +:101AF00008E4F0539BF0439B01439704224397086B +:101B000043970222AE82AF83A3A3E0FCA3E0FABA1C +:101B100002028005BA0341802D8E828F83A3A3A386 +:101B2000A3E0FAA3E04A703674062EF582E43FF58E +:101B300083E0FEA3E0FFBE0125BF002290026A748D +:101B400004F0439701227D00BC0513BD00109002F4 +:101B50006A7405F04397012243970843970222A332 +:101B6000A3E0A3E0900269F0539BF0439704229016 +:101B70000269E0901108F0539BF0439B01439704E6 +:101B800022AE82AF83A3A3A3A3E0FCA3E0FD4C702D +:101B90000D8E828F83A3A3E0900267F08011BC01B9 +:101BA0000EBD000B8E828F83A3A3E0900268F053DA +:101BB0009BF043970422A3A3A3A3E0FEA3E0FF4E60 +:101BC000700A900267E0901108F0800EBE010BBF12 +:101BD0000008900268E0901108F0539BF0439B01CD +:101BE0004397042290026AE0FFBF041490026AE463 +:101BF000F0901100E0900061F0539BF043970422B5 +:101C0000BF051890026AE4F0901100E0FFBF0516CE +:101C1000901101E0FFBF750E020F5090026AE4F0D0 +:101C2000539BF04397042290026AE0FFBF010A121F +:101C30001C6043970443970122BF02074397014367 +:101C4000970822439708439701900265E0F5962292 +:101C500085822485832585F0268575228576232235 +:101C6000E5224523700D90026A7402F0539BF085C3 +:101C70009B9B22AE22AF23C374089EE49F503790F3 +:101C8000026A7401F07530088524828525838526D3 +:101C9000F0121CFDAC22AD23EC24F8FCED34FFFD6A +:101CA0008C228D2374082524F524E43525F525534D +:101CB0009BF0439B0822BE0824BF002190026A7457 +:101CC00001F07530088524828525838526F0121C55 +:101CD000FDE4F522F523539BF0439B082290026A12 +:101CE0007402F08522308524828525838526F012B2 +:101CF0001CFD539BF0AF9BE5224FF59B22AD82AEBE +:101D000083AFF0E53024F7502AAB307C00C003C02D +:101D10000474F1C0E0743DC0E07480C0E074DAC0C7 +:101D2000E0743DC0E07480C0E0123441E58124F8E5 +:101D3000F581228D758E768F778530787579009054 +:101D4000110875F00002329AAD82AE83AFF075755E +:101D5000007576117577007578087579008D828E1B +:101D6000838FF002329AAD82AE83AFF0E53124EF7B +:101D7000502AAB317C00C003C0047403C0E0743E41 +:101D8000C0E07480C0E074DAC0E0743DC0E07480EC +:101D9000C0E0123441E58124F8F581228D758E76FC +:101DA0008F7785317875790090112075F0000232B7 +:101DB0009AAD82AE83AFF0757510757611757700A8 +:101DC0007578107579008D828E838FF002329AAD0E +:101DD00082AE83AFF0E53224BF502AAB327C00C024 +:101DE00003C0047415C0E0743EC0E07480C0E074A9 +:101DF000DAC0E0743DC0E07480C0E0123441E58197 +:101E000024F8F581228D758E768F778532787579F5 +:101E10000090118075F00002329AAD82AE83AFF06F +:101E20007575407576117577007578407579008DF8 +:101E3000828E838FF002329A85821685831785F011 +:101E400018C2AFC285900003120F21C2FC7B007C38 +:101E500000C3EB9514EC64808515F063F08095F079 +:101E6000503FEB2516F8EC3517F9AA1888828983BC +:101E70008AF0123BA9F582C004C003C002C001C0B1 +:101E800000121EAAAF82D000D001D002D003D0042D +:101E9000888289838AF0EF12330E0BBB00B30C806B +:101EA000B0D2FCD287D285D2AF22AF827E007D0035 +:101EB000BD0800502D8E04EC2CFEC2B700000000BF +:101EC00000000000EF30E704D2878002C28730862E +:101ED00003430601D2B7000000008F04EC2CFF0D75 +:101EE00080CE8E8222AF82BFA502800ABFA602806A +:101EF00009BFA70E800890000122900002229000E6 +:101F0000042290000022AF82BFA8005003021FCB22 +:101F1000EF243D5003021FCBEF2458FF240A83F522 +:101F200082EF241F83F583E4735F63676B6F7B83AA +:101F3000877F8B8F939FA3A7ABAFB3BF7377B7BBDD +:101F4000979BC3C71F1F1F1F1F1F1F1F1F1F1F1F61 +:101F50001F1F1F1F1F1F1F1F1F1F1F1F1F1F1F9020 +:101F600000E2229000E9229000EA229000B522903F +:101F700000B6229000B3229000B4229000B72290C5 +:101F800000CC229000CD229001832290018A2290E1 +:101F90000192229001942290019F229001CB2290E5 +:101FA00002212290022322900224229002252290D4 +:101FB0000226229002272290006F22900070229029 +:101FC000022A2290029F229002A022900000221258 +:101FD00028B8900006120EF490029875F0001223B3 +:101FE000269000C8120F2185333D85343E753F8011 +:101FF0007582001227B590000C120EF412268D90F7 +:102000000020120EF485353D85363E753F80758281 +:10201000011227B590000C120EF412268D90001EAE +:10202000120EF47538007582001223C0900014124D +:102030000EF47538007582001223C090000F120E46 +:10204000F4E4F53BF53C9000001226C490001E120B +:102050000EF40222CDAE82AF83E090029AF08E821F +:102060008F83A3A3E090029BF08E828F83A3A3A310 +:10207000E090029CF08E828F83A3A3A3A3E0900242 +:102080009DF08E828F83A3A3A3A3A3E090029EF072 +:1020900074062EF582E43FF583E090029FF07537D9 +:1020A000017E007F00C3EE9406EF64809480501997 +:1020B000EE249AFCEF3402FD8C828D83E060037580 +:1020C00037000EBE00DF0F80DCE537606190029BB9 +:1020D000E4F090029AF5F012240490029B7401F04F +:1020E00090029A75F00012240490029BE4F0900292 +:1020F0009AF5F012240490029B7401F090029A75F4 +:10210000F00012240490029BE4F090029AF5F01281 +:10211000240490029B7401F090029A75F00012243E +:102120000490029BE4F090029AF5F00224049002DD +:102130009A75F000022404AE82AF839002A074016D +:10214000F0FC7D00C3EC9415ED648094805019EC94 +:102150002EFAED3FFB8A828B83E060059002A0E4BB +:10216000F00CBC00DF0D80DC9002A0E0FDFB33959D +:10217000E0FCC007C006C005C003C0047450C0E046 +:10218000743EC0E07480C0E0123441E58124FBF568 +:1021900081D005D006D007ED70030221FE90029B8E +:1021A000E4F090029AF5F012240490029B7401F07E +:1021B00090029A75F00012240490029BE4F09002C1 +:1021C0009AF5F012240490029B7401F090029A7523 +:1021D000F00012240490029BE4F090029AF5F012B1 +:1021E000240490029B7401F090029A75F00012246E +:1021F0000490029BE4F090029AF5F00224048E828F +:102200008F83A3E0FD74022EF539E43FF53A8D8209 +:102210000224E0AE82AF83E0FDBD01028005BD0275 +:102220002A80128E828F83A3E0F53BA3E0F53C90D9 +:1022300000000226C48E828F83A3E0FEA3E0FFE4A9 +:10224000F53BF53C8E828F830226C422AD82AE839D +:10225000AFF09002A175F000C007C006C0051223C0 +:1022600026D005D006D0079002A2E0FC5304078DCB +:10227000828E838FF0EC12330E0DBD00010E8D8225 +:102280008E838FF0123BA9FC9002A2E05460C4033D +:102290005407FB8D828E838FF012330EECB5030151 +:1022A000228D828E838FF0123BA9FD7F00C005C076 +:1022B00007745FC0E0743EC0E07480C0E012344137 +:1022C000E58124FBF581227538000223C090027855 +:1022D00074AAF0900279741DF090027A7402F07E74 +:1022E000037F00C3EE941FEF648094805013EE24AC +:1022F00078F582EF3402F583E4F00EBE00E50F803E +:10230000E275751F75760090027875F0001228F658 +:10231000AF82900297EFF075142075150090027847 +:1023200075F000021E38AD82AE83AFF0C007C00664 +:10233000C00512283C900064120F2112239FD00583 +:10234000D006D007900278E0FCBCBB028004758206 +:10235000002275750275760090027A75F000C0074C +:10236000C006C0051228F6AC82D005D006D0079072 +:102370000279E0B5040280047582002290027AE0BE +:102380008D828E838FF012330E0DBD00010E9002F0 +:102390007BE08D828E838FF012330E758201229046 +:1023A000027874FFF0900279F090027AF090027B4C +:1023B000F075140475150090027875F000021E384F +:1023C000AF8290027874AAF09002797403F09002C0 +:1023D0007A7401F090027BE538F090027CEFF075A2 +:1023E000750575760090027875F0001228F6AF82B8 +:1023F00090027DEFF075140675150090027875F067 +:1024000000021E38AD82AE83AFF090027874AAF05D +:10241000900279741DF090027A7402F08D828E839E +:102420008FF0123BA990027BF074012DFAE43EFB81 +:102430008F048A828B838CF0123BA990027CF0740B +:10244000022DFAE43EFB8F048A828B838CF0123BD0 +:10245000A990027DF074032DFAE43EFB8F048A827A +:102460008B838CF0123BA990027EF074042DFAE469 +:102470003EFB8F048A828B838CF0123BA990027FF3 +:10248000F074052DFDE43EFE8D828E838FF0123BAD +:10249000A9900280F0900281E4F07E0AFFC3EE94DE +:1024A0001FEF648094805013EE2478F582EF34029D +:1024B000F583E4F00EBE00E50F80E275751F7576BA +:1024C0000090027875F0001228F6AF82900297EF24 +:1024D000F075142075150090027875F000021E3812 +:1024E000E5829002A3F090027874AAF090027974C9 +:1024F0001DF090027A7402F09002A3E090027BF04B +:1025000090027CE4F090027DF090027EF090027FD9 +:10251000F0900280F0900281F0AE39AF3A8E828F57 +:1025200083E0900282F08E828F83A3E0900283F09A +:102530008E828F83A3A3E0900284F08E828F83A388 +:10254000A3A3E0900285F08E828F83A3A3A3A3E0D0 +:10255000900286F08E828F83A3A3A3A3A3E09002B0 +:1025600087F074062EF582E43FF583E0900288F050 +:1025700074072EF582E43FF583E0900289F0740839 +:102580002EF582E43FF583E090028AF074092EF57F +:1025900082E43FF583E090028BF0740A2EF582E42A +:1025A0003FF583E090028CF0740B2EF582E43FF54A +:1025B00083E090028DF0740C2EF582E43FF583E009 +:1025C00090028EF0740D2EF582E43FF583E09002C8 +:1025D0008FF0740E2EF582E43FF583E0900290F0C8 +:1025E000740F2EF582E43FF583E0900291F07410B1 +:1025F0002EF582E43FF583E0900292F074112EF5FF +:1026000082E43FF583E0900293F074122EF582E4A9 +:102610003FF583E0900294F074132EF582E43FF5C9 +:1026200083E0900295F0900296E4F075751FF576C0 +:10263000900278F5F01228F6AF82900297EFF075CD +:10264000142075150090027875F000021E38AF82D4 +:1026500090027874AAF09002797403F090027AF0F4 +:1026600090027BEFF090027CE4F0757505F57690B2 +:102670000278F5F01228F6AF8290027DEFF0751423 +:102680000675150090027875F000021E38900278E9 +:1026900074AAF09002797401F090027A7404F075D3 +:1026A000750375760090027875F0001228F6AF82F7 +:1026B00090027BEFF075140475150090027875F0A8 +:1026C00000021E38AE82AF8390027874AAF09002A6 +:1026D00079740BF090027A7405F090027BE4F0902C +:1026E000027CF090027DF090027EF090027FF090EC +:1026F0000280F08E05900281EDF08F06900282EE4E +:10270000F0AF3B900283EFF0AF3C900284EFF075A6 +:10271000750D75760090027875F0001228F6AF827C +:10272000900285EFF075140E75150090027875F023 +:1027300000021E38AF8290027874AAF09002797479 +:1027400003F090027A23F090027BEFF090027CE499 +:10275000F0757505F576900278F5F01228F6AF82DF +:1027600090027DEFF075140675150090027875F0F3 +:1027700000021E38AF8290027874AAF09002797439 +:1027800003F090027A7407F090027BEFF090027CE5 +:10279000E4F0757505F576900278F5F01228F6AF3D +:1027A0008290027DEFF07514067515009002787521 +:1027B000F000021E38AF8290027874AAF09002797D +:1027C000741DF090027A7408F090027BEFF0AD3D3A +:1027D000AE3EAF3F7B047C008D828E838FF0123B38 +:1027E000A9FA601190027CEAF00DBD00010E0BBB4E +:1027F00000E60C80E38B068C07C3EE941FEF648029 +:1028000094805013EE2478F582EF3402F583E4F0DF +:102810000EBE00E50F80E275751F75760090027898 +:1028200075F0001228F6AF82900297EFF075142031 +:1028300075150090027875F000021E3890027874C9 +:10284000AAF09002797403F090027A740AF0900270 +:102850007BE4F090027CF0757505F576900278F5D2 +:10286000F01228F6AF8290027DEFF0751406751510 +:102870000090027875F000021E3890027874AAF079 +:102880009002797403F090027A740BF090027BE46A +:10289000F090027CF0757505F576900278F5F012EF +:1028A00028F6AF8290027DEFF07514067515009042 +:1028B000027875F000021E3890027874AAF0900237 +:1028C000797403F090027A740CF090027BE4F0903B +:1028D000027CF0757505F576900278F5F01228F611 +:1028E000AF8290027DEFF0751406751500900278A6 +:1028F00075F000021E3885827785837885F0797CB3 +:10290000007A007B00C3EA9575EB64808576F063FE +:10291000F08095F0501CEA2577F8EB3578F9AF791F +:10292000888289838FF0123BA92CFC0ABA00D60B4F +:1029300080D37455C39CF58222AF82439020439884 +:102940003F43A03F438807EF24F0500122EF2F9030 +:10295000295373801E801F80208021802280238045 +:102960002480258026802780288029802A802B802B +:102970002C802DC28822C28922C28A22C2A522C2EC +:10298000A422C2A322C2A222C2A122C2A022C29D0C +:1029900022C29C22C29B22C29A22C29922C298229F +:1029A000C29522E5F8C313FF530707E58854184F73 +:1029B00044E0F582225390DF5398C053A0C053885F +:1029C000F8221229CC122A1843A90222758C057507 +:1029D000A500758C4575A600758C8575BB00758C3A +:1029E000C5758D00758C0075E11C75E22E75E33F91 +:1029F00075E43F75E57875E68775E7FE75EE7875E1 +:102A0000D90E43F81043B0804380A043D11043E572 +:102A10008043E1A043E9402290FF9C7404F090FFC2 +:102A200098E4F090FF9D7404F090FF99E4F090FF1B +:102A30009E7404F090FF9AE4F075DE04F5DD75D520 +:102A400004F5D2F5C3F5CE75D604F5D3F5C4F5C1BA +:102A500075D704F5D4F5C5F5C290FFBD7404F090A8 +:102A6000FFA5E4F090FFEDF090FFD5F090FFBC746F +:102A700004F090FFA4E4F090FFECF090FFD4F0900D +:102A8000FFBB7404F090FFA3E4F090FFEBF090FF25 +:102A9000D3F090FFBA7404F090FFA2E4F090FFEA44 +:102AA000F090FFD2F090FFB97404F090FFA1E4F031 +:102AB00090FFE9F090FFD1F090FFB87404F090FF20 +:102AC000A0E4F090FFE8F090FFD0F090FFC3740412 +:102AD000F090FFABE4F090FFF3F090FFDBF090FF9D +:102AE000C27404F090FFAAE4F090FFF2F090FFDAD5 +:102AF000F090FFC17404F090FFA9E4F090FFF1F0B2 +:102B000090FFD9F090FFC07404F090FFA8E4F0901B +:102B1000FFF0F090FFD8F090FFBF7404F090FFA793 +:102B2000E4F090FFEFF090FFD7F090FFBE7404F058 +:102B300090FFA6E4F090FFEEF090FFD6F090FFC972 +:102B40007404F090FFB1E4F090FFF9F090FFE1F031 +:102B500022AF82BFA502800ABFA6028009BFA70ECE +:102B60008008900001229000022290000422900030 +:102B70000022AF82BFA8005003022C37EF243D5043 +:102B800003022C37EF2458FF240A83F582EF241F19 +:102B900083F583E473CBCFD3D7DBE7EFF3EBF7FB1E +:102BA000FF0B0F13171B1F2BDFE3232703072F3305 +:102BB0002B2B2B2B2B2B2B2B2B2B2B2B2C2C2C2C61 +:102BC0002C2C2C2B2B2C2C2C2C2C2C9000E22290FF +:102BD00000E9229000EA229000B5229000B62290EF +:102BE00000B3229000B4229000B7229000CC229033 +:102BF00000CD229001832290018A2290019222909E +:102C000001942290019F229001CB229002212290D8 +:102C10000223229002242290022522900226229052 +:102C200002272290006F229000702290022A2290A8 +:102C3000029F229002A02290000022A28DE43390F5 +:102C400002A4F0A28EE4339002A5F0229002A4E048 +:102C5000FFA28DE433FEEFB50602803EA28DE43381 +:102C60009002A4F09002A4E0FF601ABF012C7489C6 +:102C7000C0E0743EC0E07480C0E01234411581159C +:102C800081158180157494C0E0743EC0E07480C0EA +:102C9000E01234411581158115819002A5E0FFA253 +:102CA0008EE433FEEFB5060122A28EE4339002A536 +:102CB000F09002A5E0FF6019BF012B749EC0E07484 +:102CC0003EC0E07480C0E012344115811581158149 +:102CD0002274A9C0E0743EC0E07480C0E0123441A8 +:102CE00015811581158122AE82AF83BE4005BF7E5E +:102CF000028024BE4105BF7E028010BE4205BF7E19 +:102D000002800CBE4315BF7E128008900001229005 +:102D1000000222900003229000002290FFFF22AECA +:102D200082AF838E048F05BC4005BD7E028016BC39 +:102D30004105BD7E02800EBC4205BD7E028006BC00 +:102D40004317BD7E149002A4E0700A8E828F831216 +:102D50002CE71222C77582002275820122AE82AF53 +:102D6000839002A4E0FD600ABD010E8E828F830273 +:102D7000110E8E828F8302205522AE82AF83900285 +:102D8000A4E0FD600ABD010E8E828F8302114B8E7E +:102D9000828F8302213722AE82AF839002A4E0FDAE +:102DA000600ABD010E8E828F830211888E828F830E +:102DB000022213229002A4E0701FAE1AAF1BC3744C +:102DC000209E744E9F5012C2AF90006175F00012A9 +:102DD000224CE4F51AF51BD2AF051AE4B51A020528 +:102DE0001B220230B15380E35390F153B0875388D4 +:102DF0007F53C0010230FD85824385834485F045C1 +:102E0000E5427016AC4174F42C400A0540E4B5402C +:102E10000905418005E4F540F541E4FBFCF9FAF5CC +:102E200046F54785404885414974FC2549404AA8F4 +:102E30004874042549FF5307078882EF24FCF58373 +:102E4000C002C001123329AE82AF83E4C39EF546AF +:102E500074049FF547AE40AF415307078E82EF24BD +:102E6000FCF583123329AE82AF83D001D002E4C3D4 +:102E70009EFB74049FFC022F1474F825494046AE53 +:102E800048740755498E8224FCF583123329AE829B +:102E9000AF83E4C39EFB74049FFCAE40AF41740457 +:102EA0002FFF5307078E82EF24FCF583C004C00375 +:102EB000123329AE82AF83D003D004E4C39EF974E9 +:102EC000049FFA804FAE4874042549FF5307078ECC +:102ED00082EF24FCF583C004C003123329AE82AF15 +:102EE00083E4C39EF974049FFAAE40AF41530707D1 +:102EF0008E82EF24FCF583C002C001123329AE821A +:102F0000AF83D001D002D003D004E4C39EF5467451 +:102F1000049FF5478543828544838545F0123BA98C +:102F2000FF30E0047B007C04EF30E10479007A0498 +:102F3000EF30E20675460075470474012543FDE451 +:102F40003544FEAF458D828E838FF0123BA9FF7012 +:102F500009FBFCF9FA8C46754704BF010D7B007C28 +:102F60000079007A04E4F546F547BF020D79007A4E +:102F7000007B007C04E4F546F547BF030D79007A39 +:102F8000047B007C04E4F546F547AE427F0075758E +:102F9000038F768E828F83C004C003C002C00112EB +:102FA0003BC5AE82AF83D001D002D003D004BE00B7 +:102FB00005BF00028010BE0105BF0002801ABE02DC +:102FC0003BBF00388024D284D2C7D282D2B5D2B4DB +:102FD000D2918B068C078028D2C1D2C2D2C3D2C470 +:102FE000D2C5D29289068A078016D283D2C6D28FE2 +:102FF000D2B6D2B3D293AE46AF4780047E007F00F4 +:103000008E828F831230167582002290FF80E053EB +:10301000E0DFF00230B1AE82AF83E4C39EFE740401 +:103020009FFD8DC38ECE8DC48EC18DC58EC290FF87 +:10303000EDEDF090FFD5EEF090FFECEDF090FFD4C9 +:10304000EEF090FFEBEDF090FFD3EEF090FFEAEDA5 +:10305000F090FFD2EEF090FFE9EDF090FFD1EEF0AE +:1030600090FFE8EDF090FFD0EEF090FFF3EDF090E0 +:10307000FFDBEEF090FFF2EDF090FFDAEEF090FF64 +:10308000F1EDF090FFD9EEF090FFF0EDF090FFD869 +:10309000EEF090FFEFEDF090FFD7EEF090FFEEED49 +:1030A000F090FFD6EEF090FFF9EDF090FFE1EEF03A +:1030B0002290FF8074CAF090FF817408F090FF8224 +:1030C000F090FF83F090FF84F090FF85F090FF86F2 +:1030D000748AF090FF877408F090FF88F090FF8961 +:1030E000F090FF8AF090FF8BF090FF8C748AF09044 +:1030F000FF917408F075DA8AF5DBF5DC2290FF8029 +:103100007402F090FF81E4F090FF82F090FF83F072 +:1031100090FF84F090FF85F090FF867402F090FF9E +:1031200087E4F090FF88F090FF89F090FF8AF0909C +:10313000FF8BF090FF8C7402F090FF91E4F075DA51 +:1031400002F5DBF5DC22AF82BFA502800ABFA60232 +:103150008009BFA70E8008900001229000022290F3 +:1031600000042290000022AF82BFA8005003023268 +:103170002CEF243D500302322CEF2458FF240A8305 +:10318000F582EF241F83F583E473C0C4C8CCD0DC80 +:10319000E4E8E0ECF0F40004080C101420D4D81893 +:1031A0001CF8FC24283131313131313131313131A8 +:1031B00031323232323232323131323231313232F4 +:1031C0009000E2229000E9229000EA229000B522CD +:1031D0009000B6229000B3229000B4229000B72253 +:1031E0009000CC229000CD229001832290018A226F +:1031F000900192229001942290019F229001CB2273 +:103200009002212290022322900224229002252261 +:10321000900226229002272290006F2290007022B6 +:1032200090022A2290029F229002A0229000002267 +:10323000AE82AF83BE445FBF7E5CE51C602B120E86 +:1032400087E5825422601175123590002575F000D3 +:10325000120DCC120A00803A75122990002575F0E3 +:1032600000120DCC120A008029120E87E58254222A +:10327000601175133590002575F000120E04120AC6 +:1032800000800F75132990002575F000120E0412AE +:103290000A007582002275820122AD82AE83AFF0F2 +:1032A0008D7A8E7B8F7C85757D85767E85777FA8F0 +:1032B00078A9798803890418B8FF0119EB4C6025B7 +:1032C000857D82857E83857FF0123BA9FCA3858264 +:1032D0007D85837E8D828E838FF0EC12330EA3ADBD +:1032E00082AE8380CE857A82857B83857CF022AC1A +:1032F00082AD83AE76AF77BE0004EF600C1F0FE5A2 +:103300007512330EA3DEFADFF88C828D832220F74C +:103310001130F6138883A88220F509F6A8837583F7 +:10332000002280FEF280F5F022E58330E707638219 +:10333000FF6383FFA322E575457660467A01E57554 +:1033400025E0F575E576334012F576E5829575E56D +:1033500083957640030A80E6C3E57613F576E57536 +:1033600013F575C3E5829575F5F0E583957640050F +:10337000F58385F082C3E57613F576E57513F5756B +:10338000DAE12285827A85837B85F07CE578457950 +:10339000700490000022AB78AC791BBBFF011CEBE2 +:1033A0004C6048A87AA97BAA7C888289838AF0121B +:1033B0003BA9FF85757D85767E85777F857D8285B6 +:1033C0007E83857FF0123BA9FEEFB5061E08B8008C +:1033D0000109887A897B8A7C7401257DFDE4357E2C +:1033E000FEAF7F8D758E768F7780AFAD7AAE7BAF77 +:1033F0007C8D828E838FF0123BA9FD7F00AB75AC74 +:1034000076AE778B828C838EF0123BA9FB7E00ED2B +:10341000C39BF582EF9EF58322C01E85811E7E0030 +:103420008E83120FE8D01E2285825A85835B85F039 +:103430005CE4F557F558F559851D5D903419023552 +:1034400002C01EE581F51E24FBFF8F5DE4F557F5F4 +:1034500058F559E51E24FBF8865A08865B08865CF9 +:10346000903419123502D01E22AF82C04DC04EC01A +:103470004F1234768007C04BC04C8F8222158115C5 +:103480008115810555E4B55502055622AF82743089 +:103490002FFF24C6500B74072FFFE54A6003430734 +:1034A000208F82023469E582FFC4540FF582C00781 +:1034B00012348CD007740F5FF58202348C858275CC +:1034C000AB50AC51AD52AE53AA547577208A07EF7A +:1034D0002FF576EE2354014576FAEB2BFBEC33FC0B +:1034E000ED33FDEE33FEC3EA95754008EAC39575EA +:1034F000FA430301D577D68B508C518D528E538A67 +:10350000542285824B85834C85574D85584E85596D +:103510004FE4F555F556AD5AAE5BAF5C8D828E83A8 +:103520008FF0123BA9FC74012DF55AE43EF55B8F38 +:103530005CECFF7003023B6DBF25028003023B651C +:10354000E4F55EF55FF560F561F562F563F564F548 +:1035500065F567F568F569756AFF756BFFAC5AAD7F +:103560005BAE5C8C828D838EF0123BA9F56FA3ACB1 +:1035700082AD838C5A8D5B8E5C7425B56F08856F28 +:1035800082123469809074D0256F4003023627E59B +:103590006F24C6500302362774FFB56A4BB56B48DB +:1035A000C004C005C00685687585697690000AC0AC +:1035B00006C005C004123B8CAA82AB83D004D005A0 +:1035C000D006AE6F7D00EE2AFAED3BFBEA24D0F583 +:1035D00068EB34FFF569E5684569D006D005D0048D +:1035E0007081755F01023563C004C005C006856A3D +:1035F00075856B7690000AC006C005C004123B8C2E +:10360000AA82AB83D004D005D006AD6F7E00ED2A30 +:10361000FAEE3BFBEA24D0F56AEB34FFF56BD006FB +:10362000D005D004023563742EB56F1574FFB56AEA +:1036300005B56B028003023563E4F56AF56B02356C +:1036400063749F256F500EE56F24854008536FDF2C +:10365000754A018003754A007420B56F030236F481 +:10366000742BB56F030236EE742DB56F028079743A +:1036700042B56F030236FA7443B56F03023706741E +:1036800044B56F030238957446B56F030238AC74C5 +:1036900048B56F030235637449B56F0302389574FA +:1036A0004AB56F03023563744CB56F028052744F94 +:1036B000B56F0302389D7450B56F0302382A7453F6 +:1036C000B56F0280627454B56F030235637455B5EB +:1036D0006F030238A27458B56F030238A7745AB545 +:1036E0006F030235630238B1755E010235637560A0 +:1036F000010235637561010235637563010235634B +:10370000756401023563E563600AE55D14F9895D5E +:103710008706800BE55D24FEFD8D5D8D0187068E9D +:10372000821234690238BDE55D24FDFE8E5D8E0196 +:10373000870409870509870619198C508D518E5207 +:103740008C828D838EF0123B7485827085837174B8 +:10375000FFB56A09B56B0685706A85716BE55E70A9 +:103760003DC3E5709568E57195695032E568C3958C +:1037700070F568E5699571F569AC68AB698C028B89 +:10378000061CBCFF011BEA4E6010758220C004C0FD +:1037900003123469D003D00480E38C688B69AD6A6E +:1037A000AE6B8550828551838552F0123BA9FB6038 +:1037B00033C3E49D74808EF063F08095F050251D36 +:1037C000BDFF011E8B82C006C005123469D005D032 +:1037D00006AA50AB51AC520ABA00010B8A508B5169 +:1037E0008C5280BEE55E70030238BDC3E5709568FB +:1037F000E571956940030238BDE568C39570F568C9 +:10380000E5699571F569AE68AD698E038D041EBEDC +:10381000FF011DEB4C70030238B9758220C006C051 +:1038200005123469D005D00680E0E55D24FDFC8CEE +:103830005D8C01870209870309870419198A508B57 +:10384000518C52AC52BC800040047B438014BC605D +:103850000040047B50800BBC400040047B49800248 +:103860007B588B82C00312346975823A12346975B1 +:103870008230123469758278123469D003BB4902F0 +:10388000800BBB500280068551821234A68550827F +:103890001234A6802875620175670A802075670852 +:1038A000801B75670A801675671080117565018029 +:1038B0000C856F8212346980048E688D69E56560BD +:1038C0005BE55D24FCFE8E5D8E018703098704099C +:1038D00087050987061919198B508C518D528E5303 +:1038E000755034755141755280855072855173857C +:1038F000527474012572FAE43573FBAE748A508BEE +:10390000518E528572828573838574F0123BA9FDB6 +:1039100070030235168D8212346980CDE56770031D +:10392000023516E5636029E55D14F9895D87067D3A +:10393000007C007B008E508D518C528B53E5627061 +:1039400063AB50FCFDFE8B508C518D528E538054D6 +:10395000E5646021E55D24FCFE8E5D8E0187030930 +:1039600087040987050987061919198B508C518D11 +:10397000528E53802FE55D24FEFE8E5D8E018705FD +:1039800009870619EE3395E0FCFB8D508E518C5261 +:103990008B53E562700EAB50AC51FDFE8B508C51D9 +:1039A0008D528E53E5626023E55330E71BC3E495E7 +:1039B00050FBE49551FCE49552FDE49553FE8B5089 +:1039C0008C518D528E538003756200756601798526 +:1039D0007D007E00755400856782C006C005C00169 +:1039E0001234BDD001D005D006E5667013E554C48D +:1039F00054F0FCE554C4540F4204E74CF71980021C +:103A0000A7540DBD00010EE566B40100E433F56670 +:103A1000E55045514552455370BA896E8D6C8E6D97 +:103A2000E56845697005756801F569E55F702DE524 +:103A30005E7029AA68AB69AC6C0C7E00C3EC9AEE90 +:103A40009B5015758220C003C002123469D002D089 +:103A5000031ABAFF011B80DF8A688B69E562601177 +:103A600075822D123469156874FFB5680215698076 +:103A70002EE56C456D6028E560601175822B12346F +:103A800069156874FFB5680215698013E561600FF8 +:103A9000758220123469156874FFB568021569E5EE +:103AA0005E702FAE68AD698E038D041EBEFF011DD2 +:103AB000C3E56C9BE56D9C503AE55F60047C30800B +:103AC000027C208C82C006C005123469D005D00665 +:103AD00080D5C3E56C9568E56D9569500FE568C3C1 +:103AE000956CF568E569956DF569800BE4F568F509 +:103AF0006980048E688D69A96EAD6CAE6D8D038E84 +:103B0000041DBDFF011EEB4C6030E566B40100E40E +:103B100033F566700A09E7C4540FFC8C548007879C +:103B200004740F5CF554855482C006C005C00112B0 +:103B3000348CD001D005D00680C3E55E7003023519 +:103B400016AD68AE698D038E041DBDFF011EEB4CE2 +:103B50007003023516758220C006C005123469D084 +:103B600005D00680E08F82123469023516855582B1 +:103B700085568322AA82AB83123BA96003A380F8F7 +:103B8000C3E5829AF582E5839BF58322E5828575FC +:103B9000F0A4C582C0F08576F0A4D0F025F0C583EE +:103BA0008575F0A42583F5832220F71430F6148858 +:103BB00083A88220F507E6A88375830022E280F7B8 +:103BC000E49322E022C2D5E58330E70DD2D5E4C3E9 +:103BD0009582F582E49583F583E57630E70BE4C3BF +:103BE0009575F575E49576F57612333630D50BE498 +:103BF000C39582F582E49583F58322758200225372 +:103C00004D4B2076616C7068610D0A004445564941 +:103C10004345207649643A307830356163207049F5 +:103C2000643A3078303234660A0D004B45593A20F8 +:103C30003078253034782025730D0A005550004423 +:103C40004F574E004348414E474544204C4159454B +:103C5000523A2025640D0A00554E5245434F474EB7 +:103C6000495A4544204B45593A203078253034781C +:103C70000D0A006164645F6B65795F6269743A2064 +:103C800063616E2774206164643A20253032580ADB +:103C90000064656C5F6B65795F6269743A2063618B +:103CA0006E27742064656C3A20253032580A00056E +:103CB000010906A101050719E029E715002501758D +:103CC00001950881027508950181010507190029F0 +:103CD000FF150026FF0075089506810005081901EB +:103CE00029051500250175019505910275039501BA +:103CF0009101C005010980A1018501198129831560 +:103D000000250175019503810295058101C0050C0F +:103D10000901A101850219002A3C021500263C0276 +:103D2000751095018100C00600FF0901A1018505FC +:103D300019012902150026FF0075089505B102C07A +:103D400005010906A1018506050719E029E7150007 +:103D5000250175019508810205071900299F1500A5 +:103D60002501750195A08102C0120110010000001B +:103D700008AC054F02000001020301090400000124 +:103D800003010100092111010001224400070581FE +:103D900003100001090401000103000000092111C2 +:103DA000010001227600070582034000010902009C +:103DB00000020100A0FA7B3D843D8D3D943D9D3D78 +:103DC000A63D0000AD3D04030904273E3E3E4B3EA8 +:103DD000693D000001C43D03CA3D2573206275663C +:103DE00066657220746F6F206C6F6E673A20256471 +:103DF000007365745F6570305F696E5F62756666DB +:103E00006572007365745F6570315F696E5F6275BE +:103E100066666572007365745F6570325F696E5FB8 +:103E200062756666657200636F6E74616374406389 +:103E300061726C6F73736C6573732E696F00534D91 +:103E40004B204B6579626F61726400303030310015 +:103E5000697320626C616E6B3A2025640D0A0072F2 +:103E600066206C696E6B206368616E6765643A20DA +:103E700025640D0A00534D4B204254352E3000531B +:103E80004D4B204254332E30005553425F4D4F442A +:103E9000450D0A0052465F4D4F44450D0A004D4105 +:103EA000435F4D4F44450D0A0057494E5F4D4F4407 +:103EB000450D0A00447E1E001F0020002100220044 +:103EC000230024002500260027002D002E002A00B4 +:103ED000000000002B0014001A0008001500170055 +:103EE0001C0018000C00120013002F0030003100DD +:103EF00000000000390004001600070009000A0055 +:103F00000B000D000E000F003300340000002800ED +:103F100000000000E1001D001B0006001900050064 +:103F20001100100036003700380000000000E500E6 +:103F300052004C00E000E300E200000000002C0012 +:103F400000000000E3002252500000000000510079 +:103F50004F000000447E1E001F00200021002200B0 +:103F6000230024002500260027002D002E002A0013 +:103F7000000000002B0014001A00080015001700B4 +:103F80001C0018000C00120013002F00300031003C +:103F900000000000390004001600070009000A00B4 +:103FA0000B000D000E000F0033003400000028004D +:103FB00000000000E1001D001B00060019000500C4 +:103FC0001100100036003700380000000000E50046 +:103FD00052004C00E000E200E300000000002C0072 +:103FE00000000000E30023525000000000005100D8 +:103FF0004F0000003500BE00BD00C100C0000378C6 +:104000000478BC00AE00BB00A800AA00A9004C00C8 +:10401000000000000100417E427E437E407E0100A0 +:104020000100010001000100010001000100010088 +:10403000000000000100010001000100010001007A +:104040000100010001000100010001000000010069 +:10405000000000000100010001000100010001005A +:10406000010001000100010001000000000001004A +:10407000010001000100010001000000000001003A +:10408000000000000100010001000000000001002C +:104090000100000035003A003B003C003D003E00BE +:1040A0003F004000410042004300440045004C00F6 +:1040B000000000000100417E427E437E407E010000 +:1040C00001000100010001000100010001000100E8 +:1040D00000000000010001000100010001000100DA +:1040E00001000100010001000100010000000100C9 +:1040F00000000000010001000100010001000100BA +:1041000001000100010001000100000000000100A9 +:104110000100010001000100010000000000010099 +:10412000000000000100010001000000000001008B +:10413000010000003C4E4F20464C4F41543E0000D1 +:10414000000000000000000000000000000000006F +:10415000000000000000000000000000000000005F +:10416000000000000000000000000000000000004F +:10417000000000000000000000000000000000003F +:10418000000000000000000000000000000000002F +:10419000000000000000000000000000000000001F +:1041A000000000000000000000000000000000000F +:1041B00000000000000000000000000000000000FF +:1041C00000000000000000000000000000000000EF +:1041D00000000000000000000000000000000000DF +:1041E00000000000000000000000000000000000CF +:1041F00000000000000000000000000000000000BF +:1042000000000000000000000000000000000000AE +:10421000000000000000000000000000000000009E +:10422000000000000000000000000000000000008E +:10423000000000000000000000000000000000007E +:10424000000000000000000000000000000000006E +:10425000000000000000000000000000000000005E +:10426000000000000000000000000000000000004E +:10427000000000000000000000000000000000003E +:10428000000000000000000000000000000000002E +:10429000000000000000000000000000000000001E +:1042A000000000000000000000000000000000000E +:1042B00000000000000000000000000000000000FE +:1042C00000000000000000000000000000000000EE +:1042D00000000000000000000000000000000000DE +:1042E00000000000000000000000000000000000CE +:1042F00000000000000000000000000000000000BE +:1043000000000000000000000000000000000000AD +:10431000000000000000000000000000000000009D +:10432000000000000000000000000000000000008D +:10433000000000000000000000000000000000007D +:10434000000000000000000000000000000000006D +:10435000000000000000000000000000000000005D +:10436000000000000000000000000000000000004D +:10437000000000000000000000000000000000003D +:10438000000000000000000000000000000000002D +:10439000000000000000000000000000000000001D +:1043A000000000000000000000000000000000000D +:1043B00000000000000000000000000000000000FD +:1043C00000000000000000000000000000000000ED +:1043D00000000000000000000000000000000000DD +:1043E00000000000000000000000000000000000CD +:1043F00000000000000000000000000000000000BD +:1044000000000000000000000000000000000000AC +:10441000000000000000000000000000000000009C +:10442000000000000000000000000000000000008C +:10443000000000000000000000000000000000007C +:10444000000000000000000000000000000000006C +:10445000000000000000000000000000000000005C +:10446000000000000000000000000000000000004C +:10447000000000000000000000000000000000003C +:10448000000000000000000000000000000000002C +:10449000000000000000000000000000000000001C +:1044A000000000000000000000000000000000000C +:1044B00000000000000000000000000000000000FC +:1044C00000000000000000000000000000000000EC +:1044D00000000000000000000000000000000000DC +:1044E00000000000000000000000000000000000CC +:1044F00000000000000000000000000000000000BC +:1045000000000000000000000000000000000000AB +:10451000000000000000000000000000000000009B +:10452000000000000000000000000000000000008B +:10453000000000000000000000000000000000007B +:10454000000000000000000000000000000000006B +:10455000000000000000000000000000000000005B +:10456000000000000000000000000000000000004B +:10457000000000000000000000000000000000003B +:10458000000000000000000000000000000000002B +:10459000000000000000000000000000000000001B +:1045A000000000000000000000000000000000000B +:1045B00000000000000000000000000000000000FB +:1045C00000000000000000000000000000000000EB +:1045D00000000000000000000000000000000000DB +:1045E00000000000000000000000000000000000CB +:1045F00000000000000000000000000000000000BB +:1046000000000000000000000000000000000000AA +:10461000000000000000000000000000000000009A +:10462000000000000000000000000000000000008A +:10463000000000000000000000000000000000007A +:10464000000000000000000000000000000000006A +:10465000000000000000000000000000000000005A +:10466000000000000000000000000000000000004A +:10467000000000000000000000000000000000003A +:10468000000000000000000000000000000000002A +:10469000000000000000000000000000000000001A +:1046A000000000000000000000000000000000000A +:1046B00000000000000000000000000000000000FA +:1046C00000000000000000000000000000000000EA +:1046D00000000000000000000000000000000000DA +:1046E00000000000000000000000000000000000CA +:1046F00000000000000000000000000000000000BA +:1047000000000000000000000000000000000000A9 +:104710000000000000000000000000000000000099 +:104720000000000000000000000000000000000089 +:104730000000000000000000000000000000000079 +:104740000000000000000000000000000000000069 +:104750000000000000000000000000000000000059 +:104760000000000000000000000000000000000049 +:104770000000000000000000000000000000000039 +:104780000000000000000000000000000000000029 +:104790000000000000000000000000000000000019 +:1047A0000000000000000000000000000000000009 +:1047B00000000000000000000000000000000000F9 +:1047C00000000000000000000000000000000000E9 +:1047D00000000000000000000000000000000000D9 +:1047E00000000000000000000000000000000000C9 +:1047F00000000000000000000000000000000000B9 +:1048000000000000000000000000000000000000A8 +:104810000000000000000000000000000000000098 +:104820000000000000000000000000000000000088 +:104830000000000000000000000000000000000078 +:104840000000000000000000000000000000000068 +:104850000000000000000000000000000000000058 +:104860000000000000000000000000000000000048 +:104870000000000000000000000000000000000038 +:104880000000000000000000000000000000000028 +:104890000000000000000000000000000000000018 +:1048A0000000000000000000000000000000000008 +:1048B00000000000000000000000000000000000F8 +:1048C00000000000000000000000000000000000E8 +:1048D00000000000000000000000000000000000D8 +:1048E00000000000000000000000000000000000C8 +:1048F00000000000000000000000000000000000B8 +:1049000000000000000000000000000000000000A7 +:104910000000000000000000000000000000000097 +:104920000000000000000000000000000000000087 +:104930000000000000000000000000000000000077 +:104940000000000000000000000000000000000067 +:104950000000000000000000000000000000000057 +:104960000000000000000000000000000000000047 +:104970000000000000000000000000000000000037 +:104980000000000000000000000000000000000027 +:104990000000000000000000000000000000000017 +:1049A0000000000000000000000000000000000007 +:1049B00000000000000000000000000000000000F7 +:1049C00000000000000000000000000000000000E7 +:1049D00000000000000000000000000000000000D7 +:1049E00000000000000000000000000000000000C7 +:1049F00000000000000000000000000000000000B7 +:104A000000000000000000000000000000000000A6 +:104A10000000000000000000000000000000000096 +:104A20000000000000000000000000000000000086 +:104A30000000000000000000000000000000000076 +:104A40000000000000000000000000000000000066 +:104A50000000000000000000000000000000000056 +:104A60000000000000000000000000000000000046 +:104A70000000000000000000000000000000000036 +:104A80000000000000000000000000000000000026 +:104A90000000000000000000000000000000000016 +:104AA0000000000000000000000000000000000006 +:104AB00000000000000000000000000000000000F6 +:104AC00000000000000000000000000000000000E6 +:104AD00000000000000000000000000000000000D6 +:104AE00000000000000000000000000000000000C6 +:104AF00000000000000000000000000000000000B6 +:104B000000000000000000000000000000000000A5 +:104B10000000000000000000000000000000000095 +:104B20000000000000000000000000000000000085 +:104B30000000000000000000000000000000000075 +:104B40000000000000000000000000000000000065 +:104B50000000000000000000000000000000000055 +:104B60000000000000000000000000000000000045 +:104B70000000000000000000000000000000000035 +:104B80000000000000000000000000000000000025 +:104B90000000000000000000000000000000000015 +:104BA0000000000000000000000000000000000005 +:104BB00000000000000000000000000000000000F5 +:104BC00000000000000000000000000000000000E5 +:104BD00000000000000000000000000000000000D5 +:104BE00000000000000000000000000000000000C5 +:104BF00000000000000000000000000000000000B5 +:104C000000000000000000000000000000000000A4 +:104C10000000000000000000000000000000000094 +:104C20000000000000000000000000000000000084 +:104C30000000000000000000000000000000000074 +:104C40000000000000000000000000000000000064 +:104C50000000000000000000000000000000000054 +:104C60000000000000000000000000000000000044 +:104C70000000000000000000000000000000000034 +:104C80000000000000000000000000000000000024 +:104C90000000000000000000000000000000000014 +:104CA0000000000000000000000000000000000004 +:104CB00000000000000000000000000000000000F4 +:104CC00000000000000000000000000000000000E4 +:104CD00000000000000000000000000000000000D4 +:104CE00000000000000000000000000000000000C4 +:104CF00000000000000000000000000000000000B4 +:104D000000000000000000000000000000000000A3 +:104D10000000000000000000000000000000000093 +:104D20000000000000000000000000000000000083 +:104D30000000000000000000000000000000000073 +:104D40000000000000000000000000000000000063 +:104D50000000000000000000000000000000000053 +:104D60000000000000000000000000000000000043 +:104D70000000000000000000000000000000000033 +:104D80000000000000000000000000000000000023 +:104D90000000000000000000000000000000000013 +:104DA0000000000000000000000000000000000003 +:104DB00000000000000000000000000000000000F3 +:104DC00000000000000000000000000000000000E3 +:104DD00000000000000000000000000000000000D3 +:104DE00000000000000000000000000000000000C3 +:104DF00000000000000000000000000000000000B3 +:104E000000000000000000000000000000000000A2 +:104E10000000000000000000000000000000000092 +:104E20000000000000000000000000000000000082 +:104E30000000000000000000000000000000000072 +:104E40000000000000000000000000000000000062 +:104E50000000000000000000000000000000000052 +:104E60000000000000000000000000000000000042 +:104E70000000000000000000000000000000000032 +:104E80000000000000000000000000000000000022 +:104E90000000000000000000000000000000000012 +:104EA0000000000000000000000000000000000002 +:104EB00000000000000000000000000000000000F2 +:104EC00000000000000000000000000000000000E2 +:104ED00000000000000000000000000000000000D2 +:104EE00000000000000000000000000000000000C2 +:104EF00000000000000000000000000000000000B2 +:104F000000000000000000000000000000000000A1 +:104F10000000000000000000000000000000000091 +:104F20000000000000000000000000000000000081 +:104F30000000000000000000000000000000000071 +:104F40000000000000000000000000000000000061 +:104F50000000000000000000000000000000000051 +:104F60000000000000000000000000000000000041 +:104F70000000000000000000000000000000000031 +:104F80000000000000000000000000000000000021 +:104F90000000000000000000000000000000000011 +:104FA0000000000000000000000000000000000001 +:104FB00000000000000000000000000000000000F1 +:104FC00000000000000000000000000000000000E1 +:104FD00000000000000000000000000000000000D1 +:104FE00000000000000000000000000000000000C1 +:104FF00000000000000000000000000000000000B1 +:1050000000000000000000000000000000000000A0 +:105010000000000000000000000000000000000090 +:105020000000000000000000000000000000000080 +:105030000000000000000000000000000000000070 +:105040000000000000000000000000000000000060 +:105050000000000000000000000000000000000050 +:105060000000000000000000000000000000000040 +:105070000000000000000000000000000000000030 +:105080000000000000000000000000000000000020 +:105090000000000000000000000000000000000010 +:1050A0000000000000000000000000000000000000 +:1050B00000000000000000000000000000000000F0 +:1050C00000000000000000000000000000000000E0 +:1050D00000000000000000000000000000000000D0 +:1050E00000000000000000000000000000000000C0 +:1050F00000000000000000000000000000000000B0 +:10510000000000000000000000000000000000009F +:10511000000000000000000000000000000000008F +:10512000000000000000000000000000000000007F +:10513000000000000000000000000000000000006F +:10514000000000000000000000000000000000005F +:10515000000000000000000000000000000000004F +:10516000000000000000000000000000000000003F +:10517000000000000000000000000000000000002F +:10518000000000000000000000000000000000001F +:10519000000000000000000000000000000000000F +:1051A00000000000000000000000000000000000FF +:1051B00000000000000000000000000000000000EF +:1051C00000000000000000000000000000000000DF +:1051D00000000000000000000000000000000000CF +:1051E00000000000000000000000000000000000BF +:1051F00000000000000000000000000000000000AF +:10520000000000000000000000000000000000009E +:10521000000000000000000000000000000000008E +:10522000000000000000000000000000000000007E +:10523000000000000000000000000000000000006E +:10524000000000000000000000000000000000005E +:10525000000000000000000000000000000000004E +:10526000000000000000000000000000000000003E +:10527000000000000000000000000000000000002E +:10528000000000000000000000000000000000001E +:10529000000000000000000000000000000000000E +:1052A00000000000000000000000000000000000FE +:1052B00000000000000000000000000000000000EE +:1052C00000000000000000000000000000000000DE +:1052D00000000000000000000000000000000000CE +:1052E00000000000000000000000000000000000BE +:1052F00000000000000000000000000000000000AE +:10530000000000000000000000000000000000009D +:10531000000000000000000000000000000000008D +:10532000000000000000000000000000000000007D +:10533000000000000000000000000000000000006D +:10534000000000000000000000000000000000005D +:10535000000000000000000000000000000000004D +:10536000000000000000000000000000000000003D +:10537000000000000000000000000000000000002D +:10538000000000000000000000000000000000001D +:10539000000000000000000000000000000000000D +:1053A00000000000000000000000000000000000FD +:1053B00000000000000000000000000000000000ED +:1053C00000000000000000000000000000000000DD +:1053D00000000000000000000000000000000000CD +:1053E00000000000000000000000000000000000BD +:1053F00000000000000000000000000000000000AD +:10540000000000000000000000000000000000009C +:10541000000000000000000000000000000000008C +:10542000000000000000000000000000000000007C +:10543000000000000000000000000000000000006C +:10544000000000000000000000000000000000005C +:10545000000000000000000000000000000000004C +:10546000000000000000000000000000000000003C +:10547000000000000000000000000000000000002C +:10548000000000000000000000000000000000001C +:10549000000000000000000000000000000000000C +:1054A00000000000000000000000000000000000FC +:1054B00000000000000000000000000000000000EC +:1054C00000000000000000000000000000000000DC +:1054D00000000000000000000000000000000000CC +:1054E00000000000000000000000000000000000BC +:1054F00000000000000000000000000000000000AC +:10550000000000000000000000000000000000009B +:10551000000000000000000000000000000000008B +:10552000000000000000000000000000000000007B +:10553000000000000000000000000000000000006B +:10554000000000000000000000000000000000005B +:10555000000000000000000000000000000000004B +:10556000000000000000000000000000000000003B +:10557000000000000000000000000000000000002B +:10558000000000000000000000000000000000001B +:10559000000000000000000000000000000000000B +:1055A00000000000000000000000000000000000FB +:1055B00000000000000000000000000000000000EB +:1055C00000000000000000000000000000000000DB +:1055D00000000000000000000000000000000000CB +:1055E00000000000000000000000000000000000BB +:1055F00000000000000000000000000000000000AB +:10560000000000000000000000000000000000009A +:10561000000000000000000000000000000000008A +:10562000000000000000000000000000000000007A +:10563000000000000000000000000000000000006A +:10564000000000000000000000000000000000005A +:10565000000000000000000000000000000000004A +:10566000000000000000000000000000000000003A +:10567000000000000000000000000000000000002A +:10568000000000000000000000000000000000001A +:10569000000000000000000000000000000000000A +:1056A00000000000000000000000000000000000FA +:1056B00000000000000000000000000000000000EA +:1056C00000000000000000000000000000000000DA +:1056D00000000000000000000000000000000000CA +:1056E00000000000000000000000000000000000BA +:1056F00000000000000000000000000000000000AA +:105700000000000000000000000000000000000099 +:105710000000000000000000000000000000000089 +:105720000000000000000000000000000000000079 +:105730000000000000000000000000000000000069 +:105740000000000000000000000000000000000059 +:105750000000000000000000000000000000000049 +:105760000000000000000000000000000000000039 +:105770000000000000000000000000000000000029 +:105780000000000000000000000000000000000019 +:105790000000000000000000000000000000000009 +:1057A00000000000000000000000000000000000F9 +:1057B00000000000000000000000000000000000E9 +:1057C00000000000000000000000000000000000D9 +:1057D00000000000000000000000000000000000C9 +:1057E00000000000000000000000000000000000B9 +:1057F00000000000000000000000000000000000A9 +:105800000000000000000000000000000000000098 +:105810000000000000000000000000000000000088 +:105820000000000000000000000000000000000078 +:105830000000000000000000000000000000000068 +:105840000000000000000000000000000000000058 +:105850000000000000000000000000000000000048 +:105860000000000000000000000000000000000038 +:105870000000000000000000000000000000000028 +:105880000000000000000000000000000000000018 +:105890000000000000000000000000000000000008 +:1058A00000000000000000000000000000000000F8 +:1058B00000000000000000000000000000000000E8 +:1058C00000000000000000000000000000000000D8 +:1058D00000000000000000000000000000000000C8 +:1058E00000000000000000000000000000000000B8 +:1058F00000000000000000000000000000000000A8 +:105900000000000000000000000000000000000097 +:105910000000000000000000000000000000000087 +:105920000000000000000000000000000000000077 +:105930000000000000000000000000000000000067 +:105940000000000000000000000000000000000057 +:105950000000000000000000000000000000000047 +:105960000000000000000000000000000000000037 +:105970000000000000000000000000000000000027 +:105980000000000000000000000000000000000017 +:105990000000000000000000000000000000000007 +:1059A00000000000000000000000000000000000F7 +:1059B00000000000000000000000000000000000E7 +:1059C00000000000000000000000000000000000D7 +:1059D00000000000000000000000000000000000C7 +:1059E00000000000000000000000000000000000B7 +:1059F00000000000000000000000000000000000A7 +:105A00000000000000000000000000000000000096 +:105A10000000000000000000000000000000000086 +:105A20000000000000000000000000000000000076 +:105A30000000000000000000000000000000000066 +:105A40000000000000000000000000000000000056 +:105A50000000000000000000000000000000000046 +:105A60000000000000000000000000000000000036 +:105A70000000000000000000000000000000000026 +:105A80000000000000000000000000000000000016 +:105A90000000000000000000000000000000000006 +:105AA00000000000000000000000000000000000F6 +:105AB00000000000000000000000000000000000E6 +:105AC00000000000000000000000000000000000D6 +:105AD00000000000000000000000000000000000C6 +:105AE00000000000000000000000000000000000B6 +:105AF00000000000000000000000000000000000A6 +:105B00000000000000000000000000000000000095 +:105B10000000000000000000000000000000000085 +:105B20000000000000000000000000000000000075 +:105B30000000000000000000000000000000000065 +:105B40000000000000000000000000000000000055 +:105B50000000000000000000000000000000000045 +:105B60000000000000000000000000000000000035 +:105B70000000000000000000000000000000000025 +:105B80000000000000000000000000000000000015 +:105B90000000000000000000000000000000000005 +:105BA00000000000000000000000000000000000F5 +:105BB00000000000000000000000000000000000E5 +:105BC00000000000000000000000000000000000D5 +:105BD00000000000000000000000000000000000C5 +:105BE00000000000000000000000000000000000B5 +:105BF00000000000000000000000000000000000A5 +:105C00000000000000000000000000000000000094 +:105C10000000000000000000000000000000000084 +:105C20000000000000000000000000000000000074 +:105C30000000000000000000000000000000000064 +:105C40000000000000000000000000000000000054 +:105C50000000000000000000000000000000000044 +:105C60000000000000000000000000000000000034 +:105C70000000000000000000000000000000000024 +:105C80000000000000000000000000000000000014 +:105C90000000000000000000000000000000000004 +:105CA00000000000000000000000000000000000F4 +:105CB00000000000000000000000000000000000E4 +:105CC00000000000000000000000000000000000D4 +:105CD00000000000000000000000000000000000C4 +:105CE00000000000000000000000000000000000B4 +:105CF00000000000000000000000000000000000A4 +:105D00000000000000000000000000000000000093 +:105D10000000000000000000000000000000000083 +:105D20000000000000000000000000000000000073 +:105D30000000000000000000000000000000000063 +:105D40000000000000000000000000000000000053 +:105D50000000000000000000000000000000000043 +:105D60000000000000000000000000000000000033 +:105D70000000000000000000000000000000000023 +:105D80000000000000000000000000000000000013 +:105D90000000000000000000000000000000000003 +:105DA00000000000000000000000000000000000F3 +:105DB00000000000000000000000000000000000E3 +:105DC00000000000000000000000000000000000D3 +:105DD00000000000000000000000000000000000C3 +:105DE00000000000000000000000000000000000B3 +:105DF00000000000000000000000000000000000A3 +:105E00000000000000000000000000000000000092 +:105E10000000000000000000000000000000000082 +:105E20000000000000000000000000000000000072 +:105E30000000000000000000000000000000000062 +:105E40000000000000000000000000000000000052 +:105E50000000000000000000000000000000000042 +:105E60000000000000000000000000000000000032 +:105E70000000000000000000000000000000000022 +:105E80000000000000000000000000000000000012 +:105E90000000000000000000000000000000000002 +:105EA00000000000000000000000000000000000F2 +:105EB00000000000000000000000000000000000E2 +:105EC00000000000000000000000000000000000D2 +:105ED00000000000000000000000000000000000C2 +:105EE00000000000000000000000000000000000B2 +:105EF00000000000000000000000000000000000A2 +:105F00000000000000000000000000000000000091 +:105F10000000000000000000000000000000000081 +:105F20000000000000000000000000000000000071 +:105F30000000000000000000000000000000000061 +:105F40000000000000000000000000000000000051 +:105F50000000000000000000000000000000000041 +:105F60000000000000000000000000000000000031 +:105F70000000000000000000000000000000000021 +:105F80000000000000000000000000000000000011 +:105F90000000000000000000000000000000000001 +:105FA00000000000000000000000000000000000F1 +:105FB00000000000000000000000000000000000E1 +:105FC00000000000000000000000000000000000D1 +:105FD00000000000000000000000000000000000C1 +:105FE00000000000000000000000000000000000B1 +:105FF00000000000000000000000000000000000A1 +:106000000000000000000000000000000000000090 +:106010000000000000000000000000000000000080 +:106020000000000000000000000000000000000070 +:106030000000000000000000000000000000000060 +:106040000000000000000000000000000000000050 +:106050000000000000000000000000000000000040 +:106060000000000000000000000000000000000030 +:106070000000000000000000000000000000000020 +:106080000000000000000000000000000000000010 +:106090000000000000000000000000000000000000 +:1060A00000000000000000000000000000000000F0 +:1060B00000000000000000000000000000000000E0 +:1060C00000000000000000000000000000000000D0 +:1060D00000000000000000000000000000000000C0 +:1060E00000000000000000000000000000000000B0 +:1060F00000000000000000000000000000000000A0 +:10610000000000000000000000000000000000008F +:10611000000000000000000000000000000000007F +:10612000000000000000000000000000000000006F +:10613000000000000000000000000000000000005F +:10614000000000000000000000000000000000004F +:10615000000000000000000000000000000000003F +:10616000000000000000000000000000000000002F +:10617000000000000000000000000000000000001F +:10618000000000000000000000000000000000000F +:1061900000000000000000000000000000000000FF +:1061A00000000000000000000000000000000000EF +:1061B00000000000000000000000000000000000DF +:1061C00000000000000000000000000000000000CF +:1061D00000000000000000000000000000000000BF +:1061E00000000000000000000000000000000000AF +:1061F000000000000000000000000000000000009F +:10620000000000000000000000000000000000008E +:10621000000000000000000000000000000000007E +:10622000000000000000000000000000000000006E +:10623000000000000000000000000000000000005E +:10624000000000000000000000000000000000004E +:10625000000000000000000000000000000000003E +:10626000000000000000000000000000000000002E +:10627000000000000000000000000000000000001E +:10628000000000000000000000000000000000000E +:1062900000000000000000000000000000000000FE +:1062A00000000000000000000000000000000000EE +:1062B00000000000000000000000000000000000DE +:1062C00000000000000000000000000000000000CE +:1062D00000000000000000000000000000000000BE +:1062E00000000000000000000000000000000000AE +:1062F000000000000000000000000000000000009E +:10630000000000000000000000000000000000008D +:10631000000000000000000000000000000000007D +:10632000000000000000000000000000000000006D +:10633000000000000000000000000000000000005D +:10634000000000000000000000000000000000004D +:10635000000000000000000000000000000000003D +:10636000000000000000000000000000000000002D +:10637000000000000000000000000000000000001D +:10638000000000000000000000000000000000000D +:1063900000000000000000000000000000000000FD +:1063A00000000000000000000000000000000000ED +:1063B00000000000000000000000000000000000DD +:1063C00000000000000000000000000000000000CD +:1063D00000000000000000000000000000000000BD +:1063E00000000000000000000000000000000000AD +:1063F000000000000000000000000000000000009D +:10640000000000000000000000000000000000008C +:10641000000000000000000000000000000000007C +:10642000000000000000000000000000000000006C +:10643000000000000000000000000000000000005C +:10644000000000000000000000000000000000004C +:10645000000000000000000000000000000000003C +:10646000000000000000000000000000000000002C +:10647000000000000000000000000000000000001C +:10648000000000000000000000000000000000000C +:1064900000000000000000000000000000000000FC +:1064A00000000000000000000000000000000000EC +:1064B00000000000000000000000000000000000DC +:1064C00000000000000000000000000000000000CC +:1064D00000000000000000000000000000000000BC +:1064E00000000000000000000000000000000000AC +:1064F000000000000000000000000000000000009C +:10650000000000000000000000000000000000008B +:10651000000000000000000000000000000000007B +:10652000000000000000000000000000000000006B +:10653000000000000000000000000000000000005B +:10654000000000000000000000000000000000004B +:10655000000000000000000000000000000000003B +:10656000000000000000000000000000000000002B +:10657000000000000000000000000000000000001B +:10658000000000000000000000000000000000000B +:1065900000000000000000000000000000000000FB +:1065A00000000000000000000000000000000000EB +:1065B00000000000000000000000000000000000DB +:1065C00000000000000000000000000000000000CB +:1065D00000000000000000000000000000000000BB +:1065E00000000000000000000000000000000000AB +:1065F000000000000000000000000000000000009B +:10660000000000000000000000000000000000008A +:10661000000000000000000000000000000000007A +:10662000000000000000000000000000000000006A +:10663000000000000000000000000000000000005A +:10664000000000000000000000000000000000004A +:10665000000000000000000000000000000000003A +:10666000000000000000000000000000000000002A +:10667000000000000000000000000000000000001A +:10668000000000000000000000000000000000000A +:1066900000000000000000000000000000000000FA +:1066A00000000000000000000000000000000000EA +:1066B00000000000000000000000000000000000DA +:1066C00000000000000000000000000000000000CA +:1066D00000000000000000000000000000000000BA +:1066E00000000000000000000000000000000000AA +:1066F000000000000000000000000000000000009A +:106700000000000000000000000000000000000089 +:106710000000000000000000000000000000000079 +:106720000000000000000000000000000000000069 +:106730000000000000000000000000000000000059 +:106740000000000000000000000000000000000049 +:106750000000000000000000000000000000000039 +:106760000000000000000000000000000000000029 +:106770000000000000000000000000000000000019 +:106780000000000000000000000000000000000009 +:1067900000000000000000000000000000000000F9 +:1067A00000000000000000000000000000000000E9 +:1067B00000000000000000000000000000000000D9 +:1067C00000000000000000000000000000000000C9 +:1067D00000000000000000000000000000000000B9 +:1067E00000000000000000000000000000000000A9 +:1067F0000000000000000000000000000000000099 +:106800000000000000000000000000000000000088 +:106810000000000000000000000000000000000078 +:106820000000000000000000000000000000000068 +:106830000000000000000000000000000000000058 +:106840000000000000000000000000000000000048 +:106850000000000000000000000000000000000038 +:106860000000000000000000000000000000000028 +:106870000000000000000000000000000000000018 +:106880000000000000000000000000000000000008 +:1068900000000000000000000000000000000000F8 +:1068A00000000000000000000000000000000000E8 +:1068B00000000000000000000000000000000000D8 +:1068C00000000000000000000000000000000000C8 +:1068D00000000000000000000000000000000000B8 +:1068E00000000000000000000000000000000000A8 +:1068F0000000000000000000000000000000000098 +:106900000000000000000000000000000000000087 +:106910000000000000000000000000000000000077 +:106920000000000000000000000000000000000067 +:106930000000000000000000000000000000000057 +:106940000000000000000000000000000000000047 +:106950000000000000000000000000000000000037 +:106960000000000000000000000000000000000027 +:106970000000000000000000000000000000000017 +:106980000000000000000000000000000000000007 +:1069900000000000000000000000000000000000F7 +:1069A00000000000000000000000000000000000E7 +:1069B00000000000000000000000000000000000D7 +:1069C00000000000000000000000000000000000C7 +:1069D00000000000000000000000000000000000B7 +:1069E00000000000000000000000000000000000A7 +:1069F0000000000000000000000000000000000097 +:106A00000000000000000000000000000000000086 +:106A10000000000000000000000000000000000076 +:106A20000000000000000000000000000000000066 +:106A30000000000000000000000000000000000056 +:106A40000000000000000000000000000000000046 +:106A50000000000000000000000000000000000036 +:106A60000000000000000000000000000000000026 +:106A70000000000000000000000000000000000016 +:106A80000000000000000000000000000000000006 +:106A900000000000000000000000000000000000F6 +:106AA00000000000000000000000000000000000E6 +:106AB00000000000000000000000000000000000D6 +:106AC00000000000000000000000000000000000C6 +:106AD00000000000000000000000000000000000B6 +:106AE00000000000000000000000000000000000A6 +:106AF0000000000000000000000000000000000096 +:106B00000000000000000000000000000000000085 +:106B10000000000000000000000000000000000075 +:106B20000000000000000000000000000000000065 +:106B30000000000000000000000000000000000055 +:106B40000000000000000000000000000000000045 +:106B50000000000000000000000000000000000035 +:106B60000000000000000000000000000000000025 +:106B70000000000000000000000000000000000015 +:106B80000000000000000000000000000000000005 +:106B900000000000000000000000000000000000F5 +:106BA00000000000000000000000000000000000E5 +:106BB00000000000000000000000000000000000D5 +:106BC00000000000000000000000000000000000C5 +:106BD00000000000000000000000000000000000B5 +:106BE00000000000000000000000000000000000A5 +:106BF0000000000000000000000000000000000095 +:106C00000000000000000000000000000000000084 +:106C10000000000000000000000000000000000074 +:106C20000000000000000000000000000000000064 +:106C30000000000000000000000000000000000054 +:106C40000000000000000000000000000000000044 +:106C50000000000000000000000000000000000034 +:106C60000000000000000000000000000000000024 +:106C70000000000000000000000000000000000014 +:106C80000000000000000000000000000000000004 +:106C900000000000000000000000000000000000F4 +:106CA00000000000000000000000000000000000E4 +:106CB00000000000000000000000000000000000D4 +:106CC00000000000000000000000000000000000C4 +:106CD00000000000000000000000000000000000B4 +:106CE00000000000000000000000000000000000A4 +:106CF0000000000000000000000000000000000094 +:106D00000000000000000000000000000000000083 +:106D10000000000000000000000000000000000073 +:106D20000000000000000000000000000000000063 +:106D30000000000000000000000000000000000053 +:106D40000000000000000000000000000000000043 +:106D50000000000000000000000000000000000033 +:106D60000000000000000000000000000000000023 +:106D70000000000000000000000000000000000013 +:106D80000000000000000000000000000000000003 +:106D900000000000000000000000000000000000F3 +:106DA00000000000000000000000000000000000E3 +:106DB00000000000000000000000000000000000D3 +:106DC00000000000000000000000000000000000C3 +:106DD00000000000000000000000000000000000B3 +:106DE00000000000000000000000000000000000A3 +:106DF0000000000000000000000000000000000093 +:106E00000000000000000000000000000000000082 +:106E10000000000000000000000000000000000072 +:106E20000000000000000000000000000000000062 +:106E30000000000000000000000000000000000052 +:106E40000000000000000000000000000000000042 +:106E50000000000000000000000000000000000032 +:106E60000000000000000000000000000000000022 +:106E70000000000000000000000000000000000012 +:106E80000000000000000000000000000000000002 +:106E900000000000000000000000000000000000F2 +:106EA00000000000000000000000000000000000E2 +:106EB00000000000000000000000000000000000D2 +:106EC00000000000000000000000000000000000C2 +:106ED00000000000000000000000000000000000B2 +:106EE00000000000000000000000000000000000A2 +:106EF0000000000000000000000000000000000092 +:106F00000000000000000000000000000000000081 +:106F10000000000000000000000000000000000071 +:106F20000000000000000000000000000000000061 +:106F30000000000000000000000000000000000051 +:106F40000000000000000000000000000000000041 +:106F50000000000000000000000000000000000031 +:106F60000000000000000000000000000000000021 +:106F70000000000000000000000000000000000011 +:106F80000000000000000000000000000000000001 +:106F900000000000000000000000000000000000F1 +:106FA00000000000000000000000000000000000E1 +:106FB00000000000000000000000000000000000D1 +:106FC00000000000000000000000000000000000C1 +:106FD00000000000000000000000000000000000B1 +:106FE00000000000000000000000000000000000A1 +:106FF0000000000000000000000000000000000091 +:107000000000000000000000000000000000000080 +:107010000000000000000000000000000000000070 +:107020000000000000000000000000000000000060 +:107030000000000000000000000000000000000050 +:107040000000000000000000000000000000000040 +:107050000000000000000000000000000000000030 +:107060000000000000000000000000000000000020 +:107070000000000000000000000000000000000010 +:107080000000000000000000000000000000000000 +:1070900000000000000000000000000000000000F0 +:1070A00000000000000000000000000000000000E0 +:1070B00000000000000000000000000000000000D0 +:1070C00000000000000000000000000000000000C0 +:1070D00000000000000000000000000000000000B0 +:1070E00000000000000000000000000000000000A0 +:1070F0000000000000000000000000000000000090 +:10710000000000000000000000000000000000007F +:10711000000000000000000000000000000000006F +:10712000000000000000000000000000000000005F +:10713000000000000000000000000000000000004F +:10714000000000000000000000000000000000003F +:10715000000000000000000000000000000000002F +:10716000000000000000000000000000000000001F +:10717000000000000000000000000000000000000F +:1071800000000000000000000000000000000000FF +:1071900000000000000000000000000000000000EF +:1071A00000000000000000000000000000000000DF +:1071B00000000000000000000000000000000000CF +:1071C00000000000000000000000000000000000BF +:1071D00000000000000000000000000000000000AF +:1071E000000000000000000000000000000000009F +:1071F000000000000000000000000000000000008F +:10720000000000000000000000000000000000007E +:10721000000000000000000000000000000000006E +:10722000000000000000000000000000000000005E +:10723000000000000000000000000000000000004E +:10724000000000000000000000000000000000003E +:10725000000000000000000000000000000000002E +:10726000000000000000000000000000000000001E +:10727000000000000000000000000000000000000E +:1072800000000000000000000000000000000000FE +:1072900000000000000000000000000000000000EE +:1072A00000000000000000000000000000000000DE +:1072B00000000000000000000000000000000000CE +:1072C00000000000000000000000000000000000BE +:1072D00000000000000000000000000000000000AE +:1072E000000000000000000000000000000000009E +:1072F000000000000000000000000000000000008E +:10730000000000000000000000000000000000007D +:10731000000000000000000000000000000000006D +:10732000000000000000000000000000000000005D +:10733000000000000000000000000000000000004D +:10734000000000000000000000000000000000003D +:10735000000000000000000000000000000000002D +:10736000000000000000000000000000000000001D +:10737000000000000000000000000000000000000D +:1073800000000000000000000000000000000000FD +:1073900000000000000000000000000000000000ED +:1073A00000000000000000000000000000000000DD +:1073B00000000000000000000000000000000000CD +:1073C00000000000000000000000000000000000BD +:1073D00000000000000000000000000000000000AD +:1073E000000000000000000000000000000000009D +:1073F000000000000000000000000000000000008D +:10740000000000000000000000000000000000007C +:10741000000000000000000000000000000000006C +:10742000000000000000000000000000000000005C +:10743000000000000000000000000000000000004C +:10744000000000000000000000000000000000003C +:10745000000000000000000000000000000000002C +:10746000000000000000000000000000000000001C +:10747000000000000000000000000000000000000C +:1074800000000000000000000000000000000000FC +:1074900000000000000000000000000000000000EC +:1074A00000000000000000000000000000000000DC +:1074B00000000000000000000000000000000000CC +:1074C00000000000000000000000000000000000BC +:1074D00000000000000000000000000000000000AC +:1074E000000000000000000000000000000000009C +:1074F000000000000000000000000000000000008C +:10750000000000000000000000000000000000007B +:10751000000000000000000000000000000000006B +:10752000000000000000000000000000000000005B +:10753000000000000000000000000000000000004B +:10754000000000000000000000000000000000003B +:10755000000000000000000000000000000000002B +:10756000000000000000000000000000000000001B +:10757000000000000000000000000000000000000B +:1075800000000000000000000000000000000000FB +:1075900000000000000000000000000000000000EB +:1075A00000000000000000000000000000000000DB +:1075B00000000000000000000000000000000000CB +:1075C00000000000000000000000000000000000BB +:1075D00000000000000000000000000000000000AB +:1075E000000000000000000000000000000000009B +:1075F000000000000000000000000000000000008B +:10760000000000000000000000000000000000007A +:10761000000000000000000000000000000000006A +:10762000000000000000000000000000000000005A +:10763000000000000000000000000000000000004A +:10764000000000000000000000000000000000003A +:10765000000000000000000000000000000000002A +:10766000000000000000000000000000000000001A +:10767000000000000000000000000000000000000A +:1076800000000000000000000000000000000000FA +:1076900000000000000000000000000000000000EA +:1076A00000000000000000000000000000000000DA +:1076B00000000000000000000000000000000000CA +:1076C00000000000000000000000000000000000BA +:1076D00000000000000000000000000000000000AA +:1076E000000000000000000000000000000000009A +:1076F000000000000000000000000000000000008A +:107700000000000000000000000000000000000079 +:107710000000000000000000000000000000000069 +:107720000000000000000000000000000000000059 +:107730000000000000000000000000000000000049 +:107740000000000000000000000000000000000039 +:107750000000000000000000000000000000000029 +:107760000000000000000000000000000000000019 +:107770000000000000000000000000000000000009 +:1077800000000000000000000000000000000000F9 +:1077900000000000000000000000000000000000E9 +:1077A00000000000000000000000000000000000D9 +:1077B00000000000000000000000000000000000C9 +:1077C00000000000000000000000000000000000B9 +:1077D00000000000000000000000000000000000A9 +:1077E0000000000000000000000000000000000099 +:1077F0000000000000000000000000000000000089 +:107800000000000000000000000000000000000078 +:107810000000000000000000000000000000000068 +:107820000000000000000000000000000000000058 +:107830000000000000000000000000000000000048 +:107840000000000000000000000000000000000038 +:107850000000000000000000000000000000000028 +:107860000000000000000000000000000000000018 +:107870000000000000000000000000000000000008 +:1078800000000000000000000000000000000000F8 +:1078900000000000000000000000000000000000E8 +:1078A00000000000000000000000000000000000D8 +:1078B00000000000000000000000000000000000C8 +:1078C00000000000000000000000000000000000B8 +:1078D00000000000000000000000000000000000A8 +:1078E0000000000000000000000000000000000098 +:1078F0000000000000000000000000000000000088 +:107900000000000000000000000000000000000077 +:107910000000000000000000000000000000000067 +:107920000000000000000000000000000000000057 +:107930000000000000000000000000000000000047 +:107940000000000000000000000000000000000037 +:107950000000000000000000000000000000000027 +:107960000000000000000000000000000000000017 +:107970000000000000000000000000000000000007 +:1079800000000000000000000000000000000000F7 +:1079900000000000000000000000000000000000E7 +:1079A00000000000000000000000000000000000D7 +:1079B00000000000000000000000000000000000C7 +:1079C00000000000000000000000000000000000B7 +:1079D00000000000000000000000000000000000A7 +:1079E0000000000000000000000000000000000097 +:1079F0000000000000000000000000000000000087 +:107A00000000000000000000000000000000000076 +:107A10000000000000000000000000000000000066 +:107A20000000000000000000000000000000000056 +:107A30000000000000000000000000000000000046 +:107A40000000000000000000000000000000000036 +:107A50000000000000000000000000000000000026 +:107A60000000000000000000000000000000000016 +:107A70000000000000000000000000000000000006 +:107A800000000000000000000000000000000000F6 +:107A900000000000000000000000000000000000E6 +:107AA00000000000000000000000000000000000D6 +:107AB00000000000000000000000000000000000C6 +:107AC00000000000000000000000000000000000B6 +:107AD00000000000000000000000000000000000A6 +:107AE0000000000000000000000000000000000096 +:107AF0000000000000000000000000000000000086 +:107B00000000000000000000000000000000000075 +:107B10000000000000000000000000000000000065 +:107B20000000000000000000000000000000000055 +:107B30000000000000000000000000000000000045 +:107B40000000000000000000000000000000000035 +:107B50000000000000000000000000000000000025 +:107B60000000000000000000000000000000000015 +:107B70000000000000000000000000000000000005 +:107B800000000000000000000000000000000000F5 +:107B900000000000000000000000000000000000E5 +:107BA00000000000000000000000000000000000D5 +:107BB00000000000000000000000000000000000C5 +:107BC00000000000000000000000000000000000B5 +:107BD00000000000000000000000000000000000A5 +:107BE0000000000000000000000000000000000095 +:107BF0000000000000000000000000000000000085 +:107C00000000000000000000000000000000000074 +:107C10000000000000000000000000000000000064 +:107C20000000000000000000000000000000000054 +:107C30000000000000000000000000000000000044 +:107C40000000000000000000000000000000000034 +:107C50000000000000000000000000000000000024 +:107C60000000000000000000000000000000000014 +:107C70000000000000000000000000000000000004 +:107C800000000000000000000000000000000000F4 +:107C900000000000000000000000000000000000E4 +:107CA00000000000000000000000000000000000D4 +:107CB00000000000000000000000000000000000C4 +:107CC00000000000000000000000000000000000B4 +:107CD00000000000000000000000000000000000A4 +:107CE0000000000000000000000000000000000094 +:107CF0000000000000000000000000000000000084 +:107D00000000000000000000000000000000000073 +:107D10000000000000000000000000000000000063 +:107D20000000000000000000000000000000000053 +:107D30000000000000000000000000000000000043 +:107D40000000000000000000000000000000000033 +:107D50000000000000000000000000000000000023 +:107D60000000000000000000000000000000000013 +:107D70000000000000000000000000000000000003 +:107D800000000000000000000000000000000000F3 +:107D900000000000000000000000000000000000E3 +:107DA00000000000000000000000000000000000D3 +:107DB00000000000000000000000000000000000C3 +:107DC00000000000000000000000000000000000B3 +:107DD00000000000000000000000000000000000A3 +:107DE0000000000000000000000000000000000093 +:107DF0000000000000000000000000000000000083 +:107E00000000000000000000000000000000000072 +:107E10000000000000000000000000000000000062 +:107E20000000000000000000000000000000000052 +:107E30000000000000000000000000000000000042 +:107E40000000000000000000000000000000000032 +:107E50000000000000000000000000000000000022 +:107E60000000000000000000000000000000000012 +:107E70000000000000000000000000000000000002 +:107E800000000000000000000000000000000000F2 +:107E900000000000000000000000000000000000E2 +:107EA00000000000000000000000000000000000D2 +:107EB00000000000000000000000000000000000C2 +:107EC00000000000000000000000000000000000B2 +:107ED00000000000000000000000000000000000A2 +:107EE0000000000000000000000000000000000092 +:107EF0000000000000000000000000000000000082 +:107F00000000000000000000000000000000000071 +:107F10000000000000000000000000000000000061 +:107F20000000000000000000000000000000000051 +:107F30000000000000000000000000000000000041 +:107F40000000000000000000000000000000000031 +:107F50000000000000000000000000000000000021 +:107F60000000000000000000000000000000000011 +:107F70000000000000000000000000000000000001 +:107F800000000000000000000000000000000000F1 +:107F900000000000000000000000000000000000E1 +:107FA00000000000000000000000000000000000D1 +:107FB00000000000000000000000000000000000C1 +:107FC00000000000000000000000000000000000B1 +:107FD00000000000000000000000000000000000A1 +:107FE0000000000000000000000000000000000091 +:107FF0000000000000000000000000000000000081 +:108000000000000000000000000000000000000070 +:108010000000000000000000000000000000000060 +:108020000000000000000000000000000000000050 +:108030000000000000000000000000000000000040 +:108040000000000000000000000000000000000030 +:108050000000000000000000000000000000000020 +:108060000000000000000000000000000000000010 +:108070000000000000000000000000000000000000 +:1080800000000000000000000000000000000000F0 +:1080900000000000000000000000000000000000E0 +:1080A00000000000000000000000000000000000D0 +:1080B00000000000000000000000000000000000C0 +:1080C00000000000000000000000000000000000B0 +:1080D00000000000000000000000000000000000A0 +:1080E0000000000000000000000000000000000090 +:1080F0000000000000000000000000000000000080 +:10810000000000000000000000000000000000006F +:10811000000000000000000000000000000000005F +:10812000000000000000000000000000000000004F +:10813000000000000000000000000000000000003F +:10814000000000000000000000000000000000002F +:10815000000000000000000000000000000000001F +:10816000000000000000000000000000000000000F +:1081700000000000000000000000000000000000FF +:1081800000000000000000000000000000000000EF +:1081900000000000000000000000000000000000DF +:1081A00000000000000000000000000000000000CF +:1081B00000000000000000000000000000000000BF +:1081C00000000000000000000000000000000000AF +:1081D000000000000000000000000000000000009F +:1081E000000000000000000000000000000000008F +:1081F000000000000000000000000000000000007F +:10820000000000000000000000000000000000006E +:10821000000000000000000000000000000000005E +:10822000000000000000000000000000000000004E +:10823000000000000000000000000000000000003E +:10824000000000000000000000000000000000002E +:10825000000000000000000000000000000000001E +:10826000000000000000000000000000000000000E +:1082700000000000000000000000000000000000FE +:1082800000000000000000000000000000000000EE +:1082900000000000000000000000000000000000DE +:1082A00000000000000000000000000000000000CE +:1082B00000000000000000000000000000000000BE +:1082C00000000000000000000000000000000000AE +:1082D000000000000000000000000000000000009E +:1082E000000000000000000000000000000000008E +:1082F000000000000000000000000000000000007E +:10830000000000000000000000000000000000006D +:10831000000000000000000000000000000000005D +:10832000000000000000000000000000000000004D +:10833000000000000000000000000000000000003D +:10834000000000000000000000000000000000002D +:10835000000000000000000000000000000000001D +:10836000000000000000000000000000000000000D +:1083700000000000000000000000000000000000FD +:1083800000000000000000000000000000000000ED +:1083900000000000000000000000000000000000DD +:1083A00000000000000000000000000000000000CD +:1083B00000000000000000000000000000000000BD +:1083C00000000000000000000000000000000000AD +:1083D000000000000000000000000000000000009D +:1083E000000000000000000000000000000000008D +:1083F000000000000000000000000000000000007D +:10840000000000000000000000000000000000006C +:10841000000000000000000000000000000000005C +:10842000000000000000000000000000000000004C +:10843000000000000000000000000000000000003C +:10844000000000000000000000000000000000002C +:10845000000000000000000000000000000000001C +:10846000000000000000000000000000000000000C +:1084700000000000000000000000000000000000FC +:1084800000000000000000000000000000000000EC +:1084900000000000000000000000000000000000DC +:1084A00000000000000000000000000000000000CC +:1084B00000000000000000000000000000000000BC +:1084C00000000000000000000000000000000000AC +:1084D000000000000000000000000000000000009C +:1084E000000000000000000000000000000000008C +:1084F000000000000000000000000000000000007C +:10850000000000000000000000000000000000006B +:10851000000000000000000000000000000000005B +:10852000000000000000000000000000000000004B +:10853000000000000000000000000000000000003B +:10854000000000000000000000000000000000002B +:10855000000000000000000000000000000000001B +:10856000000000000000000000000000000000000B +:1085700000000000000000000000000000000000FB +:1085800000000000000000000000000000000000EB +:1085900000000000000000000000000000000000DB +:1085A00000000000000000000000000000000000CB +:1085B00000000000000000000000000000000000BB +:1085C00000000000000000000000000000000000AB +:1085D000000000000000000000000000000000009B +:1085E000000000000000000000000000000000008B +:1085F000000000000000000000000000000000007B +:10860000000000000000000000000000000000006A +:10861000000000000000000000000000000000005A +:10862000000000000000000000000000000000004A +:10863000000000000000000000000000000000003A +:10864000000000000000000000000000000000002A +:10865000000000000000000000000000000000001A +:10866000000000000000000000000000000000000A +:1086700000000000000000000000000000000000FA +:1086800000000000000000000000000000000000EA +:1086900000000000000000000000000000000000DA +:1086A00000000000000000000000000000000000CA +:1086B00000000000000000000000000000000000BA +:1086C00000000000000000000000000000000000AA +:1086D000000000000000000000000000000000009A +:1086E000000000000000000000000000000000008A +:1086F000000000000000000000000000000000007A +:108700000000000000000000000000000000000069 +:108710000000000000000000000000000000000059 +:108720000000000000000000000000000000000049 +:108730000000000000000000000000000000000039 +:108740000000000000000000000000000000000029 +:108750000000000000000000000000000000000019 +:108760000000000000000000000000000000000009 +:1087700000000000000000000000000000000000F9 +:1087800000000000000000000000000000000000E9 +:1087900000000000000000000000000000000000D9 +:1087A00000000000000000000000000000000000C9 +:1087B00000000000000000000000000000000000B9 +:1087C00000000000000000000000000000000000A9 +:1087D0000000000000000000000000000000000099 +:1087E0000000000000000000000000000000000089 +:1087F0000000000000000000000000000000000079 +:108800000000000000000000000000000000000068 +:108810000000000000000000000000000000000058 +:108820000000000000000000000000000000000048 +:108830000000000000000000000000000000000038 +:108840000000000000000000000000000000000028 +:108850000000000000000000000000000000000018 +:108860000000000000000000000000000000000008 +:1088700000000000000000000000000000000000F8 +:1088800000000000000000000000000000000000E8 +:1088900000000000000000000000000000000000D8 +:1088A00000000000000000000000000000000000C8 +:1088B00000000000000000000000000000000000B8 +:1088C00000000000000000000000000000000000A8 +:1088D0000000000000000000000000000000000098 +:1088E0000000000000000000000000000000000088 +:1088F0000000000000000000000000000000000078 +:108900000000000000000000000000000000000067 +:108910000000000000000000000000000000000057 +:108920000000000000000000000000000000000047 +:108930000000000000000000000000000000000037 +:108940000000000000000000000000000000000027 +:108950000000000000000000000000000000000017 +:108960000000000000000000000000000000000007 +:1089700000000000000000000000000000000000F7 +:1089800000000000000000000000000000000000E7 +:1089900000000000000000000000000000000000D7 +:1089A00000000000000000000000000000000000C7 +:1089B00000000000000000000000000000000000B7 +:1089C00000000000000000000000000000000000A7 +:1089D0000000000000000000000000000000000097 +:1089E0000000000000000000000000000000000087 +:1089F0000000000000000000000000000000000077 +:108A00000000000000000000000000000000000066 +:108A10000000000000000000000000000000000056 +:108A20000000000000000000000000000000000046 +:108A30000000000000000000000000000000000036 +:108A40000000000000000000000000000000000026 +:108A50000000000000000000000000000000000016 +:108A60000000000000000000000000000000000006 +:108A700000000000000000000000000000000000F6 +:108A800000000000000000000000000000000000E6 +:108A900000000000000000000000000000000000D6 +:108AA00000000000000000000000000000000000C6 +:108AB00000000000000000000000000000000000B6 +:108AC00000000000000000000000000000000000A6 +:108AD0000000000000000000000000000000000096 +:108AE0000000000000000000000000000000000086 +:108AF0000000000000000000000000000000000076 +:108B00000000000000000000000000000000000065 +:108B10000000000000000000000000000000000055 +:108B20000000000000000000000000000000000045 +:108B30000000000000000000000000000000000035 +:108B40000000000000000000000000000000000025 +:108B50000000000000000000000000000000000015 +:108B60000000000000000000000000000000000005 +:108B700000000000000000000000000000000000F5 +:108B800000000000000000000000000000000000E5 +:108B900000000000000000000000000000000000D5 +:108BA00000000000000000000000000000000000C5 +:108BB00000000000000000000000000000000000B5 +:108BC00000000000000000000000000000000000A5 +:108BD0000000000000000000000000000000000095 +:108BE0000000000000000000000000000000000085 +:108BF0000000000000000000000000000000000075 +:108C00000000000000000000000000000000000064 +:108C10000000000000000000000000000000000054 +:108C20000000000000000000000000000000000044 +:108C30000000000000000000000000000000000034 +:108C40000000000000000000000000000000000024 +:108C50000000000000000000000000000000000014 +:108C60000000000000000000000000000000000004 +:108C700000000000000000000000000000000000F4 +:108C800000000000000000000000000000000000E4 +:108C900000000000000000000000000000000000D4 +:108CA00000000000000000000000000000000000C4 +:108CB00000000000000000000000000000000000B4 +:108CC00000000000000000000000000000000000A4 +:108CD0000000000000000000000000000000000094 +:108CE0000000000000000000000000000000000084 +:108CF0000000000000000000000000000000000074 +:108D00000000000000000000000000000000000063 +:108D10000000000000000000000000000000000053 +:108D20000000000000000000000000000000000043 +:108D30000000000000000000000000000000000033 +:108D40000000000000000000000000000000000023 +:108D50000000000000000000000000000000000013 +:108D60000000000000000000000000000000000003 +:108D700000000000000000000000000000000000F3 +:108D800000000000000000000000000000000000E3 +:108D900000000000000000000000000000000000D3 +:108DA00000000000000000000000000000000000C3 +:108DB00000000000000000000000000000000000B3 +:108DC00000000000000000000000000000000000A3 +:108DD0000000000000000000000000000000000093 +:108DE0000000000000000000000000000000000083 +:108DF0000000000000000000000000000000000073 +:108E00000000000000000000000000000000000062 +:108E10000000000000000000000000000000000052 +:108E20000000000000000000000000000000000042 +:108E30000000000000000000000000000000000032 +:108E40000000000000000000000000000000000022 +:108E50000000000000000000000000000000000012 +:108E60000000000000000000000000000000000002 +:108E700000000000000000000000000000000000F2 +:108E800000000000000000000000000000000000E2 +:108E900000000000000000000000000000000000D2 +:108EA00000000000000000000000000000000000C2 +:108EB00000000000000000000000000000000000B2 +:108EC00000000000000000000000000000000000A2 +:108ED0000000000000000000000000000000000092 +:108EE0000000000000000000000000000000000082 +:108EF0000000000000000000000000000000000072 +:108F00000000000000000000000000000000000061 +:108F10000000000000000000000000000000000051 +:108F20000000000000000000000000000000000041 +:108F30000000000000000000000000000000000031 +:108F40000000000000000000000000000000000021 +:108F50000000000000000000000000000000000011 +:108F60000000000000000000000000000000000001 +:108F700000000000000000000000000000000000F1 +:108F800000000000000000000000000000000000E1 +:108F900000000000000000000000000000000000D1 +:108FA00000000000000000000000000000000000C1 +:108FB00000000000000000000000000000000000B1 +:108FC00000000000000000000000000000000000A1 +:108FD0000000000000000000000000000000000091 +:108FE0000000000000000000000000000000000081 +:108FF0000000000000000000000000000000000071 +:109000000000000000000000000000000000000060 +:109010000000000000000000000000000000000050 +:109020000000000000000000000000000000000040 +:109030000000000000000000000000000000000030 +:109040000000000000000000000000000000000020 +:109050000000000000000000000000000000000010 +:109060000000000000000000000000000000000000 +:1090700000000000000000000000000000000000F0 +:1090800000000000000000000000000000000000E0 +:1090900000000000000000000000000000000000D0 +:1090A00000000000000000000000000000000000C0 +:1090B00000000000000000000000000000000000B0 +:1090C00000000000000000000000000000000000A0 +:1090D0000000000000000000000000000000000090 +:1090E0000000000000000000000000000000000080 +:1090F0000000000000000000000000000000000070 +:10910000000000000000000000000000000000005F +:10911000000000000000000000000000000000004F +:10912000000000000000000000000000000000003F +:10913000000000000000000000000000000000002F +:10914000000000000000000000000000000000001F +:10915000000000000000000000000000000000000F +:1091600000000000000000000000000000000000FF +:1091700000000000000000000000000000000000EF +:1091800000000000000000000000000000000000DF +:1091900000000000000000000000000000000000CF +:1091A00000000000000000000000000000000000BF +:1091B00000000000000000000000000000000000AF +:1091C000000000000000000000000000000000009F +:1091D000000000000000000000000000000000008F +:1091E000000000000000000000000000000000007F +:1091F000000000000000000000000000000000006F +:10920000000000000000000000000000000000005E +:10921000000000000000000000000000000000004E +:10922000000000000000000000000000000000003E +:10923000000000000000000000000000000000002E +:10924000000000000000000000000000000000001E +:10925000000000000000000000000000000000000E +:1092600000000000000000000000000000000000FE +:1092700000000000000000000000000000000000EE +:1092800000000000000000000000000000000000DE +:1092900000000000000000000000000000000000CE +:1092A00000000000000000000000000000000000BE +:1092B00000000000000000000000000000000000AE +:1092C000000000000000000000000000000000009E +:1092D000000000000000000000000000000000008E +:1092E000000000000000000000000000000000007E +:1092F000000000000000000000000000000000006E +:10930000000000000000000000000000000000005D +:10931000000000000000000000000000000000004D +:10932000000000000000000000000000000000003D +:10933000000000000000000000000000000000002D +:10934000000000000000000000000000000000001D +:10935000000000000000000000000000000000000D +:1093600000000000000000000000000000000000FD +:1093700000000000000000000000000000000000ED +:1093800000000000000000000000000000000000DD +:1093900000000000000000000000000000000000CD +:1093A00000000000000000000000000000000000BD +:1093B00000000000000000000000000000000000AD +:1093C000000000000000000000000000000000009D +:1093D000000000000000000000000000000000008D +:1093E000000000000000000000000000000000007D +:1093F000000000000000000000000000000000006D +:10940000000000000000000000000000000000005C +:10941000000000000000000000000000000000004C +:10942000000000000000000000000000000000003C +:10943000000000000000000000000000000000002C +:10944000000000000000000000000000000000001C +:10945000000000000000000000000000000000000C +:1094600000000000000000000000000000000000FC +:1094700000000000000000000000000000000000EC +:1094800000000000000000000000000000000000DC +:1094900000000000000000000000000000000000CC +:1094A00000000000000000000000000000000000BC +:1094B00000000000000000000000000000000000AC +:1094C000000000000000000000000000000000009C +:1094D000000000000000000000000000000000008C +:1094E000000000000000000000000000000000007C +:1094F000000000000000000000000000000000006C +:10950000000000000000000000000000000000005B +:10951000000000000000000000000000000000004B +:10952000000000000000000000000000000000003B +:10953000000000000000000000000000000000002B +:10954000000000000000000000000000000000001B +:10955000000000000000000000000000000000000B +:1095600000000000000000000000000000000000FB +:1095700000000000000000000000000000000000EB +:1095800000000000000000000000000000000000DB +:1095900000000000000000000000000000000000CB +:1095A00000000000000000000000000000000000BB +:1095B00000000000000000000000000000000000AB +:1095C000000000000000000000000000000000009B +:1095D000000000000000000000000000000000008B +:1095E000000000000000000000000000000000007B +:1095F000000000000000000000000000000000006B +:10960000000000000000000000000000000000005A +:10961000000000000000000000000000000000004A +:10962000000000000000000000000000000000003A +:10963000000000000000000000000000000000002A +:10964000000000000000000000000000000000001A +:10965000000000000000000000000000000000000A +:1096600000000000000000000000000000000000FA +:1096700000000000000000000000000000000000EA +:1096800000000000000000000000000000000000DA +:1096900000000000000000000000000000000000CA +:1096A00000000000000000000000000000000000BA +:1096B00000000000000000000000000000000000AA +:1096C000000000000000000000000000000000009A +:1096D000000000000000000000000000000000008A +:1096E000000000000000000000000000000000007A +:1096F000000000000000000000000000000000006A +:109700000000000000000000000000000000000059 +:109710000000000000000000000000000000000049 +:109720000000000000000000000000000000000039 +:109730000000000000000000000000000000000029 +:109740000000000000000000000000000000000019 +:109750000000000000000000000000000000000009 +:1097600000000000000000000000000000000000F9 +:1097700000000000000000000000000000000000E9 +:1097800000000000000000000000000000000000D9 +:1097900000000000000000000000000000000000C9 +:1097A00000000000000000000000000000000000B9 +:1097B00000000000000000000000000000000000A9 +:1097C0000000000000000000000000000000000099 +:1097D0000000000000000000000000000000000089 +:1097E0000000000000000000000000000000000079 +:1097F0000000000000000000000000000000000069 +:109800000000000000000000000000000000000058 +:109810000000000000000000000000000000000048 +:109820000000000000000000000000000000000038 +:109830000000000000000000000000000000000028 +:109840000000000000000000000000000000000018 +:109850000000000000000000000000000000000008 +:1098600000000000000000000000000000000000F8 +:1098700000000000000000000000000000000000E8 +:1098800000000000000000000000000000000000D8 +:1098900000000000000000000000000000000000C8 +:1098A00000000000000000000000000000000000B8 +:1098B00000000000000000000000000000000000A8 +:1098C0000000000000000000000000000000000098 +:1098D0000000000000000000000000000000000088 +:1098E0000000000000000000000000000000000078 +:1098F0000000000000000000000000000000000068 +:109900000000000000000000000000000000000057 +:109910000000000000000000000000000000000047 +:109920000000000000000000000000000000000037 +:109930000000000000000000000000000000000027 +:109940000000000000000000000000000000000017 +:109950000000000000000000000000000000000007 +:1099600000000000000000000000000000000000F7 +:1099700000000000000000000000000000000000E7 +:1099800000000000000000000000000000000000D7 +:1099900000000000000000000000000000000000C7 +:1099A00000000000000000000000000000000000B7 +:1099B00000000000000000000000000000000000A7 +:1099C0000000000000000000000000000000000097 +:1099D0000000000000000000000000000000000087 +:1099E0000000000000000000000000000000000077 +:1099F0000000000000000000000000000000000067 +:109A00000000000000000000000000000000000056 +:109A10000000000000000000000000000000000046 +:109A20000000000000000000000000000000000036 +:109A30000000000000000000000000000000000026 +:109A40000000000000000000000000000000000016 +:109A50000000000000000000000000000000000006 +:109A600000000000000000000000000000000000F6 +:109A700000000000000000000000000000000000E6 +:109A800000000000000000000000000000000000D6 +:109A900000000000000000000000000000000000C6 +:109AA00000000000000000000000000000000000B6 +:109AB00000000000000000000000000000000000A6 +:109AC0000000000000000000000000000000000096 +:109AD0000000000000000000000000000000000086 +:109AE0000000000000000000000000000000000076 +:109AF0000000000000000000000000000000000066 +:109B00000000000000000000000000000000000055 +:109B10000000000000000000000000000000000045 +:109B20000000000000000000000000000000000035 +:109B30000000000000000000000000000000000025 +:109B40000000000000000000000000000000000015 +:109B50000000000000000000000000000000000005 +:109B600000000000000000000000000000000000F5 +:109B700000000000000000000000000000000000E5 +:109B800000000000000000000000000000000000D5 +:109B900000000000000000000000000000000000C5 +:109BA00000000000000000000000000000000000B5 +:109BB00000000000000000000000000000000000A5 +:109BC0000000000000000000000000000000000095 +:109BD0000000000000000000000000000000000085 +:109BE0000000000000000000000000000000000075 +:109BF0000000000000000000000000000000000065 +:109C00000000000000000000000000000000000054 +:109C10000000000000000000000000000000000044 +:109C20000000000000000000000000000000000034 +:109C30000000000000000000000000000000000024 +:109C40000000000000000000000000000000000014 +:109C50000000000000000000000000000000000004 +:109C600000000000000000000000000000000000F4 +:109C700000000000000000000000000000000000E4 +:109C800000000000000000000000000000000000D4 +:109C900000000000000000000000000000000000C4 +:109CA00000000000000000000000000000000000B4 +:109CB00000000000000000000000000000000000A4 +:109CC0000000000000000000000000000000000094 +:109CD0000000000000000000000000000000000084 +:109CE0000000000000000000000000000000000074 +:109CF0000000000000000000000000000000000064 +:109D00000000000000000000000000000000000053 +:109D10000000000000000000000000000000000043 +:109D20000000000000000000000000000000000033 +:109D30000000000000000000000000000000000023 +:109D40000000000000000000000000000000000013 +:109D50000000000000000000000000000000000003 +:109D600000000000000000000000000000000000F3 +:109D700000000000000000000000000000000000E3 +:109D800000000000000000000000000000000000D3 +:109D900000000000000000000000000000000000C3 +:109DA00000000000000000000000000000000000B3 +:109DB00000000000000000000000000000000000A3 +:109DC0000000000000000000000000000000000093 +:109DD0000000000000000000000000000000000083 +:109DE0000000000000000000000000000000000073 +:109DF0000000000000000000000000000000000063 +:109E00000000000000000000000000000000000052 +:109E10000000000000000000000000000000000042 +:109E20000000000000000000000000000000000032 +:109E30000000000000000000000000000000000022 +:109E40000000000000000000000000000000000012 +:109E50000000000000000000000000000000000002 +:109E600000000000000000000000000000000000F2 +:109E700000000000000000000000000000000000E2 +:109E800000000000000000000000000000000000D2 +:109E900000000000000000000000000000000000C2 +:109EA00000000000000000000000000000000000B2 +:109EB00000000000000000000000000000000000A2 +:109EC0000000000000000000000000000000000092 +:109ED0000000000000000000000000000000000082 +:109EE0000000000000000000000000000000000072 +:109EF0000000000000000000000000000000000062 +:109F00000000000000000000000000000000000051 +:109F10000000000000000000000000000000000041 +:109F20000000000000000000000000000000000031 +:109F30000000000000000000000000000000000021 +:109F40000000000000000000000000000000000011 +:109F50000000000000000000000000000000000001 +:109F600000000000000000000000000000000000F1 +:109F700000000000000000000000000000000000E1 +:109F800000000000000000000000000000000000D1 +:109F900000000000000000000000000000000000C1 +:109FA00000000000000000000000000000000000B1 +:109FB00000000000000000000000000000000000A1 +:109FC0000000000000000000000000000000000091 +:109FD0000000000000000000000000000000000081 +:109FE0000000000000000000000000000000000071 +:109FF0000000000000000000000000000000000061 +:10A000000000000000000000000000000000000050 +:10A010000000000000000000000000000000000040 +:10A020000000000000000000000000000000000030 +:10A030000000000000000000000000000000000020 +:10A040000000000000000000000000000000000010 +:10A050000000000000000000000000000000000000 +:10A0600000000000000000000000000000000000F0 +:10A0700000000000000000000000000000000000E0 +:10A0800000000000000000000000000000000000D0 +:10A0900000000000000000000000000000000000C0 +:10A0A00000000000000000000000000000000000B0 +:10A0B00000000000000000000000000000000000A0 +:10A0C0000000000000000000000000000000000090 +:10A0D0000000000000000000000000000000000080 +:10A0E0000000000000000000000000000000000070 +:10A0F0000000000000000000000000000000000060 +:10A10000000000000000000000000000000000004F +:10A11000000000000000000000000000000000003F +:10A12000000000000000000000000000000000002F +:10A13000000000000000000000000000000000001F +:10A14000000000000000000000000000000000000F +:10A1500000000000000000000000000000000000FF +:10A1600000000000000000000000000000000000EF +:10A1700000000000000000000000000000000000DF +:10A1800000000000000000000000000000000000CF +:10A1900000000000000000000000000000000000BF +:10A1A00000000000000000000000000000000000AF +:10A1B000000000000000000000000000000000009F +:10A1C000000000000000000000000000000000008F +:10A1D000000000000000000000000000000000007F +:10A1E000000000000000000000000000000000006F +:10A1F000000000000000000000000000000000005F +:10A20000000000000000000000000000000000004E +:10A21000000000000000000000000000000000003E +:10A22000000000000000000000000000000000002E +:10A23000000000000000000000000000000000001E +:10A24000000000000000000000000000000000000E +:10A2500000000000000000000000000000000000FE +:10A2600000000000000000000000000000000000EE +:10A2700000000000000000000000000000000000DE +:10A2800000000000000000000000000000000000CE +:10A2900000000000000000000000000000000000BE +:10A2A00000000000000000000000000000000000AE +:10A2B000000000000000000000000000000000009E +:10A2C000000000000000000000000000000000008E +:10A2D000000000000000000000000000000000007E +:10A2E000000000000000000000000000000000006E +:10A2F000000000000000000000000000000000005E +:10A30000000000000000000000000000000000004D +:10A31000000000000000000000000000000000003D +:10A32000000000000000000000000000000000002D +:10A33000000000000000000000000000000000001D +:10A34000000000000000000000000000000000000D +:10A3500000000000000000000000000000000000FD +:10A3600000000000000000000000000000000000ED +:10A3700000000000000000000000000000000000DD +:10A3800000000000000000000000000000000000CD +:10A3900000000000000000000000000000000000BD +:10A3A00000000000000000000000000000000000AD +:10A3B000000000000000000000000000000000009D +:10A3C000000000000000000000000000000000008D +:10A3D000000000000000000000000000000000007D +:10A3E000000000000000000000000000000000006D +:10A3F000000000000000000000000000000000005D +:10A40000000000000000000000000000000000004C +:10A41000000000000000000000000000000000003C +:10A42000000000000000000000000000000000002C +:10A43000000000000000000000000000000000001C +:10A44000000000000000000000000000000000000C +:10A4500000000000000000000000000000000000FC +:10A4600000000000000000000000000000000000EC +:10A4700000000000000000000000000000000000DC +:10A4800000000000000000000000000000000000CC +:10A4900000000000000000000000000000000000BC +:10A4A00000000000000000000000000000000000AC +:10A4B000000000000000000000000000000000009C +:10A4C000000000000000000000000000000000008C +:10A4D000000000000000000000000000000000007C +:10A4E000000000000000000000000000000000006C +:10A4F000000000000000000000000000000000005C +:10A50000000000000000000000000000000000004B +:10A51000000000000000000000000000000000003B +:10A52000000000000000000000000000000000002B +:10A53000000000000000000000000000000000001B +:10A54000000000000000000000000000000000000B +:10A5500000000000000000000000000000000000FB +:10A5600000000000000000000000000000000000EB +:10A5700000000000000000000000000000000000DB +:10A5800000000000000000000000000000000000CB +:10A5900000000000000000000000000000000000BB +:10A5A00000000000000000000000000000000000AB +:10A5B000000000000000000000000000000000009B +:10A5C000000000000000000000000000000000008B +:10A5D000000000000000000000000000000000007B +:10A5E000000000000000000000000000000000006B +:10A5F000000000000000000000000000000000005B +:10A60000000000000000000000000000000000004A +:10A61000000000000000000000000000000000003A +:10A62000000000000000000000000000000000002A +:10A63000000000000000000000000000000000001A +:10A64000000000000000000000000000000000000A +:10A6500000000000000000000000000000000000FA +:10A6600000000000000000000000000000000000EA +:10A6700000000000000000000000000000000000DA +:10A6800000000000000000000000000000000000CA +:10A6900000000000000000000000000000000000BA +:10A6A00000000000000000000000000000000000AA +:10A6B000000000000000000000000000000000009A +:10A6C000000000000000000000000000000000008A +:10A6D000000000000000000000000000000000007A +:10A6E000000000000000000000000000000000006A +:10A6F000000000000000000000000000000000005A +:10A700000000000000000000000000000000000049 +:10A710000000000000000000000000000000000039 +:10A720000000000000000000000000000000000029 +:10A730000000000000000000000000000000000019 +:10A740000000000000000000000000000000000009 +:10A7500000000000000000000000000000000000F9 +:10A7600000000000000000000000000000000000E9 +:10A7700000000000000000000000000000000000D9 +:10A7800000000000000000000000000000000000C9 +:10A7900000000000000000000000000000000000B9 +:10A7A00000000000000000000000000000000000A9 +:10A7B0000000000000000000000000000000000099 +:10A7C0000000000000000000000000000000000089 +:10A7D0000000000000000000000000000000000079 +:10A7E0000000000000000000000000000000000069 +:10A7F0000000000000000000000000000000000059 +:10A800000000000000000000000000000000000048 +:10A810000000000000000000000000000000000038 +:10A820000000000000000000000000000000000028 +:10A830000000000000000000000000000000000018 +:10A840000000000000000000000000000000000008 +:10A8500000000000000000000000000000000000F8 +:10A8600000000000000000000000000000000000E8 +:10A8700000000000000000000000000000000000D8 +:10A8800000000000000000000000000000000000C8 +:10A8900000000000000000000000000000000000B8 +:10A8A00000000000000000000000000000000000A8 +:10A8B0000000000000000000000000000000000098 +:10A8C0000000000000000000000000000000000088 +:10A8D0000000000000000000000000000000000078 +:10A8E0000000000000000000000000000000000068 +:10A8F0000000000000000000000000000000000058 +:10A900000000000000000000000000000000000047 +:10A910000000000000000000000000000000000037 +:10A920000000000000000000000000000000000027 +:10A930000000000000000000000000000000000017 +:10A940000000000000000000000000000000000007 +:10A9500000000000000000000000000000000000F7 +:10A9600000000000000000000000000000000000E7 +:10A9700000000000000000000000000000000000D7 +:10A9800000000000000000000000000000000000C7 +:10A9900000000000000000000000000000000000B7 +:10A9A00000000000000000000000000000000000A7 +:10A9B0000000000000000000000000000000000097 +:10A9C0000000000000000000000000000000000087 +:10A9D0000000000000000000000000000000000077 +:10A9E0000000000000000000000000000000000067 +:10A9F0000000000000000000000000000000000057 +:10AA00000000000000000000000000000000000046 +:10AA10000000000000000000000000000000000036 +:10AA20000000000000000000000000000000000026 +:10AA30000000000000000000000000000000000016 +:10AA40000000000000000000000000000000000006 +:10AA500000000000000000000000000000000000F6 +:10AA600000000000000000000000000000000000E6 +:10AA700000000000000000000000000000000000D6 +:10AA800000000000000000000000000000000000C6 +:10AA900000000000000000000000000000000000B6 +:10AAA00000000000000000000000000000000000A6 +:10AAB0000000000000000000000000000000000096 +:10AAC0000000000000000000000000000000000086 +:10AAD0000000000000000000000000000000000076 +:10AAE0000000000000000000000000000000000066 +:10AAF0000000000000000000000000000000000056 +:10AB00000000000000000000000000000000000045 +:10AB10000000000000000000000000000000000035 +:10AB20000000000000000000000000000000000025 +:10AB30000000000000000000000000000000000015 +:10AB40000000000000000000000000000000000005 +:10AB500000000000000000000000000000000000F5 +:10AB600000000000000000000000000000000000E5 +:10AB700000000000000000000000000000000000D5 +:10AB800000000000000000000000000000000000C5 +:10AB900000000000000000000000000000000000B5 +:10ABA00000000000000000000000000000000000A5 +:10ABB0000000000000000000000000000000000095 +:10ABC0000000000000000000000000000000000085 +:10ABD0000000000000000000000000000000000075 +:10ABE0000000000000000000000000000000000065 +:10ABF0000000000000000000000000000000000055 +:10AC00000000000000000000000000000000000044 +:10AC10000000000000000000000000000000000034 +:10AC20000000000000000000000000000000000024 +:10AC30000000000000000000000000000000000014 +:10AC40000000000000000000000000000000000004 +:10AC500000000000000000000000000000000000F4 +:10AC600000000000000000000000000000000000E4 +:10AC700000000000000000000000000000000000D4 +:10AC800000000000000000000000000000000000C4 +:10AC900000000000000000000000000000000000B4 +:10ACA00000000000000000000000000000000000A4 +:10ACB0000000000000000000000000000000000094 +:10ACC0000000000000000000000000000000000084 +:10ACD0000000000000000000000000000000000074 +:10ACE0000000000000000000000000000000000064 +:10ACF0000000000000000000000000000000000054 +:10AD00000000000000000000000000000000000043 +:10AD10000000000000000000000000000000000033 +:10AD20000000000000000000000000000000000023 +:10AD30000000000000000000000000000000000013 +:10AD40000000000000000000000000000000000003 +:10AD500000000000000000000000000000000000F3 +:10AD600000000000000000000000000000000000E3 +:10AD700000000000000000000000000000000000D3 +:10AD800000000000000000000000000000000000C3 +:10AD900000000000000000000000000000000000B3 +:10ADA00000000000000000000000000000000000A3 +:10ADB0000000000000000000000000000000000093 +:10ADC0000000000000000000000000000000000083 +:10ADD0000000000000000000000000000000000073 +:10ADE0000000000000000000000000000000000063 +:10ADF0000000000000000000000000000000000053 +:10AE00000000000000000000000000000000000042 +:10AE10000000000000000000000000000000000032 +:10AE20000000000000000000000000000000000022 +:10AE30000000000000000000000000000000000012 +:10AE40000000000000000000000000000000000002 +:10AE500000000000000000000000000000000000F2 +:10AE600000000000000000000000000000000000E2 +:10AE700000000000000000000000000000000000D2 +:10AE800000000000000000000000000000000000C2 +:10AE900000000000000000000000000000000000B2 +:10AEA00000000000000000000000000000000000A2 +:10AEB0000000000000000000000000000000000092 +:10AEC0000000000000000000000000000000000082 +:10AED0000000000000000000000000000000000072 +:10AEE0000000000000000000000000000000000062 +:10AEF0000000000000000000000000000000000052 +:10AF00000000000000000000000000000000000041 +:10AF10000000000000000000000000000000000031 +:10AF20000000000000000000000000000000000021 +:10AF30000000000000000000000000000000000011 +:10AF40000000000000000000000000000000000001 +:10AF500000000000000000000000000000000000F1 +:10AF600000000000000000000000000000000000E1 +:10AF700000000000000000000000000000000000D1 +:10AF800000000000000000000000000000000000C1 +:10AF900000000000000000000000000000000000B1 +:10AFA00000000000000000000000000000000000A1 +:10AFB0000000000000000000000000000000000091 +:10AFC0000000000000000000000000000000000081 +:10AFD0000000000000000000000000000000000071 +:10AFE0000000000000000000000000000000000061 +:10AFF0000000000000000000000000000000000051 +:10B000000000000000000000000000000000000040 +:10B010000000000000000000000000000000000030 +:10B020000000000000000000000000000000000020 +:10B030000000000000000000000000000000000010 +:10B040000000000000000000000000000000000000 +:10B0500000000000000000000000000000000000F0 +:10B0600000000000000000000000000000000000E0 +:10B0700000000000000000000000000000000000D0 +:10B0800000000000000000000000000000000000C0 +:10B0900000000000000000000000000000000000B0 +:10B0A00000000000000000000000000000000000A0 +:10B0B0000000000000000000000000000000000090 +:10B0C0000000000000000000000000000000000080 +:10B0D0000000000000000000000000000000000070 +:10B0E0000000000000000000000000000000000060 +:10B0F0000000000000000000000000000000000050 +:10B10000000000000000000000000000000000003F +:10B11000000000000000000000000000000000002F +:10B12000000000000000000000000000000000001F +:10B13000000000000000000000000000000000000F +:10B1400000000000000000000000000000000000FF +:10B1500000000000000000000000000000000000EF +:10B1600000000000000000000000000000000000DF +:10B1700000000000000000000000000000000000CF +:10B1800000000000000000000000000000000000BF +:10B1900000000000000000000000000000000000AF +:10B1A000000000000000000000000000000000009F +:10B1B000000000000000000000000000000000008F +:10B1C000000000000000000000000000000000007F +:10B1D000000000000000000000000000000000006F +:10B1E000000000000000000000000000000000005F +:10B1F000000000000000000000000000000000004F +:10B20000000000000000000000000000000000003E +:10B21000000000000000000000000000000000002E +:10B22000000000000000000000000000000000001E +:10B23000000000000000000000000000000000000E +:10B2400000000000000000000000000000000000FE +:10B2500000000000000000000000000000000000EE +:10B2600000000000000000000000000000000000DE +:10B2700000000000000000000000000000000000CE +:10B2800000000000000000000000000000000000BE +:10B2900000000000000000000000000000000000AE +:10B2A000000000000000000000000000000000009E +:10B2B000000000000000000000000000000000008E +:10B2C000000000000000000000000000000000007E +:10B2D000000000000000000000000000000000006E +:10B2E000000000000000000000000000000000005E +:10B2F000000000000000000000000000000000004E +:10B30000000000000000000000000000000000003D +:10B31000000000000000000000000000000000002D +:10B32000000000000000000000000000000000001D +:10B33000000000000000000000000000000000000D +:10B3400000000000000000000000000000000000FD +:10B3500000000000000000000000000000000000ED +:10B3600000000000000000000000000000000000DD +:10B3700000000000000000000000000000000000CD +:10B3800000000000000000000000000000000000BD +:10B3900000000000000000000000000000000000AD +:10B3A000000000000000000000000000000000009D +:10B3B000000000000000000000000000000000008D +:10B3C000000000000000000000000000000000007D +:10B3D000000000000000000000000000000000006D +:10B3E000000000000000000000000000000000005D +:10B3F000000000000000000000000000000000004D +:10B40000000000000000000000000000000000003C +:10B41000000000000000000000000000000000002C +:10B42000000000000000000000000000000000001C +:10B43000000000000000000000000000000000000C +:10B4400000000000000000000000000000000000FC +:10B4500000000000000000000000000000000000EC +:10B4600000000000000000000000000000000000DC +:10B4700000000000000000000000000000000000CC +:10B4800000000000000000000000000000000000BC +:10B4900000000000000000000000000000000000AC +:10B4A000000000000000000000000000000000009C +:10B4B000000000000000000000000000000000008C +:10B4C000000000000000000000000000000000007C +:10B4D000000000000000000000000000000000006C +:10B4E000000000000000000000000000000000005C +:10B4F000000000000000000000000000000000004C +:10B50000000000000000000000000000000000003B +:10B51000000000000000000000000000000000002B +:10B52000000000000000000000000000000000001B +:10B53000000000000000000000000000000000000B +:10B5400000000000000000000000000000000000FB +:10B5500000000000000000000000000000000000EB +:10B5600000000000000000000000000000000000DB +:10B5700000000000000000000000000000000000CB +:10B5800000000000000000000000000000000000BB +:10B5900000000000000000000000000000000000AB +:10B5A000000000000000000000000000000000009B +:10B5B000000000000000000000000000000000008B +:10B5C000000000000000000000000000000000007B +:10B5D000000000000000000000000000000000006B +:10B5E000000000000000000000000000000000005B +:10B5F000000000000000000000000000000000004B +:10B60000000000000000000000000000000000003A +:10B61000000000000000000000000000000000002A +:10B62000000000000000000000000000000000001A +:10B63000000000000000000000000000000000000A +:10B6400000000000000000000000000000000000FA +:10B6500000000000000000000000000000000000EA +:10B6600000000000000000000000000000000000DA +:10B6700000000000000000000000000000000000CA +:10B6800000000000000000000000000000000000BA +:10B6900000000000000000000000000000000000AA +:10B6A000000000000000000000000000000000009A +:10B6B000000000000000000000000000000000008A +:10B6C000000000000000000000000000000000007A +:10B6D000000000000000000000000000000000006A +:10B6E000000000000000000000000000000000005A +:10B6F000000000000000000000000000000000004A +:10B700000000000000000000000000000000000039 +:10B710000000000000000000000000000000000029 +:10B720000000000000000000000000000000000019 +:10B730000000000000000000000000000000000009 +:10B7400000000000000000000000000000000000F9 +:10B7500000000000000000000000000000000000E9 +:10B7600000000000000000000000000000000000D9 +:10B7700000000000000000000000000000000000C9 +:10B7800000000000000000000000000000000000B9 +:10B7900000000000000000000000000000000000A9 +:10B7A0000000000000000000000000000000000099 +:10B7B0000000000000000000000000000000000089 +:10B7C0000000000000000000000000000000000079 +:10B7D0000000000000000000000000000000000069 +:10B7E0000000000000000000000000000000000059 +:10B7F0000000000000000000000000000000000049 +:10B800000000000000000000000000000000000038 +:10B810000000000000000000000000000000000028 +:10B820000000000000000000000000000000000018 +:10B830000000000000000000000000000000000008 +:10B8400000000000000000000000000000000000F8 +:10B8500000000000000000000000000000000000E8 +:10B8600000000000000000000000000000000000D8 +:10B8700000000000000000000000000000000000C8 +:10B8800000000000000000000000000000000000B8 +:10B8900000000000000000000000000000000000A8 +:10B8A0000000000000000000000000000000000098 +:10B8B0000000000000000000000000000000000088 +:10B8C0000000000000000000000000000000000078 +:10B8D0000000000000000000000000000000000068 +:10B8E0000000000000000000000000000000000058 +:10B8F0000000000000000000000000000000000048 +:10B900000000000000000000000000000000000037 +:10B910000000000000000000000000000000000027 +:10B920000000000000000000000000000000000017 +:10B930000000000000000000000000000000000007 +:10B9400000000000000000000000000000000000F7 +:10B9500000000000000000000000000000000000E7 +:10B9600000000000000000000000000000000000D7 +:10B9700000000000000000000000000000000000C7 +:10B9800000000000000000000000000000000000B7 +:10B9900000000000000000000000000000000000A7 +:10B9A0000000000000000000000000000000000097 +:10B9B0000000000000000000000000000000000087 +:10B9C0000000000000000000000000000000000077 +:10B9D0000000000000000000000000000000000067 +:10B9E0000000000000000000000000000000000057 +:10B9F0000000000000000000000000000000000047 +:10BA00000000000000000000000000000000000036 +:10BA10000000000000000000000000000000000026 +:10BA20000000000000000000000000000000000016 +:10BA30000000000000000000000000000000000006 +:10BA400000000000000000000000000000000000F6 +:10BA500000000000000000000000000000000000E6 +:10BA600000000000000000000000000000000000D6 +:10BA700000000000000000000000000000000000C6 +:10BA800000000000000000000000000000000000B6 +:10BA900000000000000000000000000000000000A6 +:10BAA0000000000000000000000000000000000096 +:10BAB0000000000000000000000000000000000086 +:10BAC0000000000000000000000000000000000076 +:10BAD0000000000000000000000000000000000066 +:10BAE0000000000000000000000000000000000056 +:10BAF0000000000000000000000000000000000046 +:10BB00000000000000000000000000000000000035 +:10BB10000000000000000000000000000000000025 +:10BB20000000000000000000000000000000000015 +:10BB30000000000000000000000000000000000005 +:10BB400000000000000000000000000000000000F5 +:10BB500000000000000000000000000000000000E5 +:10BB600000000000000000000000000000000000D5 +:10BB700000000000000000000000000000000000C5 +:10BB800000000000000000000000000000000000B5 +:10BB900000000000000000000000000000000000A5 +:10BBA0000000000000000000000000000000000095 +:10BBB0000000000000000000000000000000000085 +:10BBC0000000000000000000000000000000000075 +:10BBD0000000000000000000000000000000000065 +:10BBE0000000000000000000000000000000000055 +:10BBF0000000000000000000000000000000000045 +:10BC00000000000000000000000000000000000034 +:10BC10000000000000000000000000000000000024 +:10BC20000000000000000000000000000000000014 +:10BC30000000000000000000000000000000000004 +:10BC400000000000000000000000000000000000F4 +:10BC500000000000000000000000000000000000E4 +:10BC600000000000000000000000000000000000D4 +:10BC700000000000000000000000000000000000C4 +:10BC800000000000000000000000000000000000B4 +:10BC900000000000000000000000000000000000A4 +:10BCA0000000000000000000000000000000000094 +:10BCB0000000000000000000000000000000000084 +:10BCC0000000000000000000000000000000000074 +:10BCD0000000000000000000000000000000000064 +:10BCE0000000000000000000000000000000000054 +:10BCF0000000000000000000000000000000000044 +:10BD00000000000000000000000000000000000033 +:10BD10000000000000000000000000000000000023 +:10BD20000000000000000000000000000000000013 +:10BD30000000000000000000000000000000000003 +:10BD400000000000000000000000000000000000F3 +:10BD500000000000000000000000000000000000E3 +:10BD600000000000000000000000000000000000D3 +:10BD700000000000000000000000000000000000C3 +:10BD800000000000000000000000000000000000B3 +:10BD900000000000000000000000000000000000A3 +:10BDA0000000000000000000000000000000000093 +:10BDB0000000000000000000000000000000000083 +:10BDC0000000000000000000000000000000000073 +:10BDD0000000000000000000000000000000000063 +:10BDE0000000000000000000000000000000000053 +:10BDF0000000000000000000000000000000000043 +:10BE00000000000000000000000000000000000032 +:10BE10000000000000000000000000000000000022 +:10BE20000000000000000000000000000000000012 +:10BE30000000000000000000000000000000000002 +:10BE400000000000000000000000000000000000F2 +:10BE500000000000000000000000000000000000E2 +:10BE600000000000000000000000000000000000D2 +:10BE700000000000000000000000000000000000C2 +:10BE800000000000000000000000000000000000B2 +:10BE900000000000000000000000000000000000A2 +:10BEA0000000000000000000000000000000000092 +:10BEB0000000000000000000000000000000000082 +:10BEC0000000000000000000000000000000000072 +:10BED0000000000000000000000000000000000062 +:10BEE0000000000000000000000000000000000052 +:10BEF0000000000000000000000000000000000042 +:10BF00000000000000000000000000000000000031 +:10BF10000000000000000000000000000000000021 +:10BF20000000000000000000000000000000000011 +:10BF30000000000000000000000000000000000001 +:10BF400000000000000000000000000000000000F1 +:10BF500000000000000000000000000000000000E1 +:10BF600000000000000000000000000000000000D1 +:10BF700000000000000000000000000000000000C1 +:10BF800000000000000000000000000000000000B1 +:10BF900000000000000000000000000000000000A1 +:10BFA0000000000000000000000000000000000091 +:10BFB0000000000000000000000000000000000081 +:10BFC0000000000000000000000000000000000071 +:10BFD0000000000000000000000000000000000061 +:10BFE0000000000000000000000000000000000051 +:10BFF0000000000000000000000000000000000041 +:10C000000000000000000000000000000000000030 +:10C010000000000000000000000000000000000020 +:10C020000000000000000000000000000000000010 +:10C030000000000000000000000000000000000000 +:10C0400000000000000000000000000000000000F0 +:10C0500000000000000000000000000000000000E0 +:10C0600000000000000000000000000000000000D0 +:10C0700000000000000000000000000000000000C0 +:10C0800000000000000000000000000000000000B0 +:10C0900000000000000000000000000000000000A0 +:10C0A0000000000000000000000000000000000090 +:10C0B0000000000000000000000000000000000080 +:10C0C0000000000000000000000000000000000070 +:10C0D0000000000000000000000000000000000060 +:10C0E0000000000000000000000000000000000050 +:10C0F0000000000000000000000000000000000040 +:10C10000000000000000000000000000000000002F +:10C11000000000000000000000000000000000001F +:10C12000000000000000000000000000000000000F +:10C1300000000000000000000000000000000000FF +:10C1400000000000000000000000000000000000EF +:10C1500000000000000000000000000000000000DF +:10C1600000000000000000000000000000000000CF +:10C1700000000000000000000000000000000000BF +:10C1800000000000000000000000000000000000AF +:10C19000000000000000000000000000000000009F +:10C1A000000000000000000000000000000000008F +:10C1B000000000000000000000000000000000007F +:10C1C000000000000000000000000000000000006F +:10C1D000000000000000000000000000000000005F +:10C1E000000000000000000000000000000000004F +:10C1F000000000000000000000000000000000003F +:10C20000000000000000000000000000000000002E +:10C21000000000000000000000000000000000001E +:10C22000000000000000000000000000000000000E +:10C2300000000000000000000000000000000000FE +:10C2400000000000000000000000000000000000EE +:10C2500000000000000000000000000000000000DE +:10C2600000000000000000000000000000000000CE +:10C2700000000000000000000000000000000000BE +:10C2800000000000000000000000000000000000AE +:10C29000000000000000000000000000000000009E +:10C2A000000000000000000000000000000000008E +:10C2B000000000000000000000000000000000007E +:10C2C000000000000000000000000000000000006E +:10C2D000000000000000000000000000000000005E +:10C2E000000000000000000000000000000000004E +:10C2F000000000000000000000000000000000003E +:10C30000000000000000000000000000000000002D +:10C31000000000000000000000000000000000001D +:10C32000000000000000000000000000000000000D +:10C3300000000000000000000000000000000000FD +:10C3400000000000000000000000000000000000ED +:10C3500000000000000000000000000000000000DD +:10C3600000000000000000000000000000000000CD +:10C3700000000000000000000000000000000000BD +:10C3800000000000000000000000000000000000AD +:10C39000000000000000000000000000000000009D +:10C3A000000000000000000000000000000000008D +:10C3B000000000000000000000000000000000007D +:10C3C000000000000000000000000000000000006D +:10C3D000000000000000000000000000000000005D +:10C3E000000000000000000000000000000000004D +:10C3F000000000000000000000000000000000003D +:10C40000000000000000000000000000000000002C +:10C41000000000000000000000000000000000001C +:10C42000000000000000000000000000000000000C +:10C4300000000000000000000000000000000000FC +:10C4400000000000000000000000000000000000EC +:10C4500000000000000000000000000000000000DC +:10C4600000000000000000000000000000000000CC +:10C4700000000000000000000000000000000000BC +:10C4800000000000000000000000000000000000AC +:10C49000000000000000000000000000000000009C +:10C4A000000000000000000000000000000000008C +:10C4B000000000000000000000000000000000007C +:10C4C000000000000000000000000000000000006C +:10C4D000000000000000000000000000000000005C +:10C4E000000000000000000000000000000000004C +:10C4F000000000000000000000000000000000003C +:10C50000000000000000000000000000000000002B +:10C51000000000000000000000000000000000001B +:10C52000000000000000000000000000000000000B +:10C5300000000000000000000000000000000000FB +:10C5400000000000000000000000000000000000EB +:10C5500000000000000000000000000000000000DB +:10C5600000000000000000000000000000000000CB +:10C5700000000000000000000000000000000000BB +:10C5800000000000000000000000000000000000AB +:10C59000000000000000000000000000000000009B +:10C5A000000000000000000000000000000000008B +:10C5B000000000000000000000000000000000007B +:10C5C000000000000000000000000000000000006B +:10C5D000000000000000000000000000000000005B +:10C5E000000000000000000000000000000000004B +:10C5F000000000000000000000000000000000003B +:10C60000000000000000000000000000000000002A +:10C61000000000000000000000000000000000001A +:10C62000000000000000000000000000000000000A +:10C6300000000000000000000000000000000000FA +:10C6400000000000000000000000000000000000EA +:10C6500000000000000000000000000000000000DA +:10C6600000000000000000000000000000000000CA +:10C6700000000000000000000000000000000000BA +:10C6800000000000000000000000000000000000AA +:10C69000000000000000000000000000000000009A +:10C6A000000000000000000000000000000000008A +:10C6B000000000000000000000000000000000007A +:10C6C000000000000000000000000000000000006A +:10C6D000000000000000000000000000000000005A +:10C6E000000000000000000000000000000000004A +:10C6F000000000000000000000000000000000003A +:10C700000000000000000000000000000000000029 +:10C710000000000000000000000000000000000019 +:10C720000000000000000000000000000000000009 +:10C7300000000000000000000000000000000000F9 +:10C7400000000000000000000000000000000000E9 +:10C7500000000000000000000000000000000000D9 +:10C7600000000000000000000000000000000000C9 +:10C7700000000000000000000000000000000000B9 +:10C7800000000000000000000000000000000000A9 +:10C790000000000000000000000000000000000099 +:10C7A0000000000000000000000000000000000089 +:10C7B0000000000000000000000000000000000079 +:10C7C0000000000000000000000000000000000069 +:10C7D0000000000000000000000000000000000059 +:10C7E0000000000000000000000000000000000049 +:10C7F0000000000000000000000000000000000039 +:10C800000000000000000000000000000000000028 +:10C810000000000000000000000000000000000018 +:10C820000000000000000000000000000000000008 +:10C8300000000000000000000000000000000000F8 +:10C8400000000000000000000000000000000000E8 +:10C8500000000000000000000000000000000000D8 +:10C8600000000000000000000000000000000000C8 +:10C8700000000000000000000000000000000000B8 +:10C8800000000000000000000000000000000000A8 +:10C890000000000000000000000000000000000098 +:10C8A0000000000000000000000000000000000088 +:10C8B0000000000000000000000000000000000078 +:10C8C0000000000000000000000000000000000068 +:10C8D0000000000000000000000000000000000058 +:10C8E0000000000000000000000000000000000048 +:10C8F0000000000000000000000000000000000038 +:10C900000000000000000000000000000000000027 +:10C910000000000000000000000000000000000017 +:10C920000000000000000000000000000000000007 +:10C9300000000000000000000000000000000000F7 +:10C9400000000000000000000000000000000000E7 +:10C9500000000000000000000000000000000000D7 +:10C9600000000000000000000000000000000000C7 +:10C9700000000000000000000000000000000000B7 +:10C9800000000000000000000000000000000000A7 +:10C990000000000000000000000000000000000097 +:10C9A0000000000000000000000000000000000087 +:10C9B0000000000000000000000000000000000077 +:10C9C0000000000000000000000000000000000067 +:10C9D0000000000000000000000000000000000057 +:10C9E0000000000000000000000000000000000047 +:10C9F0000000000000000000000000000000000037 +:10CA00000000000000000000000000000000000026 +:10CA10000000000000000000000000000000000016 +:10CA20000000000000000000000000000000000006 +:10CA300000000000000000000000000000000000F6 +:10CA400000000000000000000000000000000000E6 +:10CA500000000000000000000000000000000000D6 +:10CA600000000000000000000000000000000000C6 +:10CA700000000000000000000000000000000000B6 +:10CA800000000000000000000000000000000000A6 +:10CA90000000000000000000000000000000000096 +:10CAA0000000000000000000000000000000000086 +:10CAB0000000000000000000000000000000000076 +:10CAC0000000000000000000000000000000000066 +:10CAD0000000000000000000000000000000000056 +:10CAE0000000000000000000000000000000000046 +:10CAF0000000000000000000000000000000000036 +:10CB00000000000000000000000000000000000025 +:10CB10000000000000000000000000000000000015 +:10CB20000000000000000000000000000000000005 +:10CB300000000000000000000000000000000000F5 +:10CB400000000000000000000000000000000000E5 +:10CB500000000000000000000000000000000000D5 +:10CB600000000000000000000000000000000000C5 +:10CB700000000000000000000000000000000000B5 +:10CB800000000000000000000000000000000000A5 +:10CB90000000000000000000000000000000000095 +:10CBA0000000000000000000000000000000000085 +:10CBB0000000000000000000000000000000000075 +:10CBC0000000000000000000000000000000000065 +:10CBD0000000000000000000000000000000000055 +:10CBE0000000000000000000000000000000000045 +:10CBF0000000000000000000000000000000000035 +:10CC00000000000000000000000000000000000024 +:10CC10000000000000000000000000000000000014 +:10CC20000000000000000000000000000000000004 +:10CC300000000000000000000000000000000000F4 +:10CC400000000000000000000000000000000000E4 +:10CC500000000000000000000000000000000000D4 +:10CC600000000000000000000000000000000000C4 +:10CC700000000000000000000000000000000000B4 +:10CC800000000000000000000000000000000000A4 +:10CC90000000000000000000000000000000000094 +:10CCA0000000000000000000000000000000000084 +:10CCB0000000000000000000000000000000000074 +:10CCC0000000000000000000000000000000000064 +:10CCD0000000000000000000000000000000000054 +:10CCE0000000000000000000000000000000000044 +:10CCF0000000000000000000000000000000000034 +:10CD00000000000000000000000000000000000023 +:10CD10000000000000000000000000000000000013 +:10CD20000000000000000000000000000000000003 +:10CD300000000000000000000000000000000000F3 +:10CD400000000000000000000000000000000000E3 +:10CD500000000000000000000000000000000000D3 +:10CD600000000000000000000000000000000000C3 +:10CD700000000000000000000000000000000000B3 +:10CD800000000000000000000000000000000000A3 +:10CD90000000000000000000000000000000000093 +:10CDA0000000000000000000000000000000000083 +:10CDB0000000000000000000000000000000000073 +:10CDC0000000000000000000000000000000000063 +:10CDD0000000000000000000000000000000000053 +:10CDE0000000000000000000000000000000000043 +:10CDF0000000000000000000000000000000000033 +:10CE00000000000000000000000000000000000022 +:10CE10000000000000000000000000000000000012 +:10CE20000000000000000000000000000000000002 +:10CE300000000000000000000000000000000000F2 +:10CE400000000000000000000000000000000000E2 +:10CE500000000000000000000000000000000000D2 +:10CE600000000000000000000000000000000000C2 +:10CE700000000000000000000000000000000000B2 +:10CE800000000000000000000000000000000000A2 +:10CE90000000000000000000000000000000000092 +:10CEA0000000000000000000000000000000000082 +:10CEB0000000000000000000000000000000000072 +:10CEC0000000000000000000000000000000000062 +:10CED0000000000000000000000000000000000052 +:10CEE0000000000000000000000000000000000042 +:10CEF0000000000000000000000000000000000032 +:10CF00000000000000000000000000000000000021 +:10CF10000000000000000000000000000000000011 +:10CF20000000000000000000000000000000000001 +:10CF300000000000000000000000000000000000F1 +:10CF400000000000000000000000000000000000E1 +:10CF500000000000000000000000000000000000D1 +:10CF600000000000000000000000000000000000C1 +:10CF700000000000000000000000000000000000B1 +:10CF800000000000000000000000000000000000A1 +:10CF90000000000000000000000000000000000091 +:10CFA0000000000000000000000000000000000081 +:10CFB0000000000000000000000000000000000071 +:10CFC0000000000000000000000000000000000061 +:10CFD0000000000000000000000000000000000051 +:10CFE0000000000000000000000000000000000041 +:10CFF0000000000000000000000000000000000031 +:10D000000000000000000000000000000000000020 +:10D010000000000000000000000000000000000010 +:10D020000000000000000000000000000000000000 +:10D0300000000000000000000000000000000000F0 +:10D0400000000000000000000000000000000000E0 +:10D0500000000000000000000000000000000000D0 +:10D0600000000000000000000000000000000000C0 +:10D0700000000000000000000000000000000000B0 +:10D0800000000000000000000000000000000000A0 +:10D090000000000000000000000000000000000090 +:10D0A0000000000000000000000000000000000080 +:10D0B0000000000000000000000000000000000070 +:10D0C0000000000000000000000000000000000060 +:10D0D0000000000000000000000000000000000050 +:10D0E0000000000000000000000000000000000040 +:10D0F0000000000000000000000000000000000030 +:10D10000000000000000000000000000000000001F +:10D11000000000000000000000000000000000000F +:10D1200000000000000000000000000000000000FF +:10D1300000000000000000000000000000000000EF +:10D1400000000000000000000000000000000000DF +:10D1500000000000000000000000000000000000CF +:10D1600000000000000000000000000000000000BF +:10D1700000000000000000000000000000000000AF +:10D18000000000000000000000000000000000009F +:10D19000000000000000000000000000000000008F +:10D1A000000000000000000000000000000000007F +:10D1B000000000000000000000000000000000006F +:10D1C000000000000000000000000000000000005F +:10D1D000000000000000000000000000000000004F +:10D1E000000000000000000000000000000000003F +:10D1F000000000000000000000000000000000002F +:10D20000000000000000000000000000000000001E +:10D21000000000000000000000000000000000000E +:10D2200000000000000000000000000000000000FE +:10D2300000000000000000000000000000000000EE +:10D2400000000000000000000000000000000000DE +:10D2500000000000000000000000000000000000CE +:10D2600000000000000000000000000000000000BE +:10D2700000000000000000000000000000000000AE +:10D28000000000000000000000000000000000009E +:10D29000000000000000000000000000000000008E +:10D2A000000000000000000000000000000000007E +:10D2B000000000000000000000000000000000006E +:10D2C000000000000000000000000000000000005E +:10D2D000000000000000000000000000000000004E +:10D2E000000000000000000000000000000000003E +:10D2F000000000000000000000000000000000002E +:10D30000000000000000000000000000000000001D +:10D31000000000000000000000000000000000000D +:10D3200000000000000000000000000000000000FD +:10D3300000000000000000000000000000000000ED +:10D3400000000000000000000000000000000000DD +:10D3500000000000000000000000000000000000CD +:10D3600000000000000000000000000000000000BD +:10D3700000000000000000000000000000000000AD +:10D38000000000000000000000000000000000009D +:10D39000000000000000000000000000000000008D +:10D3A000000000000000000000000000000000007D +:10D3B000000000000000000000000000000000006D +:10D3C000000000000000000000000000000000005D +:10D3D000000000000000000000000000000000004D +:10D3E000000000000000000000000000000000003D +:10D3F000000000000000000000000000000000002D +:10D40000000000000000000000000000000000001C +:10D41000000000000000000000000000000000000C +:10D4200000000000000000000000000000000000FC +:10D4300000000000000000000000000000000000EC +:10D4400000000000000000000000000000000000DC +:10D4500000000000000000000000000000000000CC +:10D4600000000000000000000000000000000000BC +:10D4700000000000000000000000000000000000AC +:10D48000000000000000000000000000000000009C +:10D49000000000000000000000000000000000008C +:10D4A000000000000000000000000000000000007C +:10D4B000000000000000000000000000000000006C +:10D4C000000000000000000000000000000000005C +:10D4D000000000000000000000000000000000004C +:10D4E000000000000000000000000000000000003C +:10D4F000000000000000000000000000000000002C +:10D50000000000000000000000000000000000001B +:10D51000000000000000000000000000000000000B +:10D5200000000000000000000000000000000000FB +:10D5300000000000000000000000000000000000EB +:10D5400000000000000000000000000000000000DB +:10D5500000000000000000000000000000000000CB +:10D5600000000000000000000000000000000000BB +:10D5700000000000000000000000000000000000AB +:10D58000000000000000000000000000000000009B +:10D59000000000000000000000000000000000008B +:10D5A000000000000000000000000000000000007B +:10D5B000000000000000000000000000000000006B +:10D5C000000000000000000000000000000000005B +:10D5D000000000000000000000000000000000004B +:10D5E000000000000000000000000000000000003B +:10D5F000000000000000000000000000000000002B +:10D60000000000000000000000000000000000001A +:10D61000000000000000000000000000000000000A +:10D6200000000000000000000000000000000000FA +:10D6300000000000000000000000000000000000EA +:10D6400000000000000000000000000000000000DA +:10D6500000000000000000000000000000000000CA +:10D6600000000000000000000000000000000000BA +:10D6700000000000000000000000000000000000AA +:10D68000000000000000000000000000000000009A +:10D69000000000000000000000000000000000008A +:10D6A000000000000000000000000000000000007A +:10D6B000000000000000000000000000000000006A +:10D6C000000000000000000000000000000000005A +:10D6D000000000000000000000000000000000004A +:10D6E000000000000000000000000000000000003A +:10D6F000000000000000000000000000000000002A +:10D700000000000000000000000000000000000019 +:10D710000000000000000000000000000000000009 +:10D7200000000000000000000000000000000000F9 +:10D7300000000000000000000000000000000000E9 +:10D7400000000000000000000000000000000000D9 +:10D7500000000000000000000000000000000000C9 +:10D7600000000000000000000000000000000000B9 +:10D7700000000000000000000000000000000000A9 +:10D780000000000000000000000000000000000099 +:10D790000000000000000000000000000000000089 +:10D7A0000000000000000000000000000000000079 +:10D7B0000000000000000000000000000000000069 +:10D7C0000000000000000000000000000000000059 +:10D7D0000000000000000000000000000000000049 +:10D7E0000000000000000000000000000000000039 +:10D7F0000000000000000000000000000000000029 +:10D800000000000000000000000000000000000018 +:10D810000000000000000000000000000000000008 +:10D8200000000000000000000000000000000000F8 +:10D8300000000000000000000000000000000000E8 +:10D8400000000000000000000000000000000000D8 +:10D8500000000000000000000000000000000000C8 +:10D8600000000000000000000000000000000000B8 +:10D8700000000000000000000000000000000000A8 +:10D880000000000000000000000000000000000098 +:10D890000000000000000000000000000000000088 +:10D8A0000000000000000000000000000000000078 +:10D8B0000000000000000000000000000000000068 +:10D8C0000000000000000000000000000000000058 +:10D8D0000000000000000000000000000000000048 +:10D8E0000000000000000000000000000000000038 +:10D8F0000000000000000000000000000000000028 +:10D900000000000000000000000000000000000017 +:10D910000000000000000000000000000000000007 +:10D9200000000000000000000000000000000000F7 +:10D9300000000000000000000000000000000000E7 +:10D9400000000000000000000000000000000000D7 +:10D9500000000000000000000000000000000000C7 +:10D9600000000000000000000000000000000000B7 +:10D9700000000000000000000000000000000000A7 +:10D980000000000000000000000000000000000097 +:10D990000000000000000000000000000000000087 +:10D9A0000000000000000000000000000000000077 +:10D9B0000000000000000000000000000000000067 +:10D9C0000000000000000000000000000000000057 +:10D9D0000000000000000000000000000000000047 +:10D9E0000000000000000000000000000000000037 +:10D9F0000000000000000000000000000000000027 +:10DA00000000000000000000000000000000000016 +:10DA10000000000000000000000000000000000006 +:10DA200000000000000000000000000000000000F6 +:10DA300000000000000000000000000000000000E6 +:10DA400000000000000000000000000000000000D6 +:10DA500000000000000000000000000000000000C6 +:10DA600000000000000000000000000000000000B6 +:10DA700000000000000000000000000000000000A6 +:10DA80000000000000000000000000000000000096 +:10DA90000000000000000000000000000000000086 +:10DAA0000000000000000000000000000000000076 +:10DAB0000000000000000000000000000000000066 +:10DAC0000000000000000000000000000000000056 +:10DAD0000000000000000000000000000000000046 +:10DAE0000000000000000000000000000000000036 +:10DAF0000000000000000000000000000000000026 +:10DB00000000000000000000000000000000000015 +:10DB10000000000000000000000000000000000005 +:10DB200000000000000000000000000000000000F5 +:10DB300000000000000000000000000000000000E5 +:10DB400000000000000000000000000000000000D5 +:10DB500000000000000000000000000000000000C5 +:10DB600000000000000000000000000000000000B5 +:10DB700000000000000000000000000000000000A5 +:10DB80000000000000000000000000000000000095 +:10DB90000000000000000000000000000000000085 +:10DBA0000000000000000000000000000000000075 +:10DBB0000000000000000000000000000000000065 +:10DBC0000000000000000000000000000000000055 +:10DBD0000000000000000000000000000000000045 +:10DBE0000000000000000000000000000000000035 +:10DBF0000000000000000000000000000000000025 +:10DC00000000000000000000000000000000000014 +:10DC10000000000000000000000000000000000004 +:10DC200000000000000000000000000000000000F4 +:10DC300000000000000000000000000000000000E4 +:10DC400000000000000000000000000000000000D4 +:10DC500000000000000000000000000000000000C4 +:10DC600000000000000000000000000000000000B4 +:10DC700000000000000000000000000000000000A4 +:10DC80000000000000000000000000000000000094 +:10DC90000000000000000000000000000000000084 +:10DCA0000000000000000000000000000000000074 +:10DCB0000000000000000000000000000000000064 +:10DCC0000000000000000000000000000000000054 +:10DCD0000000000000000000000000000000000044 +:10DCE0000000000000000000000000000000000034 +:10DCF0000000000000000000000000000000000024 +:10DD00000000000000000000000000000000000013 +:10DD10000000000000000000000000000000000003 +:10DD200000000000000000000000000000000000F3 +:10DD300000000000000000000000000000000000E3 +:10DD400000000000000000000000000000000000D3 +:10DD500000000000000000000000000000000000C3 +:10DD600000000000000000000000000000000000B3 +:10DD700000000000000000000000000000000000A3 +:10DD80000000000000000000000000000000000093 +:10DD90000000000000000000000000000000000083 +:10DDA0000000000000000000000000000000000073 +:10DDB0000000000000000000000000000000000063 +:10DDC0000000000000000000000000000000000053 +:10DDD0000000000000000000000000000000000043 +:10DDE0000000000000000000000000000000000033 +:10DDF0000000000000000000000000000000000023 +:10DE00000000000000000000000000000000000012 +:10DE10000000000000000000000000000000000002 +:10DE200000000000000000000000000000000000F2 +:10DE300000000000000000000000000000000000E2 +:10DE400000000000000000000000000000000000D2 +:10DE500000000000000000000000000000000000C2 +:10DE600000000000000000000000000000000000B2 +:10DE700000000000000000000000000000000000A2 +:10DE80000000000000000000000000000000000092 +:10DE90000000000000000000000000000000000082 +:10DEA0000000000000000000000000000000000072 +:10DEB0000000000000000000000000000000000062 +:10DEC0000000000000000000000000000000000052 +:10DED0000000000000000000000000000000000042 +:10DEE0000000000000000000000000000000000032 +:10DEF0000000000000000000000000000000000022 +:10DF00000000000000000000000000000000000011 +:10DF10000000000000000000000000000000000001 +:10DF200000000000000000000000000000000000F1 +:10DF300000000000000000000000000000000000E1 +:10DF400000000000000000000000000000000000D1 +:10DF500000000000000000000000000000000000C1 +:10DF600000000000000000000000000000000000B1 +:10DF700000000000000000000000000000000000A1 +:10DF80000000000000000000000000000000000091 +:10DF90000000000000000000000000000000000081 +:10DFA0000000000000000000000000000000000071 +:10DFB0000000000000000000000000000000000061 +:10DFC0000000000000000000000000000000000051 +:10DFD0000000000000000000000000000000000041 +:10DFE0000000000000000000000000000000000031 +:10DFF0000000000000000000000000000000000021 +:10E000000000000000000000000000000000000010 +:10E010000000000000000000000000000000000000 +:10E0200000000000000000000000000000000000F0 +:10E0300000000000000000000000000000000000E0 +:10E0400000000000000000000000000000000000D0 +:10E0500000000000000000000000000000000000C0 +:10E0600000000000000000000000000000000000B0 +:10E0700000000000000000000000000000000000A0 +:10E080000000000000000000000000000000000090 +:10E090000000000000000000000000000000000080 +:10E0A0000000000000000000000000000000000070 +:10E0B0000000000000000000000000000000000060 +:10E0C0000000000000000000000000000000000050 +:10E0D0000000000000000000000000000000000040 +:10E0E0000000000000000000000000000000000030 +:10E0F0000000000000000000000000000000000020 +:10E10000000000000000000000000000000000000F +:10E1100000000000000000000000000000000000FF +:10E1200000000000000000000000000000000000EF +:10E1300000000000000000000000000000000000DF +:10E1400000000000000000000000000000000000CF +:10E1500000000000000000000000000000000000BF +:10E1600000000000000000000000000000000000AF +:10E17000000000000000000000000000000000009F +:10E18000000000000000000000000000000000008F +:10E19000000000000000000000000000000000007F +:10E1A000000000000000000000000000000000006F +:10E1B000000000000000000000000000000000005F +:10E1C000000000000000000000000000000000004F +:10E1D000000000000000000000000000000000003F +:10E1E000000000000000000000000000000000002F +:10E1F000000000000000000000000000000000001F +:10E20000000000000000000000000000000000000E +:10E2100000000000000000000000000000000000FE +:10E2200000000000000000000000000000000000EE +:10E2300000000000000000000000000000000000DE +:10E2400000000000000000000000000000000000CE +:10E2500000000000000000000000000000000000BE +:10E2600000000000000000000000000000000000AE +:10E27000000000000000000000000000000000009E +:10E28000000000000000000000000000000000008E +:10E29000000000000000000000000000000000007E +:10E2A000000000000000000000000000000000006E +:10E2B000000000000000000000000000000000005E +:10E2C000000000000000000000000000000000004E +:10E2D000000000000000000000000000000000003E +:10E2E000000000000000000000000000000000002E +:10E2F000000000000000000000000000000000001E +:10E30000000000000000000000000000000000000D +:10E3100000000000000000000000000000000000FD +:10E3200000000000000000000000000000000000ED +:10E3300000000000000000000000000000000000DD +:10E3400000000000000000000000000000000000CD +:10E3500000000000000000000000000000000000BD +:10E3600000000000000000000000000000000000AD +:10E37000000000000000000000000000000000009D +:10E38000000000000000000000000000000000008D +:10E39000000000000000000000000000000000007D +:10E3A000000000000000000000000000000000006D +:10E3B000000000000000000000000000000000005D +:10E3C000000000000000000000000000000000004D +:10E3D000000000000000000000000000000000003D +:10E3E000000000000000000000000000000000002D +:10E3F000000000000000000000000000000000001D +:10E40000000000000000000000000000000000000C +:10E4100000000000000000000000000000000000FC +:10E4200000000000000000000000000000000000EC +:10E4300000000000000000000000000000000000DC +:10E4400000000000000000000000000000000000CC +:10E4500000000000000000000000000000000000BC +:10E4600000000000000000000000000000000000AC +:10E47000000000000000000000000000000000009C +:10E48000000000000000000000000000000000008C +:10E49000000000000000000000000000000000007C +:10E4A000000000000000000000000000000000006C +:10E4B000000000000000000000000000000000005C +:10E4C000000000000000000000000000000000004C +:10E4D000000000000000000000000000000000003C +:10E4E000000000000000000000000000000000002C +:10E4F000000000000000000000000000000000001C +:10E50000000000000000000000000000000000000B +:10E5100000000000000000000000000000000000FB +:10E5200000000000000000000000000000000000EB +:10E5300000000000000000000000000000000000DB +:10E5400000000000000000000000000000000000CB +:10E5500000000000000000000000000000000000BB +:10E5600000000000000000000000000000000000AB +:10E57000000000000000000000000000000000009B +:10E58000000000000000000000000000000000008B +:10E59000000000000000000000000000000000007B +:10E5A000000000000000000000000000000000006B +:10E5B000000000000000000000000000000000005B +:10E5C000000000000000000000000000000000004B +:10E5D000000000000000000000000000000000003B +:10E5E000000000000000000000000000000000002B +:10E5F000000000000000000000000000000000001B +:10E60000000000000000000000000000000000000A +:10E6100000000000000000000000000000000000FA +:10E6200000000000000000000000000000000000EA +:10E6300000000000000000000000000000000000DA +:10E6400000000000000000000000000000000000CA +:10E6500000000000000000000000000000000000BA +:10E6600000000000000000000000000000000000AA +:10E67000000000000000000000000000000000009A +:10E68000000000000000000000000000000000008A +:10E69000000000000000000000000000000000007A +:10E6A000000000000000000000000000000000006A +:10E6B000000000000000000000000000000000005A +:10E6C000000000000000000000000000000000004A +:10E6D000000000000000000000000000000000003A +:10E6E000000000000000000000000000000000002A +:10E6F000000000000000000000000000000000001A +:10E700000000000000000000000000000000000009 +:10E7100000000000000000000000000000000000F9 +:10E7200000000000000000000000000000000000E9 +:10E7300000000000000000000000000000000000D9 +:10E7400000000000000000000000000000000000C9 +:10E7500000000000000000000000000000000000B9 +:10E7600000000000000000000000000000000000A9 +:10E770000000000000000000000000000000000099 +:10E780000000000000000000000000000000000089 +:10E790000000000000000000000000000000000079 +:10E7A0000000000000000000000000000000000069 +:10E7B0000000000000000000000000000000000059 +:10E7C0000000000000000000000000000000000049 +:10E7D0000000000000000000000000000000000039 +:10E7E0000000000000000000000000000000000029 +:10E7F0000000000000000000000000000000000019 +:10E800000000000000000000000000000000000008 +:10E8100000000000000000000000000000000000F8 +:10E8200000000000000000000000000000000000E8 +:10E8300000000000000000000000000000000000D8 +:10E8400000000000000000000000000000000000C8 +:10E8500000000000000000000000000000000000B8 +:10E8600000000000000000000000000000000000A8 +:10E870000000000000000000000000000000000098 +:10E880000000000000000000000000000000000088 +:10E890000000000000000000000000000000000078 +:10E8A0000000000000000000000000000000000068 +:10E8B0000000000000000000000000000000000058 +:10E8C0000000000000000000000000000000000048 +:10E8D0000000000000000000000000000000000038 +:10E8E0000000000000000000000000000000000028 +:10E8F0000000000000000000000000000000000018 +:10E900000000000000000000000000000000000007 +:10E9100000000000000000000000000000000000F7 +:10E9200000000000000000000000000000000000E7 +:10E9300000000000000000000000000000000000D7 +:10E9400000000000000000000000000000000000C7 +:10E9500000000000000000000000000000000000B7 +:10E9600000000000000000000000000000000000A7 +:10E970000000000000000000000000000000000097 +:10E980000000000000000000000000000000000087 +:10E990000000000000000000000000000000000077 +:10E9A0000000000000000000000000000000000067 +:10E9B0000000000000000000000000000000000057 +:10E9C0000000000000000000000000000000000047 +:10E9D0000000000000000000000000000000000037 +:10E9E0000000000000000000000000000000000027 +:10E9F0000000000000000000000000000000000017 +:10EA00000000000000000000000000000000000006 +:10EA100000000000000000000000000000000000F6 +:10EA200000000000000000000000000000000000E6 +:10EA300000000000000000000000000000000000D6 +:10EA400000000000000000000000000000000000C6 +:10EA500000000000000000000000000000000000B6 +:10EA600000000000000000000000000000000000A6 +:10EA70000000000000000000000000000000000096 +:10EA80000000000000000000000000000000000086 +:10EA90000000000000000000000000000000000076 +:10EAA0000000000000000000000000000000000066 +:10EAB0000000000000000000000000000000000056 +:10EAC0000000000000000000000000000000000046 +:10EAD0000000000000000000000000000000000036 +:10EAE0000000000000000000000000000000000026 +:10EAF0000000000000000000000000000000000016 +:10EB00000000000000000000000000000000000005 +:10EB100000000000000000000000000000000000F5 +:10EB200000000000000000000000000000000000E5 +:10EB300000000000000000000000000000000000D5 +:10EB400000000000000000000000000000000000C5 +:10EB500000000000000000000000000000000000B5 +:10EB600000000000000000000000000000000000A5 +:10EB70000000000000000000000000000000000095 +:10EB80000000000000000000000000000000000085 +:10EB90000000000000000000000000000000000075 +:10EBA0000000000000000000000000000000000065 +:10EBB0000000000000000000000000000000000055 +:10EBC0000000000000000000000000000000000045 +:10EBD0000000000000000000000000000000000035 +:10EBE0000000000000000000000000000000000025 +:10EBF0000000000000000000000000000000000015 +:10EC00000000000000000000000000000000000004 +:10EC100000000000000000000000000000000000F4 +:10EC200000000000000000000000000000000000E4 +:10EC300000000000000000000000000000000000D4 +:10EC400000000000000000000000000000000000C4 +:10EC500000000000000000000000000000000000B4 +:10EC600000000000000000000000000000000000A4 +:10EC70000000000000000000000000000000000094 +:10EC80000000000000000000000000000000000084 +:10EC90000000000000000000000000000000000074 +:10ECA0000000000000000000000000000000000064 +:10ECB0000000000000000000000000000000000054 +:10ECC0000000000000000000000000000000000044 +:10ECD0000000000000000000000000000000000034 +:10ECE0000000000000000000000000000000000024 +:10ECF0000000000000000000000000000000000014 +:10ED00000000000000000000000000000000000003 +:10ED100000000000000000000000000000000000F3 +:10ED200000000000000000000000000000000000E3 +:10ED300000000000000000000000000000000000D3 +:10ED400000000000000000000000000000000000C3 +:10ED500000000000000000000000000000000000B3 +:10ED600000000000000000000000000000000000A3 +:10ED70000000000000000000000000000000000093 +:10ED80000000000000000000000000000000000083 +:10ED90000000000000000000000000000000000073 +:10EDA0000000000000000000000000000000000063 +:10EDB0000000000000000000000000000000000053 +:10EDC0000000000000000000000000000000000043 +:10EDD0000000000000000000000000000000000033 +:10EDE0000000000000000000000000000000000023 +:10EDF0000000000000000000000000000000000013 +:10EE00000000000000000000000000000000000002 +:10EE100000000000000000000000000000000000F2 +:10EE200000000000000000000000000000000000E2 +:10EE300000000000000000000000000000000000D2 +:10EE400000000000000000000000000000000000C2 +:10EE500000000000000000000000000000000000B2 +:10EE600000000000000000000000000000000000A2 +:10EE70000000000000000000000000000000000092 +:10EE80000000000000000000000000000000000082 +:10EE90000000000000000000000000000000000072 +:10EEA0000000000000000000000000000000000062 +:10EEB0000000000000000000000000000000000052 +:10EEC0000000000000000000000000000000000042 +:10EED0000000000000000000000000000000000032 +:10EEE0000000000000000000000000000000000022 +:10EEF0000000000000000000000000000000000012 +:10EF00000000000000000000000000000000000001 +:10EF100000000000000000000000000000000000F1 +:10EF200000000000000000000000000000000000E1 +:10EF300000000000000000000000000000000000D1 +:10EF400000000000000000000000000000000000C1 +:10EF500000000000000000000000000000000000B1 +:10EF600000000000000000000000000000000000A1 +:10EF70000000000000000000000000000000000091 +:10EF80000000000000000000000000000000000081 +:10EF90000000000000000000000000000000000071 +:10EFA0000000000000000000000000000000000061 +:10EFB0000000000000000000000000000000000051 +:10EFC0000000000000000000000000000000000041 +:10EFD0000000000000000000000000000000000031 +:10EFE0000000000000000000000000000000000021 +:10EFF0000000000000000000000000000000000011 +:00000001FF diff --git a/tests/fixtures/nuphy-air60_smk_jtag.hex b/tests/fixtures/nuphy-air60_smk_jtag.hex new file mode 100644 index 0000000..b2c2f7c --- /dev/null +++ b/tests/fixtures/nuphy-air60_smk_jtag.hex @@ -0,0 +1,3841 @@ +:1000000002F000320000000000000032000000009A +:10001000000000320000000000000032000000007C +:10002000000000320000000000000032000000006C +:100030000000003200000000000000021329000050 +:10004000000000020F5E000000000032000000000F +:10005000000000320000000000000032000000003C +:100060000000003200000000000000020FDA020170 +:10007000F7758185123BFBE582600302006E79040F +:10008000E94400601B7A0190413F78A775A002E423 +:1000900093F2A308B8000205A0D9F4DAF275A0FF24 +:1000A000E478FFF6D8FD7800E84400600A7900752E +:1000B000A000E4F309D8FC78A7E84402600C7903B7 +:1000C000900000E4F0A3D8FCD9FA750D00750E007D +:1000D00075337575343E75357F75363EE4F51AF522 +:1000E0001BE4F540F54102006EAF82BFA502800A15 +:1000F000BFA6028009BFA70E8008900001229000D1 +:1001000002229000042290000022AF82BFA800507B +:10011000030201CFEF243D50030201CFEF2458FF2B +:10012000240A83F582EF241F83F583E47363676BEE +:100130006F737F878B838F9397A3A7ABAFB3B7C33F +:10014000777BBBBF9B9FC7CB01010101010101016F +:10015000010101010101010101010101010101018F +:100160000101019000E2229000E9229000EA229031 +:1001700000B5229000B6229000B3229000B42290E5 +:1001800000B7229000CC229000CD229001832290D3 +:10019000018A22900192229001942290019F229044 +:1001A00001CB22900221229002232290022422904D +:1001B000022522900226229002272290006F229090 +:1001C00000702290022A2290029F229002A0229088 +:1001D000000022120F5A120EDD120F9D1229C212B8 +:1001E0000483120ECE1210D543B54043B94043B537 +:1001F0004085B9B9D2AF221201D374FFC0E0743B7D +:10020000C0E07480C0E012344115811581158174FD +:100210000CC0E0743CC0E07480C0E0123441158131 +:10022000158115819003E8120EF4122C3B121FCF9A +:10023000122DE29003E8120EF475B100122C4C124C +:100240002DB41207F280F2AF82BFA502800ABFA6CA +:10025000028009BFA70E80089000012290000222B0 +:100260009000042290000022AF82BFA80050030239 +:10027000032DEF243D500302032DEF2458FF240AE1 +:1002800083F582EF241F83F583E473C1C5C9CDD103 +:10029000DDE5E9E1EDF1F50105090D111521D5D9EE +:1002A000191DF9FD252902020202020202020202C0 +:1002B0000202030303030303030202030302020314 +:1002C000039000E2229000E9229000EA229000B51B +:1002D000229000B6229000B3229000B4229000B782 +:1002E000229000CC229000CD229001832290018A9E +:1002F00022900192229001942290019F229001CBA2 +:100300002290022122900223229002242290022590 +:1003100022900226229002272290006F22900070E5 +:100320002290022A2290029F229002A02290000096 +:1003300022022D5D022D7AAE82AF839002A7E0FCEF +:10034000A3E0FDEEB50405EFB50501229002A7EE8E +:10035000F0EFA3F09000007401F0900001EEF0EFD8 +:10036000A3F0900000022D97AE82AF839002A9E027 +:10037000FCA3E0FDEEB50405EFB50501229002A94E +:10038000EEF0EFA3F09000007402F0900001EEF0A8 +:10039000EFA3F0900000022D97AF82BFA502800A64 +:1003A000BFA6028009BFA70E80089000012290001E +:1003B00002229000042290000022AF82BFA80050C9 +:1003C0000302047FEF243D500302047FEF2458FF13 +:1003D000240A83F582EF241F83F583E47313171B2C +:1003E0001F232F373B333F434753575B5F6367738D +:1003F000272B6B6F4B4F777B040404040404040425 +:1004000004040404040404040404040404040404AC +:100410000404049000E2229000E9229000EA229075 +:1004200000B5229000B6229000B3229000B4229032 +:1004300000B7229000CC229000CD22900183229020 +:10044000018A22900192229001942290019F229091 +:1004500001CB22900221229002232290022422909A +:10046000022522900226229002272290006F2290DD +:1004700000702290022A2290029F229002A02290D5 +:10048000000022750800750900750A007E007F00D3 +:10049000C3EE9410EF64809480501FEE2403F58225 +:1004A000EF3400F583E4F0EE2413F582EF3400F529 +:1004B00083E4F00EBE00D90F80D622E5822403F536 +:1004C00082E43400F583E0F5822285098222E58208 +:1004D000C42354E0FF24B4FDE4343EFEE50B250BB9 +:1004E000FC2DF582E43EF583E493FDA3E493FEE561 +:1004F0000C60067A3C7B3C80047A3F7B3C8B017B22 +:1005000080C007C006C005C004C002C001C003C04F +:1005100005C006742BC0E0743CC0E0EBC0E01234B0 +:1005200041E58124F8F581D004D005D006D0078DAF +:10053000028E03C3EA9420EB9452403F743F9A74B6 +:10054000529B4037E50C60098D03741F5BF50A80F0 +:100550000C90002575F000120E3C750A00AA0A7B6B +:1005600000C002C0037444C0E0743CC0E07480C0AA +:10057000E0123441E58124FBF58122E50A6033E590 +:100580000A75F0A0A424B4FA743E35F0FBEF2AFA01 +:10059000E43BFBEC2AF582E43BF583E493FCA3E423 +:1005A00093FF8C028F03BA0105BB000280048C0507 +:1005B0008F06850C198D828E83C006C005122D1FF3 +:1005C000E582D005D006700122850C1C8D828E83B9 +:1005D000C006C005123230E582D005D00670012277 +:1005E0008D048E07C3EC94E0EF9400403E74E79CCA +:1005F000E49F4037E50C60198D0374075BF5F00547 +:10060000F07401800225E0D5F0FBF582120E8B809C +:10061000178D0374075BF5F005F07401800225E087 +:10062000D5F0FBF582120E90020A00C3EC9404EFA1 +:100630009400402674A49CE49F401FE50C600D8D3F +:100640001290002575F000120DCC800B8D139000D8 +:100650002575F000120E04020A00C3EC94A5EF9475 +:1006600000403F74A79CE49F4038E50C602E8D034A +:10067000BBA502800ABBA602800BBBA714800C7A24 +:10068000017B0080107A027B00800A7A047B008064 +:10069000047A007B008A828B830203379000000279 +:1006A0000337C3EC94A8EF940050030207D8C37437 +:1006B000C29CE49F50030207D8E50C70030207D1E7 +:1006C0008D07BFA80050030207C4EF243D5003026A +:1006D00007C4EF2458FF240A83F582EF241F83F513 +:1006E00083E4731920272E354A585E51646A70825C +:1006F000888E949AA0B23C43A6AC767CB8BE07071D +:100700000707070707070707070707070707070779 +:100710000707070707070707077CE27F000207C8EC +:100720007CE97F000207C87CEA7F000207C87CB52D +:100730007F000207C87CB67F000207C87CB37F0039 +:100740000207C87CB47F000207C87CB77F0002079D +:10075000C87CCC7F000207C87CCD7F00806A7C8388 +:100760007F0180647C8A7F01805E7C927F0180585B +:100770007C947F0180527C9F7F01804C7CCB7F01E9 +:1007800080467C217F0280407C237F02803A7C244B +:100790007F0280347C257F02802E7C267F02802889 +:1007A0007C277F0280227C6F7F00801C7C707F0012 +:1007B00080167C2A7F0280107C9F7F02800A7CA0AA +:1007C0007F0280047C007F008C828F83120368800C +:1007D0000690000002036822C005C0067458C0E0FD +:1007E000743CC0E07480C0E0123441E58124FBF524 +:1007F00081221204CAE5827003F58222900023E46C +:10080000F0FFBF10005039900023E0FEE07031EFA0 +:100810002413F582E43400F583E0FD8F82C007C025 +:1008200006C0051204BBAC82D005D006D007EC622E +:1008300005EE4205900023ED24FFE433F00F80C263 +:10084000900023E0FFE07005F5098F82227F00BF52 +:100850001000506C8F82C0071204BBAE82D007EF2D +:100860002413F582E43400F583E0FDEE6205ED60CB +:100870004C9000247401F07C00BC050050339000C3 +:1008800024E0FB5D6021EE5203EB24FFE433F50C22 +:100890008F0B8C82C007C006C005C0041204CED0E6 +:1008A00004D005D006D0070C900024E025E0F080AD +:1008B000C8EF2413F582E43400F583EEF00F808F47 +:1008C000750900900023E0F58222122DE5E50970FC +:1008D000238508821229398508821229A3AF82C094 +:1008E000071229B5D007E5082403F582E43400F5A2 +:1008F00083EFF4F085084290006175F000122DF747 +:1009000074F125084007E50804F50880067508001D +:1009100075090102300BAF82BFA502800ABFA60293 +:100920008009BFA70E80089000012290000222904B +:1009300000042290000022AF82BFA80050030209E9 +:10094000FCEF243D50030209FCEF2458FF240A83E6 +:10095000F582EF241F83F583E4739094989CA0ACF8 +:10096000B4B8B0BCC0C4D0D4D8DCE0E4F0A4A8E8EB +:10097000ECC8CCF4F80909090909090909090909A8 +:1009800009090909090909090909090909090909D7 +:100990009000E2229000E9229000EA229000B52225 +:1009A0009000B6229000B3229000B4229000B722AB +:1009B0009000CC229000CD229001832290018A22C7 +:1009C000900192229001942290019F229001CB22CB +:1009D00090022122900223229002242290022522BA +:1009E000900226229002272290006F22900070220F +:1009F00090022A2290029F229002A02290000022C0 +:100A00001211C5AF82BF0109900063E06003020AC2 +:100A100062020A14900025E50DF0E50D450E9000E8 +:100A200025F075752D7576007577007578087579E0 +:100A30000090002575F000123383E5828583F04530 +:100A4000F0601E75752575760075770075780875E8 +:100A5000790090002D75F00012329A900025020363 +:100A600031229000357406F0900036E50DF0E50D6A +:100A7000450E900036F075754B75760075770075EC +:100A8000781675790090003575F000123383E58291 +:100A90008583F045F0601E757535757600757700B5 +:100AA00075781675790090004B75F00012329A90A7 +:100AB000003502033422AD82AE83AFF074022DFD07 +:100AC000E43EFE7C06C007C006C005C0041211C586 +:100AD000AB82D004D005D006D007BB010E900063D6 +:100AE000E060087D377E007F007C147B008C021C58 +:100AF000EA60158D828E838FF0123BA9FAA3AD8236 +:100B0000AE83EA60E80B80E58B8222AD82AE83AFD4 +:100B1000F0C007C006C0051211C5AC82D005D006D2 +:100B2000D007BC0142900063E0603C7C00BC140034 +:100B30005012EC2437FAE43400FB8A828B83E07095 +:100B4000030C80E98C03EBC40354F8FBEC2437F569 +:100B500082E43400F583E0F582C003120EA2AC8279 +:100B6000D003EC4BF5822274022DFDE43EFE8D8213 +:100B70008E838FF0123BA9F58222AD82AE83AFF057 +:100B8000E50F7003F58222C007C006C0051211C52B +:100B9000AC82D005D006D007BC014B900063E0606A +:100BA00045E50FC423541FFCBC14005035EC24371A +:100BB000F582E43400F583E50F5407FC8CF005F072 +:100BC0007C017B008006EC2CFCEB33FBD5F0F7E0DE +:100BD000F97A00E95204EA5203EC4B24FFE433F5BE +:100BE00082227582002274022DFDE43EFE7B007C91 +:100BF00000C3EB9406EC64809480501FEB2DF8EC5E +:100C00003EF98F02888289838AF0123BA9B50F04CE +:100C1000758201220BBB00D90C80D675820022851B +:100C2000827685837785F0787CFF74022576F9E4F7 +:100C30003577FAAB7889798A7A8B7B7800C3E86458 +:100C40008094865033E829FDE43AFE8B078D828E2E +:100C5000838FF0123BA9B57502801DBCFF17E825F4 +:100C600079FDE4357AFEAF7B8D828E838FF0123B67 +:100C7000A9700288040880C5B80622BCFF0122744E +:100C8000022576FDE43577FEAF78EC2DFCE43EFBE3 +:100C90008F028C828B838AF0E57502330E22AD823F +:100CA000AE83AFF074022DFDE43EFE8D778E788F1B +:100CB0007975760074FA25764044C005C006C007F1 +:100CC000E5762577F8E43578F9AF79888289838FDE +:100CD000F0123BA9B575028008D007D006D0058078 +:100CE00019D007D006D005E5762DF8E43EF98F043B +:100CF000888289838CF0E412330E057680B622ADAB +:100D000082AE83AFF0E510C423541FFCBC14005026 +:100D10003674022DFDE43EFEEC2DFCE43EFB8F021A +:100D2000E5105407F5F005F07401800225E0D5F0D8 +:100D3000FBFF8C828B838AF0123BA942078C828B4B +:100D4000838AF0EF02330EAE107F00C006C0077436 +:100D500073C0E0743CC0E07480C0E0123441E581AF +:100D600024FBF58122AD82AE83AFF0E511C423549C +:100D70001FFCBC1400503774022DFDE43EFEEC2D28 +:100D8000FCE43EFB8F02E5115407F5F005F0740119 +:100D9000800225E0D5F0FBF4FF8C828B838AF01271 +:100DA0003BA952078C828B838AF0EF02330EAE117F +:100DB0007F00C006C0077491C0E0743CC0E074803E +:100DC000C0E0123441E58124FBF58122AD82AE837F +:100DD000AFF0C007C006C0051211C5AC82D005D067 +:100DE00006D007BC0112900063E0600C85121090E1 +:100DF000003575F000020CFF8512758D828E838F91 +:100E0000F0020C1FAD82AE83AFF0C007C006C00574 +:100E10001211C5AC82D005D006D007BC01129000DB +:100E200063E0600C85131190003575F000020D65CC +:100E30008513758D828E838FF0020C9EAD82AE83FA +:100E4000AFF0C007C006C0051211C5AC82D005D0F6 +:100E500006D007BC0118900063E06012757500753C +:100E6000761475770090003775F0000232EF740247 +:100E70002DFDE43EFE7575007576067577008D8252 +:100E80008E838FF00232EF850D8222E582420D22A1 +:100E9000E582F4520D2285820D22750D0022850E09 +:100EA0008222AF827E00EFC4540FFD60048D077E66 +:100EB00004EF0303543FFD60088D078E0574022D77 +:100EC000FEEFC31360058E07EF04FE8E82229000B2 +:100ED00061E4F0900062F090006304F02275B208C3 +:100EE00075BC02E5BC20E20575B10080F643BC018B +:100EF00043B20422AE82AF837C007D00C3EC9EED42 +:100F00009F501D9003E8C007C006C005C004120F23 +:100F100021D004D005D006D0070CBC00DF0D80DC4A +:100F200022AE82AF837C007D00C3EC9EED9F501FFC +:100F300075B100000000000000000000000000008B +:100F400000000000000000000CBC00DD0D80DA2273 +:100F5000C2AF75F0A5745A02FF00758F0122C0213F +:100F6000C0E0C0F0C082C083C007C006C005C00496 +:100F7000C003C002C001C000C0D075D0001208CAB2 +:100F8000D0D0D000D001D002D003D004D005D006FC +:100F9000D007D083D082D0F0D0E0D0213275D840B5 +:100FA00075ADFF75AEE675AF0075870075AB007562 +:100FB000AC0053A9BFC20010D902800010D8028033 +:100FC0000043A94022AF8253A9BFD2008FAA43A9F0 +:100FD0004030000575B10080F82253A9BF10D90236 +:100FE0008002C20043A94032020FC5AF82BFA502F2 +:100FF000800ABFA6028009BFA70E800890000122C8 +:10100000900002229000042290000022AF82BFA82C +:101010000050030210D1EF243D50030210D1EF2401 +:1010200058FF240A83F582EF241F83F583E4736558 +:10103000696D717581898D85919599A5A9ADB1B5B8 +:10104000B9C5797DBDC19DA1C9CD1010101010107A +:101050001010101010101010101010101010101090 +:1010600010101010109000E2229000E9229000EA87 +:10107000229000B5229000B6229000B3229000B4D6 +:10108000229000B7229000CC229000CD22900183C4 +:101090002290018A22900192229001942290019F35 +:1010A000229001CB2290022122900223229002243E +:1010B0002290022522900226229002272290006F81 +:1010C000229000702290022A2290029F229002A079 +:1010D0002290000022900264E4F0900265F09002F9 +:1010E00066F0900267F0900268F0C20190026AE434 +:1010F000F0900269F0F522F523F524F525F526F5A3 +:101100009675945F7595117591C043A90122AE82C1 +:10111000AF837D00BDFF00501AE59930E2159000C5 +:1011200028C007C006C005120F21D005D006D00781 +:101130000D80E17D007531088E828F838DF0121D48 +:1011400066539CE0439C0843990422AE82AF837DA2 +:1011500000BDFF00501AE59A30E215900028C00744 +:10116000C006C005120F21D005D006D0070D80E1C2 +:101170007D007532168E828F838DF0121DCF539DA8 +:1011800080439D16439A0422AE82AF837D00BDFF4B +:1011900000501AE59A30E215900028C007C006C03A +:1011A00005120F21D005D006D0070D80E17D007516 +:1011B00032038E828F838DF0121DCF539D80439D0D +:1011C00003439A0422900267E0F58222C2AF9002A4 +:1011D0006B75F000121D48D2AF90026BE0FF9002D9 +:1011E0006CE0FE8F05BD0002802CBD01030212766B +:1011F000BF02030212ABBF21030212D8BF800280DC +:1012000050BF8103021286BF82030212C8BFA1032E +:10121000021300021322BE01028014BE03028015D5 +:10122000BE05028016BE07028017BE091D801590FC +:10123000026B02144090026B02146E90026B021457 +:10124000050215EE90026B0215484397084397027A +:1012500022BE0002800ABE0602800BBE0811800C6E +:1012600090026B0215F590026B02171B021AD04315 +:10127000970843970222BE0B0690026B0215A0430B +:10128000970843970222BE0002800ABE0602800B26 +:10129000BE0A11800C90026B02163090026B02178E +:1012A0001B021AE843970843970222BE01028005F9 +:1012B000BE030E800690026B02149C90026B021417 +:1012C000FA43970843970222BE000690026B02166B +:1012D0007343970843970222BE0902800ABE0A029E +:1012E000800BBE0B14800C90026B021B0490026BEF +:1012F000021B5F90026B021B8143970843970222F7 +:10130000BE0102800ABE02028008BE030E800602F1 +:101310001AFD021B6F90026B021BB643970843979E +:10132000022243970843970222C021C0E0C0F0C0C8 +:1013300082C083C007C006C005C004C003C002C08D +:1013400001C000C0D075D000AF92AE93EF6056EFF1 +:1013500030E3065392F70213E85392EF53929FEF54 +:1013600030E70953927F1210D50213E8EF30E408FA +:101370005392EF1211CC8070EF30E2055392FB8054 +:1013800067EF30E1055392FD805EEF30E05A5392F3 +:10139000FE4391200000000000005391DF1210D5A1 +:1013A0004397018043EE6040EE30E6085393BF431D +:1013B0009A018034EE30E5055393DF802BEE30E464 +:1013C0000B5393EF121BE4439701801CEE30E205B0 +:1013D0005393FB8013EE30E1055393FD800AEE300A +:1013E000E0065393FE121C27D0D0D000D001D002CB +:1013F000D003D004D005D006D007D083D082D0F05F +:10140000D0E0D02132AE82AF8390026AE4F0740261 +:101410002EFEE43FFF8E828F83E0FCA3E04C600849 +:101420009002647401F08005900264E4F08E828F73 +:1014300083E0900265F0539BF043970243970422A8 +:10144000AE82AF8390026AE4F08E828F83E0540F05 +:10145000600280138E828F83A3A3E0FEA3E0FFBE11 +:101460000105BF0002C201539BF043970422AE82E4 +:10147000AF8390026AE4F08E828F83E0540F6002A3 +:1014800080138E828F83A3A3E0FEA3E0FFBE01053D +:10149000BF0002D201539BF043970422AE82AF8378 +:1014A00090026AE4F08E828F83E0FD53050FBD0247 +:1014B000428E828F83A3A3E0FCA3E04C70358E8222 +:1014C0008F83A3A3A3A3E0FEA3E0FF4E700853976E +:1014D000F75397FD801DBE8108BF00055399F78023 +:1014E00012BE8208BF0005539AF78007439708434E +:1014F000970222539BF043970422AE82AF8390025F +:101500006AE4F08E828F83E0FD53050FBD022B8EBF +:10151000828F83A3A3A3A3E0FEA3E0FFBE8108BF45 +:101520000005439908801ABE8208BF0005439A0847 +:10153000800F439708439702800743970843970219 +:1015400022539BF043970422AE82AF8390026AE459 +:10155000F0E596603E8E828F83A3A3E0FEA3E0FFBA +:101560004E600A8E048F05BC0121BD001E900266EC +:10157000EEF0EE60089002647402F080069002645F +:101580007401F0539BF0439704800E4397084397F0 +:10159000028006439708439702539BF04397042227 +:1015A000AE82AF8390026AE4F08E828F83A3A3E0C1 +:1015B000FCA3E04C70318E828F83A3A3A3A3E0FE33 +:1015C000A3E0FF4E700A539BF04397044397022217 +:1015D000BE010DBF000A539BF043970443970222BC +:1015E0004397084397022243970843970222439761 +:1015F0000843970222AE82AF8390026A7402F08E93 +:10160000828F83E0540F6002801F30010890110820 +:101610007402F08005901108E4F0901109E4F05391 +:101620009BF0439B0243970422439708439702226F +:10163000AE82AF83E0FD53050FBD01308E828F83F4 +:10164000A3A3A3A3E0FEA3E0FF4E6006BE0116BF66 +:101650000013901108E4F0901109F0539BF0439BA4 +:101660000243970422439708439702224397084373 +:10167000970222AE82AF83E0FD53050FBD020280C8 +:10168000030217148E828F83A3A3A3A3E0FEA3E01B +:10169000FFBE801BBF0018AC97530402E4A2E713FF +:1016A000CC13CC901108ECF0901109E4F0805BBEF3 +:1016B0008127BF0024AC99530408E423CCC42354ED +:1016C0001F6CCC541FCC6CCC30E40244E090110869 +:1016D000ECF0901109E4F08031BE8227BF0024AE07 +:1016E0009A530608E423CEC423541F6ECE541FCE53 +:1016F0006ECE30E40244E0901108EEF0901109E45F +:10170000F0800743970843970222539BF0439B02C4 +:1017100043970422439708439702228582278583B3 +:1017200028A3A3E0FCA3E0FBBB0141903DD0E493E0 +:10173000FAA3E493FD8A758D767577808A828D830E +:10174000E493FA8A7875790090006475F00012329B +:101750009A9002737464F07400A3F0E4A3F0900014 +:1017600064E0900276F0E4A3F0021A8DBB020280DE +:101770000302188A903DD4E493FDC3EC9D4003021C +:10178000188A903DD5E493FAA3E493FDEC75F0023A +:10179000A42AF582ED35F0F583E493FAA3E493FDF2 +:1017A00074092AF529E43DF52A8A008D0188758996 +:1017B000767577808A828D83E493F98978757900CC +:1017C00090006475F000C005C00212329AD002D0B9 +:1017D000058A828D83E4932464F52BE43400F52C90 +:1017E000A829A92A852B2D852C2E752F0088828962 +:1017F00083E493FAA3E493FF8A758F767577808AE2 +:10180000828F83E493FA8A78757900852D82852EFC +:1018100083852FF0C001C00012329AD000D0018819 +:10182000828983E493FEA3E493FF8E828F83E49303 +:10183000252BF52BE4352CF52C740228F8E439F926 +:1018400088828983E493FEA3E4934E7097900066A8 +:10185000E0FEA3E04E7013E52BC39464FEE52C94E8 +:1018600000FF900066EEF0EFA3F09002737464F056 +:101870007400A3F0E4A3F0900066E0FEA3E0FF9004 +:101880000276EEF0EFA3F0021A8DE4BB030104FF31 +:10189000603BEC70387575C675763D757780903D08 +:1018A000C6E493FE8E7875790090006475F000129E +:1018B000329A9002737464F07400A3F0E4A3F09081 +:1018C0000064E0900276F0E4A3F0021A8DEF70035A +:1018D00002197F7F00EC24FFFDEF34FFFE903DD71F +:1018E000E493F97A00C3ED99EE64808AF063F080A6 +:1018F00095F0400302197F903DD8E493FDA3E49353 +:10190000FE1CBCFF011FEC2CFCEF33FFEC2DF5821D +:10191000EF3EF583E493FEA3E493FF90006474022A +:10192000F090006504F074012465FCE43400FD8E41 +:10193000828F83E493FA602C0EBE00010F8C828D9F +:1019400083EAF074012CF9E43DFA89828A83E4F099 +:101950000429FCE43AFD900064E0FA0A0A9000646D +:10196000EAF080CB9002737464F07400A3F0E4A3F7 +:10197000F0900064E0900276F0E4A3F0021A8DBBD0 +:101980002276852782852883A3A3A3A3E0FE702F58 +:101990009002767444F0E4A3F07575AF75763C75EB +:1019A0007780757844F579900064F5F012329A905A +:1019B00002737464F07400A3F0E4A3F0021A8DBE05 +:1019C000012F9002767476F0E4A3F07575F37576C6 +:1019D0003C757780757876F579900064F5F0123271 +:1019E0009A9002737464F07400A3F0E4A3F0021AF6 +:1019F0008D43970843970222BB21028003021A8677 +:101A0000852782852883A3A3A3A3E0FE703775757D +:101A10008475763D757780903D84E493FF8F78756B +:101A2000790090006475F00012329A900273746429 +:101A3000F07400A3F0E4A3F0900064E0900276F06C +:101A4000E4A3F08048BE013775759D75763D7577C6 +:101A500080903D9DE493FF8F7875790090006475C8 +:101A6000F00012329A9002737464F07400A3F0E4F0 +:101A7000A3F0900064E0900276F0E4A3F0800E43BF +:101A800097084397022243970843970222852782AB +:101A9000852883A3A3A3A3A3A3E0FEA3E0FF900252 +:101AA00076E0FCA3E0FDC3EE9CEF9D40048C068D28 +:101AB00007900273E0FBA3E0FCA3E0FD8E758F7638 +:101AC0008B828C838DF0121C50121C604397042271 +:101AD00090026A7402F0900266E0901108F0539B45 +:101AE000F0439B014397042290026A7402F0901124 +:101AF00008E4F0539BF0439B01439704224397086B +:101B000043970222AE82AF83A3A3E0FCA3E0FABA1C +:101B100002028005BA0341802D8E828F83A3A3A386 +:101B2000A3E0FAA3E04A703674062EF582E43FF58E +:101B300083E0FEA3E0FFBE0125BF002290026A748D +:101B400004F0439701227D00BC0513BD00109002F4 +:101B50006A7405F04397012243970843970222A332 +:101B6000A3E0A3E0900269F0539BF0439704229016 +:101B70000269E0901108F0539BF0439B01439704E6 +:101B800022AE82AF83A3A3A3A3E0FCA3E0FD4C702D +:101B90000D8E828F83A3A3E0900267F08011BC01B9 +:101BA0000EBD000B8E828F83A3A3E0900268F053DA +:101BB0009BF043970422A3A3A3A3E0FEA3E0FF4E60 +:101BC000700A900267E0901108F0800EBE010BBF12 +:101BD0000008900268E0901108F0539BF0439B01CD +:101BE0004397042290026AE0FFBF041490026AE463 +:101BF000F0901100E0900061F0539BF043970422B5 +:101C0000BF051890026AE4F0901100E0FFBF0516CE +:101C1000901101E0FFBF750E020F5090026AE4F0D0 +:101C2000539BF04397042290026AE0FFBF010A121F +:101C30001C6043970443970122BF02074397014367 +:101C4000970822439708439701900265E0F5962292 +:101C500085822485832585F0268575228576232235 +:101C6000E5224523700D90026A7402F0539BF085C3 +:101C70009B9B22AE22AF23C374089EE49F503790F3 +:101C8000026A7401F07530088524828525838526D3 +:101C9000F0121CFDAC22AD23EC24F8FCED34FFFD6A +:101CA0008C228D2374082524F524E43525F525534D +:101CB0009BF0439B0822BE0824BF002190026A7457 +:101CC00001F07530088524828525838526F0121C55 +:101CD000FDE4F522F523539BF0439B082290026A12 +:101CE0007402F08522308524828525838526F012B2 +:101CF0001CFD539BF0AF9BE5224FF59B22AD82AEBE +:101D000083AFF0E53024F7502AAB307C00C003C02D +:101D10000474F1C0E0743DC0E07480C0E074DAC0C7 +:101D2000E0743DC0E07480C0E0123441E58124F8E5 +:101D3000F581228D758E768F778530787579009054 +:101D4000110875F00002329AAD82AE83AFF075755E +:101D5000007576117577007578087579008D828E1B +:101D6000838FF002329AAD82AE83AFF0E53124EF7B +:101D7000502AAB317C00C003C0047403C0E0743E41 +:101D8000C0E07480C0E074DAC0E0743DC0E07480EC +:101D9000C0E0123441E58124F8F581228D758E76FC +:101DA0008F7785317875790090112075F0000232B7 +:101DB0009AAD82AE83AFF0757510757611757700A8 +:101DC0007578107579008D828E838FF002329AAD0E +:101DD00082AE83AFF0E53224BF502AAB327C00C024 +:101DE00003C0047415C0E0743EC0E07480C0E074A9 +:101DF000DAC0E0743DC0E07480C0E0123441E58197 +:101E000024F8F581228D758E768F778532787579F5 +:101E10000090118075F00002329AAD82AE83AFF06F +:101E20007575407576117577007578407579008DF8 +:101E3000828E838FF002329A85821685831785F011 +:101E400018C2AFC285900003120F21C2FC7B007C38 +:101E500000C3EB9514EC64808515F063F08095F079 +:101E6000503FEB2516F8EC3517F9AA1888828983BC +:101E70008AF0123BA9F582C004C003C002C001C0B1 +:101E800000121EAAAF82D000D001D002D003D0042D +:101E9000888289838AF0EF12330E0BBB00B30C806B +:101EA000B0D2FCD287D285D2AF22AF827E007D0035 +:101EB000BD0800502D8E04EC2CFEC2B700000000BF +:101EC00000000000EF30E704D2878002C28730862E +:101ED00003430601D2B7000000008F04EC2CFF0D75 +:101EE00080CE8E8222AF82BFA502800ABFA602806A +:101EF00009BFA70E800890000122900002229000E6 +:101F0000042290000022AF82BFA8005003021FCB22 +:101F1000EF243D5003021FCBEF2458FF240A83F522 +:101F200082EF241F83F583E4735F63676B6F7B83AA +:101F3000877F8B8F939FA3A7ABAFB3BF7377B7BBDD +:101F4000979BC3C71F1F1F1F1F1F1F1F1F1F1F1F61 +:101F50001F1F1F1F1F1F1F1F1F1F1F1F1F1F1F9020 +:101F600000E2229000E9229000EA229000B522903F +:101F700000B6229000B3229000B4229000B72290C5 +:101F800000CC229000CD229001832290018A2290E1 +:101F90000192229001942290019F229001CB2290E5 +:101FA00002212290022322900224229002252290D4 +:101FB0000226229002272290006F22900070229029 +:101FC000022A2290029F229002A022900000221258 +:101FD00028B8900006120EF490029875F0001223B3 +:101FE000269000C8120F2185333D85343E753F8011 +:101FF0007582001227B590000C120EF412268D90F7 +:102000000020120EF485353D85363E753F80758281 +:10201000011227B590000C120EF412268D90001EAE +:10202000120EF47538007582001223C0900014124D +:102030000EF47538007582001223C090000F120E46 +:10204000F4E4F53BF53C9000001226C490001E120B +:102050000EF40222CDAE82AF83E090029AF08E821F +:102060008F83A3A3E090029BF08E828F83A3A3A310 +:10207000E090029CF08E828F83A3A3A3A3E0900242 +:102080009DF08E828F83A3A3A3A3A3E090029EF072 +:1020900074062EF582E43FF583E090029FF07537D9 +:1020A000017E007F00C3EE9406EF64809480501997 +:1020B000EE249AFCEF3402FD8C828D83E060037580 +:1020C00037000EBE00DF0F80DCE537606190029BB9 +:1020D000E4F090029AF5F012240490029B7401F04F +:1020E00090029A75F00012240490029BE4F0900292 +:1020F0009AF5F012240490029B7401F090029A75F4 +:10210000F00012240490029BE4F090029AF5F01281 +:10211000240490029B7401F090029A75F00012243E +:102120000490029BE4F090029AF5F00224049002DD +:102130009A75F000022404AE82AF839002A074016D +:10214000F0FC7D00C3EC9415ED648094805019EC94 +:102150002EFAED3FFB8A828B83E060059002A0E4BB +:10216000F00CBC00DF0D80DC9002A0E0FDFB33959D +:10217000E0FCC007C006C005C003C0047450C0E046 +:10218000743EC0E07480C0E0123441E58124FBF568 +:1021900081D005D006D007ED70030221FE90029B8E +:1021A000E4F090029AF5F012240490029B7401F07E +:1021B00090029A75F00012240490029BE4F09002C1 +:1021C0009AF5F012240490029B7401F090029A7523 +:1021D000F00012240490029BE4F090029AF5F012B1 +:1021E000240490029B7401F090029A75F00012246E +:1021F0000490029BE4F090029AF5F00224048E828F +:102200008F83A3E0FD74022EF539E43FF53A8D8209 +:102210000224E0AE82AF83E0FDBD01028005BD0275 +:102220002A80128E828F83A3E0F53BA3E0F53C90D9 +:1022300000000226C48E828F83A3E0FEA3E0FFE4A9 +:10224000F53BF53C8E828F830226C422AD82AE839D +:10225000AFF09002A175F000C007C006C0051223C0 +:1022600026D005D006D0079002A2E0FC5304078DCB +:10227000828E838FF0EC12330E0DBD00010E8D8225 +:102280008E838FF0123BA9FC9002A2E05460C4033D +:102290005407FB8D828E838FF012330EECB5030151 +:1022A000228D828E838FF0123BA9FD7F00C005C076 +:1022B00007745FC0E0743EC0E07480C0E012344137 +:1022C000E58124FBF581227538000223C090027855 +:1022D00074AAF0900279741DF090027A7402F07E74 +:1022E000037F00C3EE941FEF648094805013EE24AC +:1022F00078F582EF3402F583E4F00EBE00E50F803E +:10230000E275751F75760090027875F0001228F658 +:10231000AF82900297EFF075142075150090027847 +:1023200075F000021E38AD82AE83AFF0C007C00664 +:10233000C00512283C900064120F2112239FD00583 +:10234000D006D007900278E0FCBCBB028004758206 +:10235000002275750275760090027A75F000C0074C +:10236000C006C0051228F6AC82D005D006D0079072 +:102370000279E0B5040280047582002290027AE0BE +:102380008D828E838FF012330E0DBD00010E9002F0 +:102390007BE08D828E838FF012330E758201229046 +:1023A000027874FFF0900279F090027AF090027B4C +:1023B000F075140475150090027875F000021E384F +:1023C000AF8290027874AAF09002797403F09002C0 +:1023D0007A7401F090027BE538F090027CEFF075A2 +:1023E000750575760090027875F0001228F6AF82B8 +:1023F00090027DEFF075140675150090027875F067 +:1024000000021E38AD82AE83AFF090027874AAF05D +:10241000900279741DF090027A7402F08D828E839E +:102420008FF0123BA990027BF074012DFAE43EFB81 +:102430008F048A828B838CF0123BA990027CF0740B +:10244000022DFAE43EFB8F048A828B838CF0123BD0 +:10245000A990027DF074032DFAE43EFB8F048A827A +:102460008B838CF0123BA990027EF074042DFAE469 +:102470003EFB8F048A828B838CF0123BA990027FF3 +:10248000F074052DFDE43EFE8D828E838FF0123BAD +:10249000A9900280F0900281E4F07E0AFFC3EE94DE +:1024A0001FEF648094805013EE2478F582EF34029D +:1024B000F583E4F00EBE00E50F80E275751F7576BA +:1024C0000090027875F0001228F6AF82900297EF24 +:1024D000F075142075150090027875F000021E3812 +:1024E000E5829002A3F090027874AAF090027974C9 +:1024F0001DF090027A7402F09002A3E090027BF04B +:1025000090027CE4F090027DF090027EF090027FD9 +:10251000F0900280F0900281F0AE39AF3A8E828F57 +:1025200083E0900282F08E828F83A3E0900283F09A +:102530008E828F83A3A3E0900284F08E828F83A388 +:10254000A3A3E0900285F08E828F83A3A3A3A3E0D0 +:10255000900286F08E828F83A3A3A3A3A3E09002B0 +:1025600087F074062EF582E43FF583E0900288F050 +:1025700074072EF582E43FF583E0900289F0740839 +:102580002EF582E43FF583E090028AF074092EF57F +:1025900082E43FF583E090028BF0740A2EF582E42A +:1025A0003FF583E090028CF0740B2EF582E43FF54A +:1025B00083E090028DF0740C2EF582E43FF583E009 +:1025C00090028EF0740D2EF582E43FF583E09002C8 +:1025D0008FF0740E2EF582E43FF583E0900290F0C8 +:1025E000740F2EF582E43FF583E0900291F07410B1 +:1025F0002EF582E43FF583E0900292F074112EF5FF +:1026000082E43FF583E0900293F074122EF582E4A9 +:102610003FF583E0900294F074132EF582E43FF5C9 +:1026200083E0900295F0900296E4F075751FF576C0 +:10263000900278F5F01228F6AF82900297EFF075CD +:10264000142075150090027875F000021E38AF82D4 +:1026500090027874AAF09002797403F090027AF0F4 +:1026600090027BEFF090027CE4F0757505F57690B2 +:102670000278F5F01228F6AF8290027DEFF0751423 +:102680000675150090027875F000021E38900278E9 +:1026900074AAF09002797401F090027A7404F075D3 +:1026A000750375760090027875F0001228F6AF82F7 +:1026B00090027BEFF075140475150090027875F0A8 +:1026C00000021E38AE82AF8390027874AAF09002A6 +:1026D00079740BF090027A7405F090027BE4F0902C +:1026E000027CF090027DF090027EF090027FF090EC +:1026F0000280F08E05900281EDF08F06900282EE4E +:10270000F0AF3B900283EFF0AF3C900284EFF075A6 +:10271000750D75760090027875F0001228F6AF827C +:10272000900285EFF075140E75150090027875F023 +:1027300000021E38AF8290027874AAF09002797479 +:1027400003F090027A23F090027BEFF090027CE499 +:10275000F0757505F576900278F5F01228F6AF82DF +:1027600090027DEFF075140675150090027875F0F3 +:1027700000021E38AF8290027874AAF09002797439 +:1027800003F090027A7407F090027BEFF090027CE5 +:10279000E4F0757505F576900278F5F01228F6AF3D +:1027A0008290027DEFF07514067515009002787521 +:1027B000F000021E38AF8290027874AAF09002797D +:1027C000741DF090027A7408F090027BEFF0AD3D3A +:1027D000AE3EAF3F7B047C008D828E838FF0123B38 +:1027E000A9FA601190027CEAF00DBD00010E0BBB4E +:1027F00000E60C80E38B068C07C3EE941FEF648029 +:1028000094805013EE2478F582EF3402F583E4F0DF +:102810000EBE00E50F80E275751F75760090027898 +:1028200075F0001228F6AF82900297EFF075142031 +:1028300075150090027875F000021E3890027874C9 +:10284000AAF09002797403F090027A740AF0900270 +:102850007BE4F090027CF0757505F576900278F5D2 +:10286000F01228F6AF8290027DEFF0751406751510 +:102870000090027875F000021E3890027874AAF079 +:102880009002797403F090027A740BF090027BE46A +:10289000F090027CF0757505F576900278F5F012EF +:1028A00028F6AF8290027DEFF07514067515009042 +:1028B000027875F000021E3890027874AAF0900237 +:1028C000797403F090027A740CF090027BE4F0903B +:1028D000027CF0757505F576900278F5F01228F611 +:1028E000AF8290027DEFF0751406751500900278A6 +:1028F00075F000021E3885827785837885F0797CB3 +:10290000007A007B00C3EA9575EB64808576F063FE +:10291000F08095F0501CEA2577F8EB3578F9AF791F +:10292000888289838FF0123BA92CFC0ABA00D60B4F +:1029300080D37455C39CF58222AF82439020439884 +:102940003F43A03F438807EF24F0500122EF2F9030 +:10295000295373801E801F80208021802280238045 +:102960002480258026802780288029802A802B802B +:102970002C802DC28822C28922C28A22C2A522C2EC +:10298000A422C2A322C2A222C2A122C2A022C29D0C +:1029900022C29C22C29B22C29A22C29922C298229F +:1029A000C29522E5F8C313FF530707E58854184F73 +:1029B00044E0F582225390DF5398C053A0C053885F +:1029C000F8221229CC122A1843A90222758C057507 +:1029D000A500758C4575A600758C8575BB00758C3A +:1029E000C5758D00758C0075E11C75E22E75E33F91 +:1029F00075E43F75E57875E68775E7FE75EE7875E1 +:102A0000D90E43F81043B0804380A043D11043E572 +:102A10008043E1A043E9402290FF9C7404F090FFC2 +:102A200098E4F090FF9D7404F090FF99E4F090FF1B +:102A30009E7404F090FF9AE4F075DE04F5DD75D520 +:102A400004F5D2F5C3F5CE75D604F5D3F5C4F5C1BA +:102A500075D704F5D4F5C5F5C290FFBD7404F090A8 +:102A6000FFA5E4F090FFEDF090FFD5F090FFBC746F +:102A700004F090FFA4E4F090FFECF090FFD4F0900D +:102A8000FFBB7404F090FFA3E4F090FFEBF090FF25 +:102A9000D3F090FFBA7404F090FFA2E4F090FFEA44 +:102AA000F090FFD2F090FFB97404F090FFA1E4F031 +:102AB00090FFE9F090FFD1F090FFB87404F090FF20 +:102AC000A0E4F090FFE8F090FFD0F090FFC3740412 +:102AD000F090FFABE4F090FFF3F090FFDBF090FF9D +:102AE000C27404F090FFAAE4F090FFF2F090FFDAD5 +:102AF000F090FFC17404F090FFA9E4F090FFF1F0B2 +:102B000090FFD9F090FFC07404F090FFA8E4F0901B +:102B1000FFF0F090FFD8F090FFBF7404F090FFA793 +:102B2000E4F090FFEFF090FFD7F090FFBE7404F058 +:102B300090FFA6E4F090FFEEF090FFD6F090FFC972 +:102B40007404F090FFB1E4F090FFF9F090FFE1F031 +:102B500022AF82BFA502800ABFA6028009BFA70ECE +:102B60008008900001229000022290000422900030 +:102B70000022AF82BFA8005003022C37EF243D5043 +:102B800003022C37EF2458FF240A83F582EF241F19 +:102B900083F583E473CBCFD3D7DBE7EFF3EBF7FB1E +:102BA000FF0B0F13171B1F2BDFE3232703072F3305 +:102BB0002B2B2B2B2B2B2B2B2B2B2B2B2C2C2C2C61 +:102BC0002C2C2C2B2B2C2C2C2C2C2C9000E22290FF +:102BD00000E9229000EA229000B5229000B62290EF +:102BE00000B3229000B4229000B7229000CC229033 +:102BF00000CD229001832290018A2290019222909E +:102C000001942290019F229001CB229002212290D8 +:102C10000223229002242290022522900226229052 +:102C200002272290006F229000702290022A2290A8 +:102C3000029F229002A02290000022A28DE43390F5 +:102C400002A4F0A28EE4339002A5F0229002A4E048 +:102C5000FFA28DE433FEEFB50602803EA28DE43381 +:102C60009002A4F09002A4E0FF601ABF012C7489C6 +:102C7000C0E0743EC0E07480C0E01234411581159C +:102C800081158180157494C0E0743EC0E07480C0EA +:102C9000E01234411581158115819002A5E0FFA253 +:102CA0008EE433FEEFB5060122A28EE4339002A536 +:102CB000F09002A5E0FF6019BF012B749EC0E07484 +:102CC0003EC0E07480C0E012344115811581158149 +:102CD0002274A9C0E0743EC0E07480C0E0123441A8 +:102CE00015811581158122AE82AF83BE4005BF7E5E +:102CF000028024BE4105BF7E028010BE4205BF7E19 +:102D000002800CBE4315BF7E128008900001229005 +:102D1000000222900003229000002290FFFF22AECA +:102D200082AF838E048F05BC4005BD7E028016BC39 +:102D30004105BD7E02800EBC4205BD7E028006BC00 +:102D40004317BD7E149002A4E0700A8E828F831216 +:102D50002CE71222C77582002275820122AE82AF53 +:102D6000839002A4E0FD600ABD010E8E828F830273 +:102D7000110E8E828F8302205522AE82AF83900285 +:102D8000A4E0FD600ABD010E8E828F8302114B8E7E +:102D9000828F8302213722AE82AF839002A4E0FDAE +:102DA000600ABD010E8E828F830211888E828F830E +:102DB000022213229002A4E0701FAE1AAF1BC3744C +:102DC000209E744E9F5012C2AF90006175F00012A9 +:102DD000224CE4F51AF51BD2AF051AE4B51A020528 +:102DE0001B220230B15380E35390F153B0875388D4 +:102DF0007F53C0010230FD85824385834485F045C1 +:102E0000E5427016AC4174F42C400A0540E4B5402C +:102E10000905418005E4F540F541E4FBFCF9FAF5CC +:102E200046F54785404885414974FC2549404AA8F4 +:102E30004874042549FF5307078882EF24FCF58373 +:102E4000C002C001123329AE82AF83E4C39EF546AF +:102E500074049FF547AE40AF415307078E82EF24BD +:102E6000FCF583123329AE82AF83D001D002E4C3D4 +:102E70009EFB74049FFC022F1474F825494046AE53 +:102E800048740755498E8224FCF583123329AE829B +:102E9000AF83E4C39EFB74049FFCAE40AF41740457 +:102EA0002FFF5307078E82EF24FCF583C004C00375 +:102EB000123329AE82AF83D003D004E4C39EF974E9 +:102EC000049FFA804FAE4874042549FF5307078ECC +:102ED00082EF24FCF583C004C003123329AE82AF15 +:102EE00083E4C39EF974049FFAAE40AF41530707D1 +:102EF0008E82EF24FCF583C002C001123329AE821A +:102F0000AF83D001D002D003D004E4C39EF5467451 +:102F1000049FF5478543828544838545F0123BA98C +:102F2000FF30E0047B007C04EF30E10479007A0498 +:102F3000EF30E20675460075470474012543FDE451 +:102F40003544FEAF458D828E838FF0123BA9FF7012 +:102F500009FBFCF9FA8C46754704BF010D7B007C28 +:102F60000079007A04E4F546F547BF020D79007A4E +:102F7000007B007C04E4F546F547BF030D79007A39 +:102F8000047B007C04E4F546F547AE427F0075758E +:102F9000038F768E828F83C004C003C002C00112EB +:102FA0003BC5AE82AF83D001D002D003D004BE00B7 +:102FB00005BF00028010BE0105BF0002801ABE02DC +:102FC0003BBF00388024D284D2C7D282D2B5D2B4DB +:102FD000D2918B068C078028D2C1D2C2D2C3D2C470 +:102FE000D2C5D29289068A078016D283D2C6D28FE2 +:102FF000D2B6D2B3D293AE46AF4780047E007F00F4 +:103000008E828F831230167582002290FF80E053EB +:10301000E0DFF00230B1AE82AF83E4C39EFE740401 +:103020009FFD8DC38ECE8DC48EC18DC58EC290FF87 +:10303000EDEDF090FFD5EEF090FFECEDF090FFD4C9 +:10304000EEF090FFEBEDF090FFD3EEF090FFEAEDA5 +:10305000F090FFD2EEF090FFE9EDF090FFD1EEF0AE +:1030600090FFE8EDF090FFD0EEF090FFF3EDF090E0 +:10307000FFDBEEF090FFF2EDF090FFDAEEF090FF64 +:10308000F1EDF090FFD9EEF090FFF0EDF090FFD869 +:10309000EEF090FFEFEDF090FFD7EEF090FFEEED49 +:1030A000F090FFD6EEF090FFF9EDF090FFE1EEF03A +:1030B0002290FF8074CAF090FF817408F090FF8224 +:1030C000F090FF83F090FF84F090FF85F090FF86F2 +:1030D000748AF090FF877408F090FF88F090FF8961 +:1030E000F090FF8AF090FF8BF090FF8C748AF09044 +:1030F000FF917408F075DA8AF5DBF5DC2290FF8029 +:103100007402F090FF81E4F090FF82F090FF83F072 +:1031100090FF84F090FF85F090FF867402F090FF9E +:1031200087E4F090FF88F090FF89F090FF8AF0909C +:10313000FF8BF090FF8C7402F090FF91E4F075DA51 +:1031400002F5DBF5DC22AF82BFA502800ABFA60232 +:103150008009BFA70E8008900001229000022290F3 +:1031600000042290000022AF82BFA8005003023268 +:103170002CEF243D500302322CEF2458FF240A8305 +:10318000F582EF241F83F583E473C0C4C8CCD0DC80 +:10319000E4E8E0ECF0F40004080C101420D4D81893 +:1031A0001CF8FC24283131313131313131313131A8 +:1031B00031323232323232323131323231313232F4 +:1031C0009000E2229000E9229000EA229000B522CD +:1031D0009000B6229000B3229000B4229000B72253 +:1031E0009000CC229000CD229001832290018A226F +:1031F000900192229001942290019F229001CB2273 +:103200009002212290022322900224229002252261 +:10321000900226229002272290006F2290007022B6 +:1032200090022A2290029F229002A0229000002267 +:10323000AE82AF83BE445FBF7E5CE51C602B120E86 +:1032400087E5825422601175123590002575F000D3 +:10325000120DCC120A00803A75122990002575F0E3 +:1032600000120DCC120A008029120E87E58254222A +:10327000601175133590002575F000120E04120AC6 +:1032800000800F75132990002575F000120E0412AE +:103290000A007582002275820122AD82AE83AFF0F2 +:1032A0008D7A8E7B8F7C85757D85767E85777FA8F0 +:1032B00078A9798803890418B8FF0119EB4C6025B7 +:1032C000857D82857E83857FF0123BA9FCA3858264 +:1032D0007D85837E8D828E838FF0EC12330EA3ADBD +:1032E00082AE8380CE857A82857B83857CF022AC1A +:1032F00082AD83AE76AF77BE0004EF600C1F0FE5A2 +:103300007512330EA3DEFADFF88C828D832220F74C +:103310001130F6138883A88220F509F6A8837583F7 +:10332000002280FEF280F5F022E58330E707638219 +:10333000FF6383FFA322E575457660467A01E57554 +:1033400025E0F575E576334012F576E5829575E56D +:1033500083957640030A80E6C3E57613F576E57536 +:1033600013F575C3E5829575F5F0E583957640050F +:10337000F58385F082C3E57613F576E57513F5756B +:10338000DAE12285827A85837B85F07CE578457950 +:10339000700490000022AB78AC791BBBFF011CEBE2 +:1033A0004C6048A87AA97BAA7C888289838AF0121B +:1033B0003BA9FF85757D85767E85777F857D8285B6 +:1033C0007E83857FF0123BA9FEEFB5061E08B8008C +:1033D0000109887A897B8A7C7401257DFDE4357E2C +:1033E000FEAF7F8D758E768F7780AFAD7AAE7BAF77 +:1033F0007C8D828E838FF0123BA9FD7F00AB75AC74 +:1034000076AE778B828C838EF0123BA9FB7E00ED2B +:10341000C39BF582EF9EF58322C01E85811E7E0030 +:103420008E83120FE8D01E2285825A85835B85F039 +:103430005CE4F557F558F559851D5D903419023552 +:1034400002C01EE581F51E24FBFF8F5DE4F557F5F4 +:1034500058F559E51E24FBF8865A08865B08865CF9 +:10346000903419123502D01E22AF82C04DC04EC01A +:103470004F1234768007C04BC04C8F8222158115C5 +:103480008115810555E4B55502055622AF82743089 +:103490002FFF24C6500B74072FFFE54A6003430734 +:1034A000208F82023469E582FFC4540FF582C00781 +:1034B00012348CD007740F5FF58202348C858275CC +:1034C000AB50AC51AD52AE53AA547577208A07EF7A +:1034D0002FF576EE2354014576FAEB2BFBEC33FC0B +:1034E000ED33FDEE33FEC3EA95754008EAC39575EA +:1034F000FA430301D577D68B508C518D528E538A67 +:10350000542285824B85834C85574D85584E85596D +:103510004FE4F555F556AD5AAE5BAF5C8D828E83A8 +:103520008FF0123BA9FC74012DF55AE43EF55B8F38 +:103530005CECFF7003023B6DBF25028003023B651C +:10354000E4F55EF55FF560F561F562F563F564F548 +:1035500065F567F568F569756AFF756BFFAC5AAD7F +:103560005BAE5C8C828D838EF0123BA9F56FA3ACB1 +:1035700082AD838C5A8D5B8E5C7425B56F08856F28 +:1035800082123469809074D0256F4003023627E59B +:103590006F24C6500302362774FFB56A4BB56B48DB +:1035A000C004C005C00685687585697690000AC0AC +:1035B00006C005C004123B8CAA82AB83D004D005A0 +:1035C000D006AE6F7D00EE2AFAED3BFBEA24D0F583 +:1035D00068EB34FFF569E5684569D006D005D0048D +:1035E0007081755F01023563C004C005C006856A3D +:1035F00075856B7690000AC006C005C004123B8C2E +:10360000AA82AB83D004D005D006AD6F7E00ED2A30 +:10361000FAEE3BFBEA24D0F56AEB34FFF56BD006FB +:10362000D005D004023563742EB56F1574FFB56AEA +:1036300005B56B028003023563E4F56AF56B02356C +:1036400063749F256F500EE56F24854008536FDF2C +:10365000754A018003754A007420B56F030236F481 +:10366000742BB56F030236EE742DB56F028079743A +:1036700042B56F030236FA7443B56F03023706741E +:1036800044B56F030238957446B56F030238AC74C5 +:1036900048B56F030235637449B56F0302389574FA +:1036A0004AB56F03023563744CB56F028052744F94 +:1036B000B56F0302389D7450B56F0302382A7453F6 +:1036C000B56F0280627454B56F030235637455B5EB +:1036D0006F030238A27458B56F030238A7745AB545 +:1036E0006F030235630238B1755E010235637560A0 +:1036F000010235637561010235637563010235634B +:10370000756401023563E563600AE55D14F9895D5E +:103710008706800BE55D24FEFD8D5D8D0187068E9D +:10372000821234690238BDE55D24FDFE8E5D8E0196 +:10373000870409870509870619198C508D518E5207 +:103740008C828D838EF0123B7485827085837174B8 +:10375000FFB56A09B56B0685706A85716BE55E70A9 +:103760003DC3E5709568E57195695032E568C3958C +:1037700070F568E5699571F569AC68AB698C028B89 +:10378000061CBCFF011BEA4E6010758220C004C0FD +:1037900003123469D003D00480E38C688B69AD6A6E +:1037A000AE6B8550828551838552F0123BA9FB6038 +:1037B00033C3E49D74808EF063F08095F050251D36 +:1037C000BDFF011E8B82C006C005123469D005D032 +:1037D00006AA50AB51AC520ABA00010B8A508B5169 +:1037E0008C5280BEE55E70030238BDC3E5709568FB +:1037F000E571956940030238BDE568C39570F568C9 +:10380000E5699571F569AE68AD698E038D041EBEDC +:10381000FF011DEB4C70030238B9758220C006C051 +:1038200005123469D005D00680E0E55D24FDFC8CEE +:103830005D8C01870209870309870419198A508B57 +:10384000518C52AC52BC800040047B438014BC605D +:103850000040047B50800BBC400040047B49800248 +:103860007B588B82C00312346975823A12346975B1 +:103870008230123469758278123469D003BB4902F0 +:10388000800BBB500280068551821234A68550827F +:103890001234A6802875620175670A802075670852 +:1038A000801B75670A801675671080117565018029 +:1038B0000C856F8212346980048E688D69E56560BD +:1038C0005BE55D24FCFE8E5D8E018703098704099C +:1038D00087050987061919198B508C518D528E5303 +:1038E000755034755141755280855072855173857C +:1038F000527474012572FAE43573FBAE748A508BEE +:10390000518E528572828573838574F0123BA9FDB6 +:1039100070030235168D8212346980CDE56770031D +:10392000023516E5636029E55D14F9895D87067D3A +:10393000007C007B008E508D518C528B53E5627061 +:1039400063AB50FCFDFE8B508C518D528E538054D6 +:10395000E5646021E55D24FCFE8E5D8E0187030930 +:1039600087040987050987061919198B508C518D11 +:10397000528E53802FE55D24FEFE8E5D8E018705FD +:1039800009870619EE3395E0FCFB8D508E518C5261 +:103990008B53E562700EAB50AC51FDFE8B508C51D9 +:1039A0008D528E53E5626023E55330E71BC3E495E7 +:1039B00050FBE49551FCE49552FDE49553FE8B5089 +:1039C0008C518D528E538003756200756601798526 +:1039D0007D007E00755400856782C006C005C00169 +:1039E0001234BDD001D005D006E5667013E554C48D +:1039F00054F0FCE554C4540F4204E74CF71980021C +:103A0000A7540DBD00010EE566B40100E433F56670 +:103A1000E55045514552455370BA896E8D6C8E6D97 +:103A2000E56845697005756801F569E55F702DE524 +:103A30005E7029AA68AB69AC6C0C7E00C3EC9AEE90 +:103A40009B5015758220C003C002123469D002D089 +:103A5000031ABAFF011B80DF8A688B69E562601177 +:103A600075822D123469156874FFB5680215698076 +:103A70002EE56C456D6028E560601175822B12346F +:103A800069156874FFB5680215698013E561600FF8 +:103A9000758220123469156874FFB568021569E5EE +:103AA0005E702FAE68AD698E038D041EBEFF011DD2 +:103AB000C3E56C9BE56D9C503AE55F60047C30800B +:103AC000027C208C82C006C005123469D005D00665 +:103AD00080D5C3E56C9568E56D9569500FE568C3C1 +:103AE000956CF568E569956DF569800BE4F568F509 +:103AF0006980048E688D69A96EAD6CAE6D8D038E84 +:103B0000041DBDFF011EEB4C6030E566B40100E40E +:103B100033F566700A09E7C4540FFC8C548007879C +:103B200004740F5CF554855482C006C005C00112B0 +:103B3000348CD001D005D00680C3E55E7003023519 +:103B400016AD68AE698D038E041DBDFF011EEB4CE2 +:103B50007003023516758220C006C005123469D084 +:103B600005D00680E08F82123469023516855582B1 +:103B700085568322AA82AB83123BA96003A380F8F7 +:103B8000C3E5829AF582E5839BF58322E5828575FC +:103B9000F0A4C582C0F08576F0A4D0F025F0C583EE +:103BA0008575F0A42583F5832220F71430F6148858 +:103BB00083A88220F507E6A88375830022E280F7B8 +:103BC000E49322E022C2D5E58330E70DD2D5E4C3E9 +:103BD0009582F582E49583F583E57630E70BE4C3BF +:103BE0009575F575E49576F57612333630D50BE498 +:103BF000C39582F582E49583F58322758200225372 +:103C00004D4B2076616C7068610D0A004445564941 +:103C10004345207649643A307830356163207049F5 +:103C2000643A3078303234660A0D004B45593A20F8 +:103C30003078253034782025730D0A005550004423 +:103C40004F574E004348414E474544204C4159454B +:103C5000523A2025640D0A00554E5245434F474EB7 +:103C6000495A4544204B45593A203078253034781C +:103C70000D0A006164645F6B65795F6269743A2064 +:103C800063616E2774206164643A20253032580ADB +:103C90000064656C5F6B65795F6269743A2063618B +:103CA0006E27742064656C3A20253032580A00056E +:103CB000010906A101050719E029E715002501758D +:103CC00001950881027508950181010507190029F0 +:103CD000FF150026FF0075089506810005081901EB +:103CE00029051500250175019505910275039501BA +:103CF0009101C005010980A1018501198129831560 +:103D000000250175019503810295058101C0050C0F +:103D10000901A101850219002A3C021500263C0276 +:103D2000751095018100C00600FF0901A1018505FC +:103D300019012902150026FF0075089505B102C07A +:103D400005010906A1018506050719E029E7150007 +:103D5000250175019508810205071900299F1500A5 +:103D60002501750195A08102C0120110010000001B +:103D700008AC054F02000001020301090400000124 +:103D800003010100092111010001224400070581FE +:103D900003100001090401000103000000092111C2 +:103DA000010001227600070582034000010902009C +:103DB00000020100A0FA7B3D843D8D3D943D9D3D78 +:103DC000A63D0000AD3D04030904273E3E3E4B3EA8 +:103DD000693D000001C43D03CA3D2573206275663C +:103DE00066657220746F6F206C6F6E673A20256471 +:103DF000007365745F6570305F696E5F62756666DB +:103E00006572007365745F6570315F696E5F6275BE +:103E100066666572007365745F6570325F696E5FB8 +:103E200062756666657200636F6E74616374406389 +:103E300061726C6F73736C6573732E696F00534D91 +:103E40004B204B6579626F61726400303030310015 +:103E5000697320626C616E6B3A2025640D0A0072F2 +:103E600066206C696E6B206368616E6765643A20DA +:103E700025640D0A00534D4B204254352E3000531B +:103E80004D4B204254332E30005553425F4D4F442A +:103E9000450D0A0052465F4D4F44450D0A004D4105 +:103EA000435F4D4F44450D0A0057494E5F4D4F4407 +:103EB000450D0A00447E1E001F0020002100220044 +:103EC000230024002500260027002D002E002A00B4 +:103ED000000000002B0014001A0008001500170055 +:103EE0001C0018000C00120013002F0030003100DD +:103EF00000000000390004001600070009000A0055 +:103F00000B000D000E000F003300340000002800ED +:103F100000000000E1001D001B0006001900050064 +:103F20001100100036003700380000000000E500E6 +:103F300052004C00E000E300E200000000002C0012 +:103F400000000000E3002252500000000000510079 +:103F50004F000000447E1E001F00200021002200B0 +:103F6000230024002500260027002D002E002A0013 +:103F7000000000002B0014001A00080015001700B4 +:103F80001C0018000C00120013002F00300031003C +:103F900000000000390004001600070009000A00B4 +:103FA0000B000D000E000F0033003400000028004D +:103FB00000000000E1001D001B00060019000500C4 +:103FC0001100100036003700380000000000E50046 +:103FD00052004C00E000E200E300000000002C0072 +:103FE00000000000E30023525000000000005100D8 +:103FF0004F0000003500BE00BD00C100C0000378C6 +:104000000478BC00AE00BB00A800AA00A9004C00C8 +:10401000000000000100417E427E437E407E0100A0 +:104020000100010001000100010001000100010088 +:10403000000000000100010001000100010001007A +:104040000100010001000100010001000000010069 +:10405000000000000100010001000100010001005A +:10406000010001000100010001000000000001004A +:10407000010001000100010001000000000001003A +:10408000000000000100010001000000000001002C +:104090000100000035003A003B003C003D003E00BE +:1040A0003F004000410042004300440045004C00F6 +:1040B000000000000100417E427E437E407E010000 +:1040C00001000100010001000100010001000100E8 +:1040D00000000000010001000100010001000100DA +:1040E00001000100010001000100010000000100C9 +:1040F00000000000010001000100010001000100BA +:1041000001000100010001000100000000000100A9 +:104110000100010001000100010000000000010099 +:10412000000000000100010001000000000001008B +:10413000010000003C4E4F20464C4F41543E0000D1 +:10414000000000000000000000000000000000006F +:10415000000000000000000000000000000000005F +:10416000000000000000000000000000000000004F +:10417000000000000000000000000000000000003F +:10418000000000000000000000000000000000002F +:10419000000000000000000000000000000000001F +:1041A000000000000000000000000000000000000F +:1041B00000000000000000000000000000000000FF +:1041C00000000000000000000000000000000000EF +:1041D00000000000000000000000000000000000DF +:1041E00000000000000000000000000000000000CF +:1041F00000000000000000000000000000000000BF +:1042000000000000000000000000000000000000AE +:10421000000000000000000000000000000000009E +:10422000000000000000000000000000000000008E +:10423000000000000000000000000000000000007E +:10424000000000000000000000000000000000006E +:10425000000000000000000000000000000000005E +:10426000000000000000000000000000000000004E +:10427000000000000000000000000000000000003E +:10428000000000000000000000000000000000002E +:10429000000000000000000000000000000000001E +:1042A000000000000000000000000000000000000E +:1042B00000000000000000000000000000000000FE +:1042C00000000000000000000000000000000000EE +:1042D00000000000000000000000000000000000DE +:1042E00000000000000000000000000000000000CE +:1042F00000000000000000000000000000000000BE +:1043000000000000000000000000000000000000AD +:10431000000000000000000000000000000000009D +:10432000000000000000000000000000000000008D +:10433000000000000000000000000000000000007D +:10434000000000000000000000000000000000006D +:10435000000000000000000000000000000000005D +:10436000000000000000000000000000000000004D +:10437000000000000000000000000000000000003D +:10438000000000000000000000000000000000002D +:10439000000000000000000000000000000000001D +:1043A000000000000000000000000000000000000D +:1043B00000000000000000000000000000000000FD +:1043C00000000000000000000000000000000000ED +:1043D00000000000000000000000000000000000DD +:1043E00000000000000000000000000000000000CD +:1043F00000000000000000000000000000000000BD +:1044000000000000000000000000000000000000AC +:10441000000000000000000000000000000000009C +:10442000000000000000000000000000000000008C +:10443000000000000000000000000000000000007C +:10444000000000000000000000000000000000006C +:10445000000000000000000000000000000000005C +:10446000000000000000000000000000000000004C +:10447000000000000000000000000000000000003C +:10448000000000000000000000000000000000002C +:10449000000000000000000000000000000000001C +:1044A000000000000000000000000000000000000C +:1044B00000000000000000000000000000000000FC +:1044C00000000000000000000000000000000000EC +:1044D00000000000000000000000000000000000DC +:1044E00000000000000000000000000000000000CC +:1044F00000000000000000000000000000000000BC +:1045000000000000000000000000000000000000AB +:10451000000000000000000000000000000000009B +:10452000000000000000000000000000000000008B +:10453000000000000000000000000000000000007B +:10454000000000000000000000000000000000006B +:10455000000000000000000000000000000000005B +:10456000000000000000000000000000000000004B +:10457000000000000000000000000000000000003B +:10458000000000000000000000000000000000002B +:10459000000000000000000000000000000000001B +:1045A000000000000000000000000000000000000B +:1045B00000000000000000000000000000000000FB +:1045C00000000000000000000000000000000000EB +:1045D00000000000000000000000000000000000DB +:1045E00000000000000000000000000000000000CB +:1045F00000000000000000000000000000000000BB +:1046000000000000000000000000000000000000AA +:10461000000000000000000000000000000000009A +:10462000000000000000000000000000000000008A +:10463000000000000000000000000000000000007A +:10464000000000000000000000000000000000006A +:10465000000000000000000000000000000000005A +:10466000000000000000000000000000000000004A +:10467000000000000000000000000000000000003A +:10468000000000000000000000000000000000002A +:10469000000000000000000000000000000000001A +:1046A000000000000000000000000000000000000A +:1046B00000000000000000000000000000000000FA +:1046C00000000000000000000000000000000000EA +:1046D00000000000000000000000000000000000DA +:1046E00000000000000000000000000000000000CA +:1046F00000000000000000000000000000000000BA +:1047000000000000000000000000000000000000A9 +:104710000000000000000000000000000000000099 +:104720000000000000000000000000000000000089 +:104730000000000000000000000000000000000079 +:104740000000000000000000000000000000000069 +:104750000000000000000000000000000000000059 +:104760000000000000000000000000000000000049 +:104770000000000000000000000000000000000039 +:104780000000000000000000000000000000000029 +:104790000000000000000000000000000000000019 +:1047A0000000000000000000000000000000000009 +:1047B00000000000000000000000000000000000F9 +:1047C00000000000000000000000000000000000E9 +:1047D00000000000000000000000000000000000D9 +:1047E00000000000000000000000000000000000C9 +:1047F00000000000000000000000000000000000B9 +:1048000000000000000000000000000000000000A8 +:104810000000000000000000000000000000000098 +:104820000000000000000000000000000000000088 +:104830000000000000000000000000000000000078 +:104840000000000000000000000000000000000068 +:104850000000000000000000000000000000000058 +:104860000000000000000000000000000000000048 +:104870000000000000000000000000000000000038 +:104880000000000000000000000000000000000028 +:104890000000000000000000000000000000000018 +:1048A0000000000000000000000000000000000008 +:1048B00000000000000000000000000000000000F8 +:1048C00000000000000000000000000000000000E8 +:1048D00000000000000000000000000000000000D8 +:1048E00000000000000000000000000000000000C8 +:1048F00000000000000000000000000000000000B8 +:1049000000000000000000000000000000000000A7 +:104910000000000000000000000000000000000097 +:104920000000000000000000000000000000000087 +:104930000000000000000000000000000000000077 +:104940000000000000000000000000000000000067 +:104950000000000000000000000000000000000057 +:104960000000000000000000000000000000000047 +:104970000000000000000000000000000000000037 +:104980000000000000000000000000000000000027 +:104990000000000000000000000000000000000017 +:1049A0000000000000000000000000000000000007 +:1049B00000000000000000000000000000000000F7 +:1049C00000000000000000000000000000000000E7 +:1049D00000000000000000000000000000000000D7 +:1049E00000000000000000000000000000000000C7 +:1049F00000000000000000000000000000000000B7 +:104A000000000000000000000000000000000000A6 +:104A10000000000000000000000000000000000096 +:104A20000000000000000000000000000000000086 +:104A30000000000000000000000000000000000076 +:104A40000000000000000000000000000000000066 +:104A50000000000000000000000000000000000056 +:104A60000000000000000000000000000000000046 +:104A70000000000000000000000000000000000036 +:104A80000000000000000000000000000000000026 +:104A90000000000000000000000000000000000016 +:104AA0000000000000000000000000000000000006 +:104AB00000000000000000000000000000000000F6 +:104AC00000000000000000000000000000000000E6 +:104AD00000000000000000000000000000000000D6 +:104AE00000000000000000000000000000000000C6 +:104AF00000000000000000000000000000000000B6 +:104B000000000000000000000000000000000000A5 +:104B10000000000000000000000000000000000095 +:104B20000000000000000000000000000000000085 +:104B30000000000000000000000000000000000075 +:104B40000000000000000000000000000000000065 +:104B50000000000000000000000000000000000055 +:104B60000000000000000000000000000000000045 +:104B70000000000000000000000000000000000035 +:104B80000000000000000000000000000000000025 +:104B90000000000000000000000000000000000015 +:104BA0000000000000000000000000000000000005 +:104BB00000000000000000000000000000000000F5 +:104BC00000000000000000000000000000000000E5 +:104BD00000000000000000000000000000000000D5 +:104BE00000000000000000000000000000000000C5 +:104BF00000000000000000000000000000000000B5 +:104C000000000000000000000000000000000000A4 +:104C10000000000000000000000000000000000094 +:104C20000000000000000000000000000000000084 +:104C30000000000000000000000000000000000074 +:104C40000000000000000000000000000000000064 +:104C50000000000000000000000000000000000054 +:104C60000000000000000000000000000000000044 +:104C70000000000000000000000000000000000034 +:104C80000000000000000000000000000000000024 +:104C90000000000000000000000000000000000014 +:104CA0000000000000000000000000000000000004 +:104CB00000000000000000000000000000000000F4 +:104CC00000000000000000000000000000000000E4 +:104CD00000000000000000000000000000000000D4 +:104CE00000000000000000000000000000000000C4 +:104CF00000000000000000000000000000000000B4 +:104D000000000000000000000000000000000000A3 +:104D10000000000000000000000000000000000093 +:104D20000000000000000000000000000000000083 +:104D30000000000000000000000000000000000073 +:104D40000000000000000000000000000000000063 +:104D50000000000000000000000000000000000053 +:104D60000000000000000000000000000000000043 +:104D70000000000000000000000000000000000033 +:104D80000000000000000000000000000000000023 +:104D90000000000000000000000000000000000013 +:104DA0000000000000000000000000000000000003 +:104DB00000000000000000000000000000000000F3 +:104DC00000000000000000000000000000000000E3 +:104DD00000000000000000000000000000000000D3 +:104DE00000000000000000000000000000000000C3 +:104DF00000000000000000000000000000000000B3 +:104E000000000000000000000000000000000000A2 +:104E10000000000000000000000000000000000092 +:104E20000000000000000000000000000000000082 +:104E30000000000000000000000000000000000072 +:104E40000000000000000000000000000000000062 +:104E50000000000000000000000000000000000052 +:104E60000000000000000000000000000000000042 +:104E70000000000000000000000000000000000032 +:104E80000000000000000000000000000000000022 +:104E90000000000000000000000000000000000012 +:104EA0000000000000000000000000000000000002 +:104EB00000000000000000000000000000000000F2 +:104EC00000000000000000000000000000000000E2 +:104ED00000000000000000000000000000000000D2 +:104EE00000000000000000000000000000000000C2 +:104EF00000000000000000000000000000000000B2 +:104F000000000000000000000000000000000000A1 +:104F10000000000000000000000000000000000091 +:104F20000000000000000000000000000000000081 +:104F30000000000000000000000000000000000071 +:104F40000000000000000000000000000000000061 +:104F50000000000000000000000000000000000051 +:104F60000000000000000000000000000000000041 +:104F70000000000000000000000000000000000031 +:104F80000000000000000000000000000000000021 +:104F90000000000000000000000000000000000011 +:104FA0000000000000000000000000000000000001 +:104FB00000000000000000000000000000000000F1 +:104FC00000000000000000000000000000000000E1 +:104FD00000000000000000000000000000000000D1 +:104FE00000000000000000000000000000000000C1 +:104FF00000000000000000000000000000000000B1 +:1050000000000000000000000000000000000000A0 +:105010000000000000000000000000000000000090 +:105020000000000000000000000000000000000080 +:105030000000000000000000000000000000000070 +:105040000000000000000000000000000000000060 +:105050000000000000000000000000000000000050 +:105060000000000000000000000000000000000040 +:105070000000000000000000000000000000000030 +:105080000000000000000000000000000000000020 +:105090000000000000000000000000000000000010 +:1050A0000000000000000000000000000000000000 +:1050B00000000000000000000000000000000000F0 +:1050C00000000000000000000000000000000000E0 +:1050D00000000000000000000000000000000000D0 +:1050E00000000000000000000000000000000000C0 +:1050F00000000000000000000000000000000000B0 +:10510000000000000000000000000000000000009F +:10511000000000000000000000000000000000008F +:10512000000000000000000000000000000000007F +:10513000000000000000000000000000000000006F +:10514000000000000000000000000000000000005F +:10515000000000000000000000000000000000004F +:10516000000000000000000000000000000000003F +:10517000000000000000000000000000000000002F +:10518000000000000000000000000000000000001F +:10519000000000000000000000000000000000000F +:1051A00000000000000000000000000000000000FF +:1051B00000000000000000000000000000000000EF +:1051C00000000000000000000000000000000000DF +:1051D00000000000000000000000000000000000CF +:1051E00000000000000000000000000000000000BF +:1051F00000000000000000000000000000000000AF +:10520000000000000000000000000000000000009E +:10521000000000000000000000000000000000008E +:10522000000000000000000000000000000000007E +:10523000000000000000000000000000000000006E +:10524000000000000000000000000000000000005E +:10525000000000000000000000000000000000004E +:10526000000000000000000000000000000000003E +:10527000000000000000000000000000000000002E +:10528000000000000000000000000000000000001E +:10529000000000000000000000000000000000000E +:1052A00000000000000000000000000000000000FE +:1052B00000000000000000000000000000000000EE +:1052C00000000000000000000000000000000000DE +:1052D00000000000000000000000000000000000CE +:1052E00000000000000000000000000000000000BE +:1052F00000000000000000000000000000000000AE +:10530000000000000000000000000000000000009D +:10531000000000000000000000000000000000008D +:10532000000000000000000000000000000000007D +:10533000000000000000000000000000000000006D +:10534000000000000000000000000000000000005D +:10535000000000000000000000000000000000004D +:10536000000000000000000000000000000000003D +:10537000000000000000000000000000000000002D +:10538000000000000000000000000000000000001D +:10539000000000000000000000000000000000000D +:1053A00000000000000000000000000000000000FD +:1053B00000000000000000000000000000000000ED +:1053C00000000000000000000000000000000000DD +:1053D00000000000000000000000000000000000CD +:1053E00000000000000000000000000000000000BD +:1053F00000000000000000000000000000000000AD +:10540000000000000000000000000000000000009C +:10541000000000000000000000000000000000008C +:10542000000000000000000000000000000000007C +:10543000000000000000000000000000000000006C +:10544000000000000000000000000000000000005C +:10545000000000000000000000000000000000004C +:10546000000000000000000000000000000000003C +:10547000000000000000000000000000000000002C +:10548000000000000000000000000000000000001C +:10549000000000000000000000000000000000000C +:1054A00000000000000000000000000000000000FC +:1054B00000000000000000000000000000000000EC +:1054C00000000000000000000000000000000000DC +:1054D00000000000000000000000000000000000CC +:1054E00000000000000000000000000000000000BC +:1054F00000000000000000000000000000000000AC +:10550000000000000000000000000000000000009B +:10551000000000000000000000000000000000008B +:10552000000000000000000000000000000000007B +:10553000000000000000000000000000000000006B +:10554000000000000000000000000000000000005B +:10555000000000000000000000000000000000004B +:10556000000000000000000000000000000000003B +:10557000000000000000000000000000000000002B +:10558000000000000000000000000000000000001B +:10559000000000000000000000000000000000000B +:1055A00000000000000000000000000000000000FB +:1055B00000000000000000000000000000000000EB +:1055C00000000000000000000000000000000000DB +:1055D00000000000000000000000000000000000CB +:1055E00000000000000000000000000000000000BB +:1055F00000000000000000000000000000000000AB +:10560000000000000000000000000000000000009A +:10561000000000000000000000000000000000008A +:10562000000000000000000000000000000000007A +:10563000000000000000000000000000000000006A +:10564000000000000000000000000000000000005A +:10565000000000000000000000000000000000004A +:10566000000000000000000000000000000000003A +:10567000000000000000000000000000000000002A +:10568000000000000000000000000000000000001A +:10569000000000000000000000000000000000000A +:1056A00000000000000000000000000000000000FA +:1056B00000000000000000000000000000000000EA +:1056C00000000000000000000000000000000000DA +:1056D00000000000000000000000000000000000CA +:1056E00000000000000000000000000000000000BA +:1056F00000000000000000000000000000000000AA +:105700000000000000000000000000000000000099 +:105710000000000000000000000000000000000089 +:105720000000000000000000000000000000000079 +:105730000000000000000000000000000000000069 +:105740000000000000000000000000000000000059 +:105750000000000000000000000000000000000049 +:105760000000000000000000000000000000000039 +:105770000000000000000000000000000000000029 +:105780000000000000000000000000000000000019 +:105790000000000000000000000000000000000009 +:1057A00000000000000000000000000000000000F9 +:1057B00000000000000000000000000000000000E9 +:1057C00000000000000000000000000000000000D9 +:1057D00000000000000000000000000000000000C9 +:1057E00000000000000000000000000000000000B9 +:1057F00000000000000000000000000000000000A9 +:105800000000000000000000000000000000000098 +:105810000000000000000000000000000000000088 +:105820000000000000000000000000000000000078 +:105830000000000000000000000000000000000068 +:105840000000000000000000000000000000000058 +:105850000000000000000000000000000000000048 +:105860000000000000000000000000000000000038 +:105870000000000000000000000000000000000028 +:105880000000000000000000000000000000000018 +:105890000000000000000000000000000000000008 +:1058A00000000000000000000000000000000000F8 +:1058B00000000000000000000000000000000000E8 +:1058C00000000000000000000000000000000000D8 +:1058D00000000000000000000000000000000000C8 +:1058E00000000000000000000000000000000000B8 +:1058F00000000000000000000000000000000000A8 +:105900000000000000000000000000000000000097 +:105910000000000000000000000000000000000087 +:105920000000000000000000000000000000000077 +:105930000000000000000000000000000000000067 +:105940000000000000000000000000000000000057 +:105950000000000000000000000000000000000047 +:105960000000000000000000000000000000000037 +:105970000000000000000000000000000000000027 +:105980000000000000000000000000000000000017 +:105990000000000000000000000000000000000007 +:1059A00000000000000000000000000000000000F7 +:1059B00000000000000000000000000000000000E7 +:1059C00000000000000000000000000000000000D7 +:1059D00000000000000000000000000000000000C7 +:1059E00000000000000000000000000000000000B7 +:1059F00000000000000000000000000000000000A7 +:105A00000000000000000000000000000000000096 +:105A10000000000000000000000000000000000086 +:105A20000000000000000000000000000000000076 +:105A30000000000000000000000000000000000066 +:105A40000000000000000000000000000000000056 +:105A50000000000000000000000000000000000046 +:105A60000000000000000000000000000000000036 +:105A70000000000000000000000000000000000026 +:105A80000000000000000000000000000000000016 +:105A90000000000000000000000000000000000006 +:105AA00000000000000000000000000000000000F6 +:105AB00000000000000000000000000000000000E6 +:105AC00000000000000000000000000000000000D6 +:105AD00000000000000000000000000000000000C6 +:105AE00000000000000000000000000000000000B6 +:105AF00000000000000000000000000000000000A6 +:105B00000000000000000000000000000000000095 +:105B10000000000000000000000000000000000085 +:105B20000000000000000000000000000000000075 +:105B30000000000000000000000000000000000065 +:105B40000000000000000000000000000000000055 +:105B50000000000000000000000000000000000045 +:105B60000000000000000000000000000000000035 +:105B70000000000000000000000000000000000025 +:105B80000000000000000000000000000000000015 +:105B90000000000000000000000000000000000005 +:105BA00000000000000000000000000000000000F5 +:105BB00000000000000000000000000000000000E5 +:105BC00000000000000000000000000000000000D5 +:105BD00000000000000000000000000000000000C5 +:105BE00000000000000000000000000000000000B5 +:105BF00000000000000000000000000000000000A5 +:105C00000000000000000000000000000000000094 +:105C10000000000000000000000000000000000084 +:105C20000000000000000000000000000000000074 +:105C30000000000000000000000000000000000064 +:105C40000000000000000000000000000000000054 +:105C50000000000000000000000000000000000044 +:105C60000000000000000000000000000000000034 +:105C70000000000000000000000000000000000024 +:105C80000000000000000000000000000000000014 +:105C90000000000000000000000000000000000004 +:105CA00000000000000000000000000000000000F4 +:105CB00000000000000000000000000000000000E4 +:105CC00000000000000000000000000000000000D4 +:105CD00000000000000000000000000000000000C4 +:105CE00000000000000000000000000000000000B4 +:105CF00000000000000000000000000000000000A4 +:105D00000000000000000000000000000000000093 +:105D10000000000000000000000000000000000083 +:105D20000000000000000000000000000000000073 +:105D30000000000000000000000000000000000063 +:105D40000000000000000000000000000000000053 +:105D50000000000000000000000000000000000043 +:105D60000000000000000000000000000000000033 +:105D70000000000000000000000000000000000023 +:105D80000000000000000000000000000000000013 +:105D90000000000000000000000000000000000003 +:105DA00000000000000000000000000000000000F3 +:105DB00000000000000000000000000000000000E3 +:105DC00000000000000000000000000000000000D3 +:105DD00000000000000000000000000000000000C3 +:105DE00000000000000000000000000000000000B3 +:105DF00000000000000000000000000000000000A3 +:105E00000000000000000000000000000000000092 +:105E10000000000000000000000000000000000082 +:105E20000000000000000000000000000000000072 +:105E30000000000000000000000000000000000062 +:105E40000000000000000000000000000000000052 +:105E50000000000000000000000000000000000042 +:105E60000000000000000000000000000000000032 +:105E70000000000000000000000000000000000022 +:105E80000000000000000000000000000000000012 +:105E90000000000000000000000000000000000002 +:105EA00000000000000000000000000000000000F2 +:105EB00000000000000000000000000000000000E2 +:105EC00000000000000000000000000000000000D2 +:105ED00000000000000000000000000000000000C2 +:105EE00000000000000000000000000000000000B2 +:105EF00000000000000000000000000000000000A2 +:105F00000000000000000000000000000000000091 +:105F10000000000000000000000000000000000081 +:105F20000000000000000000000000000000000071 +:105F30000000000000000000000000000000000061 +:105F40000000000000000000000000000000000051 +:105F50000000000000000000000000000000000041 +:105F60000000000000000000000000000000000031 +:105F70000000000000000000000000000000000021 +:105F80000000000000000000000000000000000011 +:105F90000000000000000000000000000000000001 +:105FA00000000000000000000000000000000000F1 +:105FB00000000000000000000000000000000000E1 +:105FC00000000000000000000000000000000000D1 +:105FD00000000000000000000000000000000000C1 +:105FE00000000000000000000000000000000000B1 +:105FF00000000000000000000000000000000000A1 +:106000000000000000000000000000000000000090 +:106010000000000000000000000000000000000080 +:106020000000000000000000000000000000000070 +:106030000000000000000000000000000000000060 +:106040000000000000000000000000000000000050 +:106050000000000000000000000000000000000040 +:106060000000000000000000000000000000000030 +:106070000000000000000000000000000000000020 +:106080000000000000000000000000000000000010 +:106090000000000000000000000000000000000000 +:1060A00000000000000000000000000000000000F0 +:1060B00000000000000000000000000000000000E0 +:1060C00000000000000000000000000000000000D0 +:1060D00000000000000000000000000000000000C0 +:1060E00000000000000000000000000000000000B0 +:1060F00000000000000000000000000000000000A0 +:10610000000000000000000000000000000000008F +:10611000000000000000000000000000000000007F +:10612000000000000000000000000000000000006F +:10613000000000000000000000000000000000005F +:10614000000000000000000000000000000000004F +:10615000000000000000000000000000000000003F +:10616000000000000000000000000000000000002F +:10617000000000000000000000000000000000001F +:10618000000000000000000000000000000000000F +:1061900000000000000000000000000000000000FF +:1061A00000000000000000000000000000000000EF +:1061B00000000000000000000000000000000000DF +:1061C00000000000000000000000000000000000CF +:1061D00000000000000000000000000000000000BF +:1061E00000000000000000000000000000000000AF +:1061F000000000000000000000000000000000009F +:10620000000000000000000000000000000000008E +:10621000000000000000000000000000000000007E +:10622000000000000000000000000000000000006E +:10623000000000000000000000000000000000005E +:10624000000000000000000000000000000000004E +:10625000000000000000000000000000000000003E +:10626000000000000000000000000000000000002E +:10627000000000000000000000000000000000001E +:10628000000000000000000000000000000000000E +:1062900000000000000000000000000000000000FE +:1062A00000000000000000000000000000000000EE +:1062B00000000000000000000000000000000000DE +:1062C00000000000000000000000000000000000CE +:1062D00000000000000000000000000000000000BE +:1062E00000000000000000000000000000000000AE +:1062F000000000000000000000000000000000009E +:10630000000000000000000000000000000000008D +:10631000000000000000000000000000000000007D +:10632000000000000000000000000000000000006D +:10633000000000000000000000000000000000005D +:10634000000000000000000000000000000000004D +:10635000000000000000000000000000000000003D +:10636000000000000000000000000000000000002D +:10637000000000000000000000000000000000001D +:10638000000000000000000000000000000000000D +:1063900000000000000000000000000000000000FD +:1063A00000000000000000000000000000000000ED +:1063B00000000000000000000000000000000000DD +:1063C00000000000000000000000000000000000CD +:1063D00000000000000000000000000000000000BD +:1063E00000000000000000000000000000000000AD +:1063F000000000000000000000000000000000009D +:10640000000000000000000000000000000000008C +:10641000000000000000000000000000000000007C +:10642000000000000000000000000000000000006C +:10643000000000000000000000000000000000005C +:10644000000000000000000000000000000000004C +:10645000000000000000000000000000000000003C +:10646000000000000000000000000000000000002C +:10647000000000000000000000000000000000001C +:10648000000000000000000000000000000000000C +:1064900000000000000000000000000000000000FC +:1064A00000000000000000000000000000000000EC +:1064B00000000000000000000000000000000000DC +:1064C00000000000000000000000000000000000CC +:1064D00000000000000000000000000000000000BC +:1064E00000000000000000000000000000000000AC +:1064F000000000000000000000000000000000009C +:10650000000000000000000000000000000000008B +:10651000000000000000000000000000000000007B +:10652000000000000000000000000000000000006B +:10653000000000000000000000000000000000005B +:10654000000000000000000000000000000000004B +:10655000000000000000000000000000000000003B +:10656000000000000000000000000000000000002B +:10657000000000000000000000000000000000001B +:10658000000000000000000000000000000000000B +:1065900000000000000000000000000000000000FB +:1065A00000000000000000000000000000000000EB +:1065B00000000000000000000000000000000000DB +:1065C00000000000000000000000000000000000CB +:1065D00000000000000000000000000000000000BB +:1065E00000000000000000000000000000000000AB +:1065F000000000000000000000000000000000009B +:10660000000000000000000000000000000000008A +:10661000000000000000000000000000000000007A +:10662000000000000000000000000000000000006A +:10663000000000000000000000000000000000005A +:10664000000000000000000000000000000000004A +:10665000000000000000000000000000000000003A +:10666000000000000000000000000000000000002A +:10667000000000000000000000000000000000001A +:10668000000000000000000000000000000000000A +:1066900000000000000000000000000000000000FA +:1066A00000000000000000000000000000000000EA +:1066B00000000000000000000000000000000000DA +:1066C00000000000000000000000000000000000CA +:1066D00000000000000000000000000000000000BA +:1066E00000000000000000000000000000000000AA +:1066F000000000000000000000000000000000009A +:106700000000000000000000000000000000000089 +:106710000000000000000000000000000000000079 +:106720000000000000000000000000000000000069 +:106730000000000000000000000000000000000059 +:106740000000000000000000000000000000000049 +:106750000000000000000000000000000000000039 +:106760000000000000000000000000000000000029 +:106770000000000000000000000000000000000019 +:106780000000000000000000000000000000000009 +:1067900000000000000000000000000000000000F9 +:1067A00000000000000000000000000000000000E9 +:1067B00000000000000000000000000000000000D9 +:1067C00000000000000000000000000000000000C9 +:1067D00000000000000000000000000000000000B9 +:1067E00000000000000000000000000000000000A9 +:1067F0000000000000000000000000000000000099 +:106800000000000000000000000000000000000088 +:106810000000000000000000000000000000000078 +:106820000000000000000000000000000000000068 +:106830000000000000000000000000000000000058 +:106840000000000000000000000000000000000048 +:106850000000000000000000000000000000000038 +:106860000000000000000000000000000000000028 +:106870000000000000000000000000000000000018 +:106880000000000000000000000000000000000008 +:1068900000000000000000000000000000000000F8 +:1068A00000000000000000000000000000000000E8 +:1068B00000000000000000000000000000000000D8 +:1068C00000000000000000000000000000000000C8 +:1068D00000000000000000000000000000000000B8 +:1068E00000000000000000000000000000000000A8 +:1068F0000000000000000000000000000000000098 +:106900000000000000000000000000000000000087 +:106910000000000000000000000000000000000077 +:106920000000000000000000000000000000000067 +:106930000000000000000000000000000000000057 +:106940000000000000000000000000000000000047 +:106950000000000000000000000000000000000037 +:106960000000000000000000000000000000000027 +:106970000000000000000000000000000000000017 +:106980000000000000000000000000000000000007 +:1069900000000000000000000000000000000000F7 +:1069A00000000000000000000000000000000000E7 +:1069B00000000000000000000000000000000000D7 +:1069C00000000000000000000000000000000000C7 +:1069D00000000000000000000000000000000000B7 +:1069E00000000000000000000000000000000000A7 +:1069F0000000000000000000000000000000000097 +:106A00000000000000000000000000000000000086 +:106A10000000000000000000000000000000000076 +:106A20000000000000000000000000000000000066 +:106A30000000000000000000000000000000000056 +:106A40000000000000000000000000000000000046 +:106A50000000000000000000000000000000000036 +:106A60000000000000000000000000000000000026 +:106A70000000000000000000000000000000000016 +:106A80000000000000000000000000000000000006 +:106A900000000000000000000000000000000000F6 +:106AA00000000000000000000000000000000000E6 +:106AB00000000000000000000000000000000000D6 +:106AC00000000000000000000000000000000000C6 +:106AD00000000000000000000000000000000000B6 +:106AE00000000000000000000000000000000000A6 +:106AF0000000000000000000000000000000000096 +:106B00000000000000000000000000000000000085 +:106B10000000000000000000000000000000000075 +:106B20000000000000000000000000000000000065 +:106B30000000000000000000000000000000000055 +:106B40000000000000000000000000000000000045 +:106B50000000000000000000000000000000000035 +:106B60000000000000000000000000000000000025 +:106B70000000000000000000000000000000000015 +:106B80000000000000000000000000000000000005 +:106B900000000000000000000000000000000000F5 +:106BA00000000000000000000000000000000000E5 +:106BB00000000000000000000000000000000000D5 +:106BC00000000000000000000000000000000000C5 +:106BD00000000000000000000000000000000000B5 +:106BE00000000000000000000000000000000000A5 +:106BF0000000000000000000000000000000000095 +:106C00000000000000000000000000000000000084 +:106C10000000000000000000000000000000000074 +:106C20000000000000000000000000000000000064 +:106C30000000000000000000000000000000000054 +:106C40000000000000000000000000000000000044 +:106C50000000000000000000000000000000000034 +:106C60000000000000000000000000000000000024 +:106C70000000000000000000000000000000000014 +:106C80000000000000000000000000000000000004 +:106C900000000000000000000000000000000000F4 +:106CA00000000000000000000000000000000000E4 +:106CB00000000000000000000000000000000000D4 +:106CC00000000000000000000000000000000000C4 +:106CD00000000000000000000000000000000000B4 +:106CE00000000000000000000000000000000000A4 +:106CF0000000000000000000000000000000000094 +:106D00000000000000000000000000000000000083 +:106D10000000000000000000000000000000000073 +:106D20000000000000000000000000000000000063 +:106D30000000000000000000000000000000000053 +:106D40000000000000000000000000000000000043 +:106D50000000000000000000000000000000000033 +:106D60000000000000000000000000000000000023 +:106D70000000000000000000000000000000000013 +:106D80000000000000000000000000000000000003 +:106D900000000000000000000000000000000000F3 +:106DA00000000000000000000000000000000000E3 +:106DB00000000000000000000000000000000000D3 +:106DC00000000000000000000000000000000000C3 +:106DD00000000000000000000000000000000000B3 +:106DE00000000000000000000000000000000000A3 +:106DF0000000000000000000000000000000000093 +:106E00000000000000000000000000000000000082 +:106E10000000000000000000000000000000000072 +:106E20000000000000000000000000000000000062 +:106E30000000000000000000000000000000000052 +:106E40000000000000000000000000000000000042 +:106E50000000000000000000000000000000000032 +:106E60000000000000000000000000000000000022 +:106E70000000000000000000000000000000000012 +:106E80000000000000000000000000000000000002 +:106E900000000000000000000000000000000000F2 +:106EA00000000000000000000000000000000000E2 +:106EB00000000000000000000000000000000000D2 +:106EC00000000000000000000000000000000000C2 +:106ED00000000000000000000000000000000000B2 +:106EE00000000000000000000000000000000000A2 +:106EF0000000000000000000000000000000000092 +:106F00000000000000000000000000000000000081 +:106F10000000000000000000000000000000000071 +:106F20000000000000000000000000000000000061 +:106F30000000000000000000000000000000000051 +:106F40000000000000000000000000000000000041 +:106F50000000000000000000000000000000000031 +:106F60000000000000000000000000000000000021 +:106F70000000000000000000000000000000000011 +:106F80000000000000000000000000000000000001 +:106F900000000000000000000000000000000000F1 +:106FA00000000000000000000000000000000000E1 +:106FB00000000000000000000000000000000000D1 +:106FC00000000000000000000000000000000000C1 +:106FD00000000000000000000000000000000000B1 +:106FE00000000000000000000000000000000000A1 +:106FF0000000000000000000000000000000000091 +:107000000000000000000000000000000000000080 +:107010000000000000000000000000000000000070 +:107020000000000000000000000000000000000060 +:107030000000000000000000000000000000000050 +:107040000000000000000000000000000000000040 +:107050000000000000000000000000000000000030 +:107060000000000000000000000000000000000020 +:107070000000000000000000000000000000000010 +:107080000000000000000000000000000000000000 +:1070900000000000000000000000000000000000F0 +:1070A00000000000000000000000000000000000E0 +:1070B00000000000000000000000000000000000D0 +:1070C00000000000000000000000000000000000C0 +:1070D00000000000000000000000000000000000B0 +:1070E00000000000000000000000000000000000A0 +:1070F0000000000000000000000000000000000090 +:10710000000000000000000000000000000000007F +:10711000000000000000000000000000000000006F +:10712000000000000000000000000000000000005F +:10713000000000000000000000000000000000004F +:10714000000000000000000000000000000000003F +:10715000000000000000000000000000000000002F +:10716000000000000000000000000000000000001F +:10717000000000000000000000000000000000000F +:1071800000000000000000000000000000000000FF +:1071900000000000000000000000000000000000EF +:1071A00000000000000000000000000000000000DF +:1071B00000000000000000000000000000000000CF +:1071C00000000000000000000000000000000000BF +:1071D00000000000000000000000000000000000AF +:1071E000000000000000000000000000000000009F +:1071F000000000000000000000000000000000008F +:10720000000000000000000000000000000000007E +:10721000000000000000000000000000000000006E +:10722000000000000000000000000000000000005E +:10723000000000000000000000000000000000004E +:10724000000000000000000000000000000000003E +:10725000000000000000000000000000000000002E +:10726000000000000000000000000000000000001E +:10727000000000000000000000000000000000000E +:1072800000000000000000000000000000000000FE +:1072900000000000000000000000000000000000EE +:1072A00000000000000000000000000000000000DE +:1072B00000000000000000000000000000000000CE +:1072C00000000000000000000000000000000000BE +:1072D00000000000000000000000000000000000AE +:1072E000000000000000000000000000000000009E +:1072F000000000000000000000000000000000008E +:10730000000000000000000000000000000000007D +:10731000000000000000000000000000000000006D +:10732000000000000000000000000000000000005D +:10733000000000000000000000000000000000004D +:10734000000000000000000000000000000000003D +:10735000000000000000000000000000000000002D +:10736000000000000000000000000000000000001D +:10737000000000000000000000000000000000000D +:1073800000000000000000000000000000000000FD +:1073900000000000000000000000000000000000ED +:1073A00000000000000000000000000000000000DD +:1073B00000000000000000000000000000000000CD +:1073C00000000000000000000000000000000000BD +:1073D00000000000000000000000000000000000AD +:1073E000000000000000000000000000000000009D +:1073F000000000000000000000000000000000008D +:10740000000000000000000000000000000000007C +:10741000000000000000000000000000000000006C +:10742000000000000000000000000000000000005C +:10743000000000000000000000000000000000004C +:10744000000000000000000000000000000000003C +:10745000000000000000000000000000000000002C +:10746000000000000000000000000000000000001C +:10747000000000000000000000000000000000000C +:1074800000000000000000000000000000000000FC +:1074900000000000000000000000000000000000EC +:1074A00000000000000000000000000000000000DC +:1074B00000000000000000000000000000000000CC +:1074C00000000000000000000000000000000000BC +:1074D00000000000000000000000000000000000AC +:1074E000000000000000000000000000000000009C +:1074F000000000000000000000000000000000008C +:10750000000000000000000000000000000000007B +:10751000000000000000000000000000000000006B +:10752000000000000000000000000000000000005B +:10753000000000000000000000000000000000004B +:10754000000000000000000000000000000000003B +:10755000000000000000000000000000000000002B +:10756000000000000000000000000000000000001B +:10757000000000000000000000000000000000000B +:1075800000000000000000000000000000000000FB +:1075900000000000000000000000000000000000EB +:1075A00000000000000000000000000000000000DB +:1075B00000000000000000000000000000000000CB +:1075C00000000000000000000000000000000000BB +:1075D00000000000000000000000000000000000AB +:1075E000000000000000000000000000000000009B +:1075F000000000000000000000000000000000008B +:10760000000000000000000000000000000000007A +:10761000000000000000000000000000000000006A +:10762000000000000000000000000000000000005A +:10763000000000000000000000000000000000004A +:10764000000000000000000000000000000000003A +:10765000000000000000000000000000000000002A +:10766000000000000000000000000000000000001A +:10767000000000000000000000000000000000000A +:1076800000000000000000000000000000000000FA +:1076900000000000000000000000000000000000EA +:1076A00000000000000000000000000000000000DA +:1076B00000000000000000000000000000000000CA +:1076C00000000000000000000000000000000000BA +:1076D00000000000000000000000000000000000AA +:1076E000000000000000000000000000000000009A +:1076F000000000000000000000000000000000008A +:107700000000000000000000000000000000000079 +:107710000000000000000000000000000000000069 +:107720000000000000000000000000000000000059 +:107730000000000000000000000000000000000049 +:107740000000000000000000000000000000000039 +:107750000000000000000000000000000000000029 +:107760000000000000000000000000000000000019 +:107770000000000000000000000000000000000009 +:1077800000000000000000000000000000000000F9 +:1077900000000000000000000000000000000000E9 +:1077A00000000000000000000000000000000000D9 +:1077B00000000000000000000000000000000000C9 +:1077C00000000000000000000000000000000000B9 +:1077D00000000000000000000000000000000000A9 +:1077E0000000000000000000000000000000000099 +:1077F0000000000000000000000000000000000089 +:107800000000000000000000000000000000000078 +:107810000000000000000000000000000000000068 +:107820000000000000000000000000000000000058 +:107830000000000000000000000000000000000048 +:107840000000000000000000000000000000000038 +:107850000000000000000000000000000000000028 +:107860000000000000000000000000000000000018 +:107870000000000000000000000000000000000008 +:1078800000000000000000000000000000000000F8 +:1078900000000000000000000000000000000000E8 +:1078A00000000000000000000000000000000000D8 +:1078B00000000000000000000000000000000000C8 +:1078C00000000000000000000000000000000000B8 +:1078D00000000000000000000000000000000000A8 +:1078E0000000000000000000000000000000000098 +:1078F0000000000000000000000000000000000088 +:107900000000000000000000000000000000000077 +:107910000000000000000000000000000000000067 +:107920000000000000000000000000000000000057 +:107930000000000000000000000000000000000047 +:107940000000000000000000000000000000000037 +:107950000000000000000000000000000000000027 +:107960000000000000000000000000000000000017 +:107970000000000000000000000000000000000007 +:1079800000000000000000000000000000000000F7 +:1079900000000000000000000000000000000000E7 +:1079A00000000000000000000000000000000000D7 +:1079B00000000000000000000000000000000000C7 +:1079C00000000000000000000000000000000000B7 +:1079D00000000000000000000000000000000000A7 +:1079E0000000000000000000000000000000000097 +:1079F0000000000000000000000000000000000087 +:107A00000000000000000000000000000000000076 +:107A10000000000000000000000000000000000066 +:107A20000000000000000000000000000000000056 +:107A30000000000000000000000000000000000046 +:107A40000000000000000000000000000000000036 +:107A50000000000000000000000000000000000026 +:107A60000000000000000000000000000000000016 +:107A70000000000000000000000000000000000006 +:107A800000000000000000000000000000000000F6 +:107A900000000000000000000000000000000000E6 +:107AA00000000000000000000000000000000000D6 +:107AB00000000000000000000000000000000000C6 +:107AC00000000000000000000000000000000000B6 +:107AD00000000000000000000000000000000000A6 +:107AE0000000000000000000000000000000000096 +:107AF0000000000000000000000000000000000086 +:107B00000000000000000000000000000000000075 +:107B10000000000000000000000000000000000065 +:107B20000000000000000000000000000000000055 +:107B30000000000000000000000000000000000045 +:107B40000000000000000000000000000000000035 +:107B50000000000000000000000000000000000025 +:107B60000000000000000000000000000000000015 +:107B70000000000000000000000000000000000005 +:107B800000000000000000000000000000000000F5 +:107B900000000000000000000000000000000000E5 +:107BA00000000000000000000000000000000000D5 +:107BB00000000000000000000000000000000000C5 +:107BC00000000000000000000000000000000000B5 +:107BD00000000000000000000000000000000000A5 +:107BE0000000000000000000000000000000000095 +:107BF0000000000000000000000000000000000085 +:107C00000000000000000000000000000000000074 +:107C10000000000000000000000000000000000064 +:107C20000000000000000000000000000000000054 +:107C30000000000000000000000000000000000044 +:107C40000000000000000000000000000000000034 +:107C50000000000000000000000000000000000024 +:107C60000000000000000000000000000000000014 +:107C70000000000000000000000000000000000004 +:107C800000000000000000000000000000000000F4 +:107C900000000000000000000000000000000000E4 +:107CA00000000000000000000000000000000000D4 +:107CB00000000000000000000000000000000000C4 +:107CC00000000000000000000000000000000000B4 +:107CD00000000000000000000000000000000000A4 +:107CE0000000000000000000000000000000000094 +:107CF0000000000000000000000000000000000084 +:107D00000000000000000000000000000000000073 +:107D10000000000000000000000000000000000063 +:107D20000000000000000000000000000000000053 +:107D30000000000000000000000000000000000043 +:107D40000000000000000000000000000000000033 +:107D50000000000000000000000000000000000023 +:107D60000000000000000000000000000000000013 +:107D70000000000000000000000000000000000003 +:107D800000000000000000000000000000000000F3 +:107D900000000000000000000000000000000000E3 +:107DA00000000000000000000000000000000000D3 +:107DB00000000000000000000000000000000000C3 +:107DC00000000000000000000000000000000000B3 +:107DD00000000000000000000000000000000000A3 +:107DE0000000000000000000000000000000000093 +:107DF0000000000000000000000000000000000083 +:107E00000000000000000000000000000000000072 +:107E10000000000000000000000000000000000062 +:107E20000000000000000000000000000000000052 +:107E30000000000000000000000000000000000042 +:107E40000000000000000000000000000000000032 +:107E50000000000000000000000000000000000022 +:107E60000000000000000000000000000000000012 +:107E70000000000000000000000000000000000002 +:107E800000000000000000000000000000000000F2 +:107E900000000000000000000000000000000000E2 +:107EA00000000000000000000000000000000000D2 +:107EB00000000000000000000000000000000000C2 +:107EC00000000000000000000000000000000000B2 +:107ED00000000000000000000000000000000000A2 +:107EE0000000000000000000000000000000000092 +:107EF0000000000000000000000000000000000082 +:107F00000000000000000000000000000000000071 +:107F10000000000000000000000000000000000061 +:107F20000000000000000000000000000000000051 +:107F30000000000000000000000000000000000041 +:107F40000000000000000000000000000000000031 +:107F50000000000000000000000000000000000021 +:107F60000000000000000000000000000000000011 +:107F70000000000000000000000000000000000001 +:107F800000000000000000000000000000000000F1 +:107F900000000000000000000000000000000000E1 +:107FA00000000000000000000000000000000000D1 +:107FB00000000000000000000000000000000000C1 +:107FC00000000000000000000000000000000000B1 +:107FD00000000000000000000000000000000000A1 +:107FE0000000000000000000000000000000000091 +:107FF0000000000000000000000000000000000081 +:108000000000000000000000000000000000000070 +:108010000000000000000000000000000000000060 +:108020000000000000000000000000000000000050 +:108030000000000000000000000000000000000040 +:108040000000000000000000000000000000000030 +:108050000000000000000000000000000000000020 +:108060000000000000000000000000000000000010 +:108070000000000000000000000000000000000000 +:1080800000000000000000000000000000000000F0 +:1080900000000000000000000000000000000000E0 +:1080A00000000000000000000000000000000000D0 +:1080B00000000000000000000000000000000000C0 +:1080C00000000000000000000000000000000000B0 +:1080D00000000000000000000000000000000000A0 +:1080E0000000000000000000000000000000000090 +:1080F0000000000000000000000000000000000080 +:10810000000000000000000000000000000000006F +:10811000000000000000000000000000000000005F +:10812000000000000000000000000000000000004F +:10813000000000000000000000000000000000003F +:10814000000000000000000000000000000000002F +:10815000000000000000000000000000000000001F +:10816000000000000000000000000000000000000F +:1081700000000000000000000000000000000000FF +:1081800000000000000000000000000000000000EF +:1081900000000000000000000000000000000000DF +:1081A00000000000000000000000000000000000CF +:1081B00000000000000000000000000000000000BF +:1081C00000000000000000000000000000000000AF +:1081D000000000000000000000000000000000009F +:1081E000000000000000000000000000000000008F +:1081F000000000000000000000000000000000007F +:10820000000000000000000000000000000000006E +:10821000000000000000000000000000000000005E +:10822000000000000000000000000000000000004E +:10823000000000000000000000000000000000003E +:10824000000000000000000000000000000000002E +:10825000000000000000000000000000000000001E +:10826000000000000000000000000000000000000E +:1082700000000000000000000000000000000000FE +:1082800000000000000000000000000000000000EE +:1082900000000000000000000000000000000000DE +:1082A00000000000000000000000000000000000CE +:1082B00000000000000000000000000000000000BE +:1082C00000000000000000000000000000000000AE +:1082D000000000000000000000000000000000009E +:1082E000000000000000000000000000000000008E +:1082F000000000000000000000000000000000007E +:10830000000000000000000000000000000000006D +:10831000000000000000000000000000000000005D +:10832000000000000000000000000000000000004D +:10833000000000000000000000000000000000003D +:10834000000000000000000000000000000000002D +:10835000000000000000000000000000000000001D +:10836000000000000000000000000000000000000D +:1083700000000000000000000000000000000000FD +:1083800000000000000000000000000000000000ED +:1083900000000000000000000000000000000000DD +:1083A00000000000000000000000000000000000CD +:1083B00000000000000000000000000000000000BD +:1083C00000000000000000000000000000000000AD +:1083D000000000000000000000000000000000009D +:1083E000000000000000000000000000000000008D +:1083F000000000000000000000000000000000007D +:10840000000000000000000000000000000000006C +:10841000000000000000000000000000000000005C +:10842000000000000000000000000000000000004C +:10843000000000000000000000000000000000003C +:10844000000000000000000000000000000000002C +:10845000000000000000000000000000000000001C +:10846000000000000000000000000000000000000C +:1084700000000000000000000000000000000000FC +:1084800000000000000000000000000000000000EC +:1084900000000000000000000000000000000000DC +:1084A00000000000000000000000000000000000CC +:1084B00000000000000000000000000000000000BC +:1084C00000000000000000000000000000000000AC +:1084D000000000000000000000000000000000009C +:1084E000000000000000000000000000000000008C +:1084F000000000000000000000000000000000007C +:10850000000000000000000000000000000000006B +:10851000000000000000000000000000000000005B +:10852000000000000000000000000000000000004B +:10853000000000000000000000000000000000003B +:10854000000000000000000000000000000000002B +:10855000000000000000000000000000000000001B +:10856000000000000000000000000000000000000B +:1085700000000000000000000000000000000000FB +:1085800000000000000000000000000000000000EB +:1085900000000000000000000000000000000000DB +:1085A00000000000000000000000000000000000CB +:1085B00000000000000000000000000000000000BB +:1085C00000000000000000000000000000000000AB +:1085D000000000000000000000000000000000009B +:1085E000000000000000000000000000000000008B +:1085F000000000000000000000000000000000007B +:10860000000000000000000000000000000000006A +:10861000000000000000000000000000000000005A +:10862000000000000000000000000000000000004A +:10863000000000000000000000000000000000003A +:10864000000000000000000000000000000000002A +:10865000000000000000000000000000000000001A +:10866000000000000000000000000000000000000A +:1086700000000000000000000000000000000000FA +:1086800000000000000000000000000000000000EA +:1086900000000000000000000000000000000000DA +:1086A00000000000000000000000000000000000CA +:1086B00000000000000000000000000000000000BA +:1086C00000000000000000000000000000000000AA +:1086D000000000000000000000000000000000009A +:1086E000000000000000000000000000000000008A +:1086F000000000000000000000000000000000007A +:108700000000000000000000000000000000000069 +:108710000000000000000000000000000000000059 +:108720000000000000000000000000000000000049 +:108730000000000000000000000000000000000039 +:108740000000000000000000000000000000000029 +:108750000000000000000000000000000000000019 +:108760000000000000000000000000000000000009 +:1087700000000000000000000000000000000000F9 +:1087800000000000000000000000000000000000E9 +:1087900000000000000000000000000000000000D9 +:1087A00000000000000000000000000000000000C9 +:1087B00000000000000000000000000000000000B9 +:1087C00000000000000000000000000000000000A9 +:1087D0000000000000000000000000000000000099 +:1087E0000000000000000000000000000000000089 +:1087F0000000000000000000000000000000000079 +:108800000000000000000000000000000000000068 +:108810000000000000000000000000000000000058 +:108820000000000000000000000000000000000048 +:108830000000000000000000000000000000000038 +:108840000000000000000000000000000000000028 +:108850000000000000000000000000000000000018 +:108860000000000000000000000000000000000008 +:1088700000000000000000000000000000000000F8 +:1088800000000000000000000000000000000000E8 +:1088900000000000000000000000000000000000D8 +:1088A00000000000000000000000000000000000C8 +:1088B00000000000000000000000000000000000B8 +:1088C00000000000000000000000000000000000A8 +:1088D0000000000000000000000000000000000098 +:1088E0000000000000000000000000000000000088 +:1088F0000000000000000000000000000000000078 +:108900000000000000000000000000000000000067 +:108910000000000000000000000000000000000057 +:108920000000000000000000000000000000000047 +:108930000000000000000000000000000000000037 +:108940000000000000000000000000000000000027 +:108950000000000000000000000000000000000017 +:108960000000000000000000000000000000000007 +:1089700000000000000000000000000000000000F7 +:1089800000000000000000000000000000000000E7 +:1089900000000000000000000000000000000000D7 +:1089A00000000000000000000000000000000000C7 +:1089B00000000000000000000000000000000000B7 +:1089C00000000000000000000000000000000000A7 +:1089D0000000000000000000000000000000000097 +:1089E0000000000000000000000000000000000087 +:1089F0000000000000000000000000000000000077 +:108A00000000000000000000000000000000000066 +:108A10000000000000000000000000000000000056 +:108A20000000000000000000000000000000000046 +:108A30000000000000000000000000000000000036 +:108A40000000000000000000000000000000000026 +:108A50000000000000000000000000000000000016 +:108A60000000000000000000000000000000000006 +:108A700000000000000000000000000000000000F6 +:108A800000000000000000000000000000000000E6 +:108A900000000000000000000000000000000000D6 +:108AA00000000000000000000000000000000000C6 +:108AB00000000000000000000000000000000000B6 +:108AC00000000000000000000000000000000000A6 +:108AD0000000000000000000000000000000000096 +:108AE0000000000000000000000000000000000086 +:108AF0000000000000000000000000000000000076 +:108B00000000000000000000000000000000000065 +:108B10000000000000000000000000000000000055 +:108B20000000000000000000000000000000000045 +:108B30000000000000000000000000000000000035 +:108B40000000000000000000000000000000000025 +:108B50000000000000000000000000000000000015 +:108B60000000000000000000000000000000000005 +:108B700000000000000000000000000000000000F5 +:108B800000000000000000000000000000000000E5 +:108B900000000000000000000000000000000000D5 +:108BA00000000000000000000000000000000000C5 +:108BB00000000000000000000000000000000000B5 +:108BC00000000000000000000000000000000000A5 +:108BD0000000000000000000000000000000000095 +:108BE0000000000000000000000000000000000085 +:108BF0000000000000000000000000000000000075 +:108C00000000000000000000000000000000000064 +:108C10000000000000000000000000000000000054 +:108C20000000000000000000000000000000000044 +:108C30000000000000000000000000000000000034 +:108C40000000000000000000000000000000000024 +:108C50000000000000000000000000000000000014 +:108C60000000000000000000000000000000000004 +:108C700000000000000000000000000000000000F4 +:108C800000000000000000000000000000000000E4 +:108C900000000000000000000000000000000000D4 +:108CA00000000000000000000000000000000000C4 +:108CB00000000000000000000000000000000000B4 +:108CC00000000000000000000000000000000000A4 +:108CD0000000000000000000000000000000000094 +:108CE0000000000000000000000000000000000084 +:108CF0000000000000000000000000000000000074 +:108D00000000000000000000000000000000000063 +:108D10000000000000000000000000000000000053 +:108D20000000000000000000000000000000000043 +:108D30000000000000000000000000000000000033 +:108D40000000000000000000000000000000000023 +:108D50000000000000000000000000000000000013 +:108D60000000000000000000000000000000000003 +:108D700000000000000000000000000000000000F3 +:108D800000000000000000000000000000000000E3 +:108D900000000000000000000000000000000000D3 +:108DA00000000000000000000000000000000000C3 +:108DB00000000000000000000000000000000000B3 +:108DC00000000000000000000000000000000000A3 +:108DD0000000000000000000000000000000000093 +:108DE0000000000000000000000000000000000083 +:108DF0000000000000000000000000000000000073 +:108E00000000000000000000000000000000000062 +:108E10000000000000000000000000000000000052 +:108E20000000000000000000000000000000000042 +:108E30000000000000000000000000000000000032 +:108E40000000000000000000000000000000000022 +:108E50000000000000000000000000000000000012 +:108E60000000000000000000000000000000000002 +:108E700000000000000000000000000000000000F2 +:108E800000000000000000000000000000000000E2 +:108E900000000000000000000000000000000000D2 +:108EA00000000000000000000000000000000000C2 +:108EB00000000000000000000000000000000000B2 +:108EC00000000000000000000000000000000000A2 +:108ED0000000000000000000000000000000000092 +:108EE0000000000000000000000000000000000082 +:108EF0000000000000000000000000000000000072 +:108F00000000000000000000000000000000000061 +:108F10000000000000000000000000000000000051 +:108F20000000000000000000000000000000000041 +:108F30000000000000000000000000000000000031 +:108F40000000000000000000000000000000000021 +:108F50000000000000000000000000000000000011 +:108F60000000000000000000000000000000000001 +:108F700000000000000000000000000000000000F1 +:108F800000000000000000000000000000000000E1 +:108F900000000000000000000000000000000000D1 +:108FA00000000000000000000000000000000000C1 +:108FB00000000000000000000000000000000000B1 +:108FC00000000000000000000000000000000000A1 +:108FD0000000000000000000000000000000000091 +:108FE0000000000000000000000000000000000081 +:108FF0000000000000000000000000000000000071 +:109000000000000000000000000000000000000060 +:109010000000000000000000000000000000000050 +:109020000000000000000000000000000000000040 +:109030000000000000000000000000000000000030 +:109040000000000000000000000000000000000020 +:109050000000000000000000000000000000000010 +:109060000000000000000000000000000000000000 +:1090700000000000000000000000000000000000F0 +:1090800000000000000000000000000000000000E0 +:1090900000000000000000000000000000000000D0 +:1090A00000000000000000000000000000000000C0 +:1090B00000000000000000000000000000000000B0 +:1090C00000000000000000000000000000000000A0 +:1090D0000000000000000000000000000000000090 +:1090E0000000000000000000000000000000000080 +:1090F0000000000000000000000000000000000070 +:10910000000000000000000000000000000000005F +:10911000000000000000000000000000000000004F +:10912000000000000000000000000000000000003F +:10913000000000000000000000000000000000002F +:10914000000000000000000000000000000000001F +:10915000000000000000000000000000000000000F +:1091600000000000000000000000000000000000FF +:1091700000000000000000000000000000000000EF +:1091800000000000000000000000000000000000DF +:1091900000000000000000000000000000000000CF +:1091A00000000000000000000000000000000000BF +:1091B00000000000000000000000000000000000AF +:1091C000000000000000000000000000000000009F +:1091D000000000000000000000000000000000008F +:1091E000000000000000000000000000000000007F +:1091F000000000000000000000000000000000006F +:10920000000000000000000000000000000000005E +:10921000000000000000000000000000000000004E +:10922000000000000000000000000000000000003E +:10923000000000000000000000000000000000002E +:10924000000000000000000000000000000000001E +:10925000000000000000000000000000000000000E +:1092600000000000000000000000000000000000FE +:1092700000000000000000000000000000000000EE +:1092800000000000000000000000000000000000DE +:1092900000000000000000000000000000000000CE +:1092A00000000000000000000000000000000000BE +:1092B00000000000000000000000000000000000AE +:1092C000000000000000000000000000000000009E +:1092D000000000000000000000000000000000008E +:1092E000000000000000000000000000000000007E +:1092F000000000000000000000000000000000006E +:10930000000000000000000000000000000000005D +:10931000000000000000000000000000000000004D +:10932000000000000000000000000000000000003D +:10933000000000000000000000000000000000002D +:10934000000000000000000000000000000000001D +:10935000000000000000000000000000000000000D +:1093600000000000000000000000000000000000FD +:1093700000000000000000000000000000000000ED +:1093800000000000000000000000000000000000DD +:1093900000000000000000000000000000000000CD +:1093A00000000000000000000000000000000000BD +:1093B00000000000000000000000000000000000AD +:1093C000000000000000000000000000000000009D +:1093D000000000000000000000000000000000008D +:1093E000000000000000000000000000000000007D +:1093F000000000000000000000000000000000006D +:10940000000000000000000000000000000000005C +:10941000000000000000000000000000000000004C +:10942000000000000000000000000000000000003C +:10943000000000000000000000000000000000002C +:10944000000000000000000000000000000000001C +:10945000000000000000000000000000000000000C +:1094600000000000000000000000000000000000FC +:1094700000000000000000000000000000000000EC +:1094800000000000000000000000000000000000DC +:1094900000000000000000000000000000000000CC +:1094A00000000000000000000000000000000000BC +:1094B00000000000000000000000000000000000AC +:1094C000000000000000000000000000000000009C +:1094D000000000000000000000000000000000008C +:1094E000000000000000000000000000000000007C +:1094F000000000000000000000000000000000006C +:10950000000000000000000000000000000000005B +:10951000000000000000000000000000000000004B +:10952000000000000000000000000000000000003B +:10953000000000000000000000000000000000002B +:10954000000000000000000000000000000000001B +:10955000000000000000000000000000000000000B +:1095600000000000000000000000000000000000FB +:1095700000000000000000000000000000000000EB +:1095800000000000000000000000000000000000DB +:1095900000000000000000000000000000000000CB +:1095A00000000000000000000000000000000000BB +:1095B00000000000000000000000000000000000AB +:1095C000000000000000000000000000000000009B +:1095D000000000000000000000000000000000008B +:1095E000000000000000000000000000000000007B +:1095F000000000000000000000000000000000006B +:10960000000000000000000000000000000000005A +:10961000000000000000000000000000000000004A +:10962000000000000000000000000000000000003A +:10963000000000000000000000000000000000002A +:10964000000000000000000000000000000000001A +:10965000000000000000000000000000000000000A +:1096600000000000000000000000000000000000FA +:1096700000000000000000000000000000000000EA +:1096800000000000000000000000000000000000DA +:1096900000000000000000000000000000000000CA +:1096A00000000000000000000000000000000000BA +:1096B00000000000000000000000000000000000AA +:1096C000000000000000000000000000000000009A +:1096D000000000000000000000000000000000008A +:1096E000000000000000000000000000000000007A +:1096F000000000000000000000000000000000006A +:109700000000000000000000000000000000000059 +:109710000000000000000000000000000000000049 +:109720000000000000000000000000000000000039 +:109730000000000000000000000000000000000029 +:109740000000000000000000000000000000000019 +:109750000000000000000000000000000000000009 +:1097600000000000000000000000000000000000F9 +:1097700000000000000000000000000000000000E9 +:1097800000000000000000000000000000000000D9 +:1097900000000000000000000000000000000000C9 +:1097A00000000000000000000000000000000000B9 +:1097B00000000000000000000000000000000000A9 +:1097C0000000000000000000000000000000000099 +:1097D0000000000000000000000000000000000089 +:1097E0000000000000000000000000000000000079 +:1097F0000000000000000000000000000000000069 +:109800000000000000000000000000000000000058 +:109810000000000000000000000000000000000048 +:109820000000000000000000000000000000000038 +:109830000000000000000000000000000000000028 +:109840000000000000000000000000000000000018 +:109850000000000000000000000000000000000008 +:1098600000000000000000000000000000000000F8 +:1098700000000000000000000000000000000000E8 +:1098800000000000000000000000000000000000D8 +:1098900000000000000000000000000000000000C8 +:1098A00000000000000000000000000000000000B8 +:1098B00000000000000000000000000000000000A8 +:1098C0000000000000000000000000000000000098 +:1098D0000000000000000000000000000000000088 +:1098E0000000000000000000000000000000000078 +:1098F0000000000000000000000000000000000068 +:109900000000000000000000000000000000000057 +:109910000000000000000000000000000000000047 +:109920000000000000000000000000000000000037 +:109930000000000000000000000000000000000027 +:109940000000000000000000000000000000000017 +:109950000000000000000000000000000000000007 +:1099600000000000000000000000000000000000F7 +:1099700000000000000000000000000000000000E7 +:1099800000000000000000000000000000000000D7 +:1099900000000000000000000000000000000000C7 +:1099A00000000000000000000000000000000000B7 +:1099B00000000000000000000000000000000000A7 +:1099C0000000000000000000000000000000000097 +:1099D0000000000000000000000000000000000087 +:1099E0000000000000000000000000000000000077 +:1099F0000000000000000000000000000000000067 +:109A00000000000000000000000000000000000056 +:109A10000000000000000000000000000000000046 +:109A20000000000000000000000000000000000036 +:109A30000000000000000000000000000000000026 +:109A40000000000000000000000000000000000016 +:109A50000000000000000000000000000000000006 +:109A600000000000000000000000000000000000F6 +:109A700000000000000000000000000000000000E6 +:109A800000000000000000000000000000000000D6 +:109A900000000000000000000000000000000000C6 +:109AA00000000000000000000000000000000000B6 +:109AB00000000000000000000000000000000000A6 +:109AC0000000000000000000000000000000000096 +:109AD0000000000000000000000000000000000086 +:109AE0000000000000000000000000000000000076 +:109AF0000000000000000000000000000000000066 +:109B00000000000000000000000000000000000055 +:109B10000000000000000000000000000000000045 +:109B20000000000000000000000000000000000035 +:109B30000000000000000000000000000000000025 +:109B40000000000000000000000000000000000015 +:109B50000000000000000000000000000000000005 +:109B600000000000000000000000000000000000F5 +:109B700000000000000000000000000000000000E5 +:109B800000000000000000000000000000000000D5 +:109B900000000000000000000000000000000000C5 +:109BA00000000000000000000000000000000000B5 +:109BB00000000000000000000000000000000000A5 +:109BC0000000000000000000000000000000000095 +:109BD0000000000000000000000000000000000085 +:109BE0000000000000000000000000000000000075 +:109BF0000000000000000000000000000000000065 +:109C00000000000000000000000000000000000054 +:109C10000000000000000000000000000000000044 +:109C20000000000000000000000000000000000034 +:109C30000000000000000000000000000000000024 +:109C40000000000000000000000000000000000014 +:109C50000000000000000000000000000000000004 +:109C600000000000000000000000000000000000F4 +:109C700000000000000000000000000000000000E4 +:109C800000000000000000000000000000000000D4 +:109C900000000000000000000000000000000000C4 +:109CA00000000000000000000000000000000000B4 +:109CB00000000000000000000000000000000000A4 +:109CC0000000000000000000000000000000000094 +:109CD0000000000000000000000000000000000084 +:109CE0000000000000000000000000000000000074 +:109CF0000000000000000000000000000000000064 +:109D00000000000000000000000000000000000053 +:109D10000000000000000000000000000000000043 +:109D20000000000000000000000000000000000033 +:109D30000000000000000000000000000000000023 +:109D40000000000000000000000000000000000013 +:109D50000000000000000000000000000000000003 +:109D600000000000000000000000000000000000F3 +:109D700000000000000000000000000000000000E3 +:109D800000000000000000000000000000000000D3 +:109D900000000000000000000000000000000000C3 +:109DA00000000000000000000000000000000000B3 +:109DB00000000000000000000000000000000000A3 +:109DC0000000000000000000000000000000000093 +:109DD0000000000000000000000000000000000083 +:109DE0000000000000000000000000000000000073 +:109DF0000000000000000000000000000000000063 +:109E00000000000000000000000000000000000052 +:109E10000000000000000000000000000000000042 +:109E20000000000000000000000000000000000032 +:109E30000000000000000000000000000000000022 +:109E40000000000000000000000000000000000012 +:109E50000000000000000000000000000000000002 +:109E600000000000000000000000000000000000F2 +:109E700000000000000000000000000000000000E2 +:109E800000000000000000000000000000000000D2 +:109E900000000000000000000000000000000000C2 +:109EA00000000000000000000000000000000000B2 +:109EB00000000000000000000000000000000000A2 +:109EC0000000000000000000000000000000000092 +:109ED0000000000000000000000000000000000082 +:109EE0000000000000000000000000000000000072 +:109EF0000000000000000000000000000000000062 +:109F00000000000000000000000000000000000051 +:109F10000000000000000000000000000000000041 +:109F20000000000000000000000000000000000031 +:109F30000000000000000000000000000000000021 +:109F40000000000000000000000000000000000011 +:109F50000000000000000000000000000000000001 +:109F600000000000000000000000000000000000F1 +:109F700000000000000000000000000000000000E1 +:109F800000000000000000000000000000000000D1 +:109F900000000000000000000000000000000000C1 +:109FA00000000000000000000000000000000000B1 +:109FB00000000000000000000000000000000000A1 +:109FC0000000000000000000000000000000000091 +:109FD0000000000000000000000000000000000081 +:109FE0000000000000000000000000000000000071 +:109FF0000000000000000000000000000000000061 +:10A000000000000000000000000000000000000050 +:10A010000000000000000000000000000000000040 +:10A020000000000000000000000000000000000030 +:10A030000000000000000000000000000000000020 +:10A040000000000000000000000000000000000010 +:10A050000000000000000000000000000000000000 +:10A0600000000000000000000000000000000000F0 +:10A0700000000000000000000000000000000000E0 +:10A0800000000000000000000000000000000000D0 +:10A0900000000000000000000000000000000000C0 +:10A0A00000000000000000000000000000000000B0 +:10A0B00000000000000000000000000000000000A0 +:10A0C0000000000000000000000000000000000090 +:10A0D0000000000000000000000000000000000080 +:10A0E0000000000000000000000000000000000070 +:10A0F0000000000000000000000000000000000060 +:10A10000000000000000000000000000000000004F +:10A11000000000000000000000000000000000003F +:10A12000000000000000000000000000000000002F +:10A13000000000000000000000000000000000001F +:10A14000000000000000000000000000000000000F +:10A1500000000000000000000000000000000000FF +:10A1600000000000000000000000000000000000EF +:10A1700000000000000000000000000000000000DF +:10A1800000000000000000000000000000000000CF +:10A1900000000000000000000000000000000000BF +:10A1A00000000000000000000000000000000000AF +:10A1B000000000000000000000000000000000009F +:10A1C000000000000000000000000000000000008F +:10A1D000000000000000000000000000000000007F +:10A1E000000000000000000000000000000000006F +:10A1F000000000000000000000000000000000005F +:10A20000000000000000000000000000000000004E +:10A21000000000000000000000000000000000003E +:10A22000000000000000000000000000000000002E +:10A23000000000000000000000000000000000001E +:10A24000000000000000000000000000000000000E +:10A2500000000000000000000000000000000000FE +:10A2600000000000000000000000000000000000EE +:10A2700000000000000000000000000000000000DE +:10A2800000000000000000000000000000000000CE +:10A2900000000000000000000000000000000000BE +:10A2A00000000000000000000000000000000000AE +:10A2B000000000000000000000000000000000009E +:10A2C000000000000000000000000000000000008E +:10A2D000000000000000000000000000000000007E +:10A2E000000000000000000000000000000000006E +:10A2F000000000000000000000000000000000005E +:10A30000000000000000000000000000000000004D +:10A31000000000000000000000000000000000003D +:10A32000000000000000000000000000000000002D +:10A33000000000000000000000000000000000001D +:10A34000000000000000000000000000000000000D +:10A3500000000000000000000000000000000000FD +:10A3600000000000000000000000000000000000ED +:10A3700000000000000000000000000000000000DD +:10A3800000000000000000000000000000000000CD +:10A3900000000000000000000000000000000000BD +:10A3A00000000000000000000000000000000000AD +:10A3B000000000000000000000000000000000009D +:10A3C000000000000000000000000000000000008D +:10A3D000000000000000000000000000000000007D +:10A3E000000000000000000000000000000000006D +:10A3F000000000000000000000000000000000005D +:10A40000000000000000000000000000000000004C +:10A41000000000000000000000000000000000003C +:10A42000000000000000000000000000000000002C +:10A43000000000000000000000000000000000001C +:10A44000000000000000000000000000000000000C +:10A4500000000000000000000000000000000000FC +:10A4600000000000000000000000000000000000EC +:10A4700000000000000000000000000000000000DC +:10A4800000000000000000000000000000000000CC +:10A4900000000000000000000000000000000000BC +:10A4A00000000000000000000000000000000000AC +:10A4B000000000000000000000000000000000009C +:10A4C000000000000000000000000000000000008C +:10A4D000000000000000000000000000000000007C +:10A4E000000000000000000000000000000000006C +:10A4F000000000000000000000000000000000005C +:10A50000000000000000000000000000000000004B +:10A51000000000000000000000000000000000003B +:10A52000000000000000000000000000000000002B +:10A53000000000000000000000000000000000001B +:10A54000000000000000000000000000000000000B +:10A5500000000000000000000000000000000000FB +:10A5600000000000000000000000000000000000EB +:10A5700000000000000000000000000000000000DB +:10A5800000000000000000000000000000000000CB +:10A5900000000000000000000000000000000000BB +:10A5A00000000000000000000000000000000000AB +:10A5B000000000000000000000000000000000009B +:10A5C000000000000000000000000000000000008B +:10A5D000000000000000000000000000000000007B +:10A5E000000000000000000000000000000000006B +:10A5F000000000000000000000000000000000005B +:10A60000000000000000000000000000000000004A +:10A61000000000000000000000000000000000003A +:10A62000000000000000000000000000000000002A +:10A63000000000000000000000000000000000001A +:10A64000000000000000000000000000000000000A +:10A6500000000000000000000000000000000000FA +:10A6600000000000000000000000000000000000EA +:10A6700000000000000000000000000000000000DA +:10A6800000000000000000000000000000000000CA +:10A6900000000000000000000000000000000000BA +:10A6A00000000000000000000000000000000000AA +:10A6B000000000000000000000000000000000009A +:10A6C000000000000000000000000000000000008A +:10A6D000000000000000000000000000000000007A +:10A6E000000000000000000000000000000000006A +:10A6F000000000000000000000000000000000005A +:10A700000000000000000000000000000000000049 +:10A710000000000000000000000000000000000039 +:10A720000000000000000000000000000000000029 +:10A730000000000000000000000000000000000019 +:10A740000000000000000000000000000000000009 +:10A7500000000000000000000000000000000000F9 +:10A7600000000000000000000000000000000000E9 +:10A7700000000000000000000000000000000000D9 +:10A7800000000000000000000000000000000000C9 +:10A7900000000000000000000000000000000000B9 +:10A7A00000000000000000000000000000000000A9 +:10A7B0000000000000000000000000000000000099 +:10A7C0000000000000000000000000000000000089 +:10A7D0000000000000000000000000000000000079 +:10A7E0000000000000000000000000000000000069 +:10A7F0000000000000000000000000000000000059 +:10A800000000000000000000000000000000000048 +:10A810000000000000000000000000000000000038 +:10A820000000000000000000000000000000000028 +:10A830000000000000000000000000000000000018 +:10A840000000000000000000000000000000000008 +:10A8500000000000000000000000000000000000F8 +:10A8600000000000000000000000000000000000E8 +:10A8700000000000000000000000000000000000D8 +:10A8800000000000000000000000000000000000C8 +:10A8900000000000000000000000000000000000B8 +:10A8A00000000000000000000000000000000000A8 +:10A8B0000000000000000000000000000000000098 +:10A8C0000000000000000000000000000000000088 +:10A8D0000000000000000000000000000000000078 +:10A8E0000000000000000000000000000000000068 +:10A8F0000000000000000000000000000000000058 +:10A900000000000000000000000000000000000047 +:10A910000000000000000000000000000000000037 +:10A920000000000000000000000000000000000027 +:10A930000000000000000000000000000000000017 +:10A940000000000000000000000000000000000007 +:10A9500000000000000000000000000000000000F7 +:10A9600000000000000000000000000000000000E7 +:10A9700000000000000000000000000000000000D7 +:10A9800000000000000000000000000000000000C7 +:10A9900000000000000000000000000000000000B7 +:10A9A00000000000000000000000000000000000A7 +:10A9B0000000000000000000000000000000000097 +:10A9C0000000000000000000000000000000000087 +:10A9D0000000000000000000000000000000000077 +:10A9E0000000000000000000000000000000000067 +:10A9F0000000000000000000000000000000000057 +:10AA00000000000000000000000000000000000046 +:10AA10000000000000000000000000000000000036 +:10AA20000000000000000000000000000000000026 +:10AA30000000000000000000000000000000000016 +:10AA40000000000000000000000000000000000006 +:10AA500000000000000000000000000000000000F6 +:10AA600000000000000000000000000000000000E6 +:10AA700000000000000000000000000000000000D6 +:10AA800000000000000000000000000000000000C6 +:10AA900000000000000000000000000000000000B6 +:10AAA00000000000000000000000000000000000A6 +:10AAB0000000000000000000000000000000000096 +:10AAC0000000000000000000000000000000000086 +:10AAD0000000000000000000000000000000000076 +:10AAE0000000000000000000000000000000000066 +:10AAF0000000000000000000000000000000000056 +:10AB00000000000000000000000000000000000045 +:10AB10000000000000000000000000000000000035 +:10AB20000000000000000000000000000000000025 +:10AB30000000000000000000000000000000000015 +:10AB40000000000000000000000000000000000005 +:10AB500000000000000000000000000000000000F5 +:10AB600000000000000000000000000000000000E5 +:10AB700000000000000000000000000000000000D5 +:10AB800000000000000000000000000000000000C5 +:10AB900000000000000000000000000000000000B5 +:10ABA00000000000000000000000000000000000A5 +:10ABB0000000000000000000000000000000000095 +:10ABC0000000000000000000000000000000000085 +:10ABD0000000000000000000000000000000000075 +:10ABE0000000000000000000000000000000000065 +:10ABF0000000000000000000000000000000000055 +:10AC00000000000000000000000000000000000044 +:10AC10000000000000000000000000000000000034 +:10AC20000000000000000000000000000000000024 +:10AC30000000000000000000000000000000000014 +:10AC40000000000000000000000000000000000004 +:10AC500000000000000000000000000000000000F4 +:10AC600000000000000000000000000000000000E4 +:10AC700000000000000000000000000000000000D4 +:10AC800000000000000000000000000000000000C4 +:10AC900000000000000000000000000000000000B4 +:10ACA00000000000000000000000000000000000A4 +:10ACB0000000000000000000000000000000000094 +:10ACC0000000000000000000000000000000000084 +:10ACD0000000000000000000000000000000000074 +:10ACE0000000000000000000000000000000000064 +:10ACF0000000000000000000000000000000000054 +:10AD00000000000000000000000000000000000043 +:10AD10000000000000000000000000000000000033 +:10AD20000000000000000000000000000000000023 +:10AD30000000000000000000000000000000000013 +:10AD40000000000000000000000000000000000003 +:10AD500000000000000000000000000000000000F3 +:10AD600000000000000000000000000000000000E3 +:10AD700000000000000000000000000000000000D3 +:10AD800000000000000000000000000000000000C3 +:10AD900000000000000000000000000000000000B3 +:10ADA00000000000000000000000000000000000A3 +:10ADB0000000000000000000000000000000000093 +:10ADC0000000000000000000000000000000000083 +:10ADD0000000000000000000000000000000000073 +:10ADE0000000000000000000000000000000000063 +:10ADF0000000000000000000000000000000000053 +:10AE00000000000000000000000000000000000042 +:10AE10000000000000000000000000000000000032 +:10AE20000000000000000000000000000000000022 +:10AE30000000000000000000000000000000000012 +:10AE40000000000000000000000000000000000002 +:10AE500000000000000000000000000000000000F2 +:10AE600000000000000000000000000000000000E2 +:10AE700000000000000000000000000000000000D2 +:10AE800000000000000000000000000000000000C2 +:10AE900000000000000000000000000000000000B2 +:10AEA00000000000000000000000000000000000A2 +:10AEB0000000000000000000000000000000000092 +:10AEC0000000000000000000000000000000000082 +:10AED0000000000000000000000000000000000072 +:10AEE0000000000000000000000000000000000062 +:10AEF0000000000000000000000000000000000052 +:10AF00000000000000000000000000000000000041 +:10AF10000000000000000000000000000000000031 +:10AF20000000000000000000000000000000000021 +:10AF30000000000000000000000000000000000011 +:10AF40000000000000000000000000000000000001 +:10AF500000000000000000000000000000000000F1 +:10AF600000000000000000000000000000000000E1 +:10AF700000000000000000000000000000000000D1 +:10AF800000000000000000000000000000000000C1 +:10AF900000000000000000000000000000000000B1 +:10AFA00000000000000000000000000000000000A1 +:10AFB0000000000000000000000000000000000091 +:10AFC0000000000000000000000000000000000081 +:10AFD0000000000000000000000000000000000071 +:10AFE0000000000000000000000000000000000061 +:10AFF0000000000000000000000000000000000051 +:10B000000000000000000000000000000000000040 +:10B010000000000000000000000000000000000030 +:10B020000000000000000000000000000000000020 +:10B030000000000000000000000000000000000010 +:10B040000000000000000000000000000000000000 +:10B0500000000000000000000000000000000000F0 +:10B0600000000000000000000000000000000000E0 +:10B0700000000000000000000000000000000000D0 +:10B0800000000000000000000000000000000000C0 +:10B0900000000000000000000000000000000000B0 +:10B0A00000000000000000000000000000000000A0 +:10B0B0000000000000000000000000000000000090 +:10B0C0000000000000000000000000000000000080 +:10B0D0000000000000000000000000000000000070 +:10B0E0000000000000000000000000000000000060 +:10B0F0000000000000000000000000000000000050 +:10B10000000000000000000000000000000000003F +:10B11000000000000000000000000000000000002F +:10B12000000000000000000000000000000000001F +:10B13000000000000000000000000000000000000F +:10B1400000000000000000000000000000000000FF +:10B1500000000000000000000000000000000000EF +:10B1600000000000000000000000000000000000DF +:10B1700000000000000000000000000000000000CF +:10B1800000000000000000000000000000000000BF +:10B1900000000000000000000000000000000000AF +:10B1A000000000000000000000000000000000009F +:10B1B000000000000000000000000000000000008F +:10B1C000000000000000000000000000000000007F +:10B1D000000000000000000000000000000000006F +:10B1E000000000000000000000000000000000005F +:10B1F000000000000000000000000000000000004F +:10B20000000000000000000000000000000000003E +:10B21000000000000000000000000000000000002E +:10B22000000000000000000000000000000000001E +:10B23000000000000000000000000000000000000E +:10B2400000000000000000000000000000000000FE +:10B2500000000000000000000000000000000000EE +:10B2600000000000000000000000000000000000DE +:10B2700000000000000000000000000000000000CE +:10B2800000000000000000000000000000000000BE +:10B2900000000000000000000000000000000000AE +:10B2A000000000000000000000000000000000009E +:10B2B000000000000000000000000000000000008E +:10B2C000000000000000000000000000000000007E +:10B2D000000000000000000000000000000000006E +:10B2E000000000000000000000000000000000005E +:10B2F000000000000000000000000000000000004E +:10B30000000000000000000000000000000000003D +:10B31000000000000000000000000000000000002D +:10B32000000000000000000000000000000000001D +:10B33000000000000000000000000000000000000D +:10B3400000000000000000000000000000000000FD +:10B3500000000000000000000000000000000000ED +:10B3600000000000000000000000000000000000DD +:10B3700000000000000000000000000000000000CD +:10B3800000000000000000000000000000000000BD +:10B3900000000000000000000000000000000000AD +:10B3A000000000000000000000000000000000009D +:10B3B000000000000000000000000000000000008D +:10B3C000000000000000000000000000000000007D +:10B3D000000000000000000000000000000000006D +:10B3E000000000000000000000000000000000005D +:10B3F000000000000000000000000000000000004D +:10B40000000000000000000000000000000000003C +:10B41000000000000000000000000000000000002C +:10B42000000000000000000000000000000000001C +:10B43000000000000000000000000000000000000C +:10B4400000000000000000000000000000000000FC +:10B4500000000000000000000000000000000000EC +:10B4600000000000000000000000000000000000DC +:10B4700000000000000000000000000000000000CC +:10B4800000000000000000000000000000000000BC +:10B4900000000000000000000000000000000000AC +:10B4A000000000000000000000000000000000009C +:10B4B000000000000000000000000000000000008C +:10B4C000000000000000000000000000000000007C +:10B4D000000000000000000000000000000000006C +:10B4E000000000000000000000000000000000005C +:10B4F000000000000000000000000000000000004C +:10B50000000000000000000000000000000000003B +:10B51000000000000000000000000000000000002B +:10B52000000000000000000000000000000000001B +:10B53000000000000000000000000000000000000B +:10B5400000000000000000000000000000000000FB +:10B5500000000000000000000000000000000000EB +:10B5600000000000000000000000000000000000DB +:10B5700000000000000000000000000000000000CB +:10B5800000000000000000000000000000000000BB +:10B5900000000000000000000000000000000000AB +:10B5A000000000000000000000000000000000009B +:10B5B000000000000000000000000000000000008B +:10B5C000000000000000000000000000000000007B +:10B5D000000000000000000000000000000000006B +:10B5E000000000000000000000000000000000005B +:10B5F000000000000000000000000000000000004B +:10B60000000000000000000000000000000000003A +:10B61000000000000000000000000000000000002A +:10B62000000000000000000000000000000000001A +:10B63000000000000000000000000000000000000A +:10B6400000000000000000000000000000000000FA +:10B6500000000000000000000000000000000000EA +:10B6600000000000000000000000000000000000DA +:10B6700000000000000000000000000000000000CA +:10B6800000000000000000000000000000000000BA +:10B6900000000000000000000000000000000000AA +:10B6A000000000000000000000000000000000009A +:10B6B000000000000000000000000000000000008A +:10B6C000000000000000000000000000000000007A +:10B6D000000000000000000000000000000000006A +:10B6E000000000000000000000000000000000005A +:10B6F000000000000000000000000000000000004A +:10B700000000000000000000000000000000000039 +:10B710000000000000000000000000000000000029 +:10B720000000000000000000000000000000000019 +:10B730000000000000000000000000000000000009 +:10B7400000000000000000000000000000000000F9 +:10B7500000000000000000000000000000000000E9 +:10B7600000000000000000000000000000000000D9 +:10B7700000000000000000000000000000000000C9 +:10B7800000000000000000000000000000000000B9 +:10B7900000000000000000000000000000000000A9 +:10B7A0000000000000000000000000000000000099 +:10B7B0000000000000000000000000000000000089 +:10B7C0000000000000000000000000000000000079 +:10B7D0000000000000000000000000000000000069 +:10B7E0000000000000000000000000000000000059 +:10B7F0000000000000000000000000000000000049 +:10B800000000000000000000000000000000000038 +:10B810000000000000000000000000000000000028 +:10B820000000000000000000000000000000000018 +:10B830000000000000000000000000000000000008 +:10B8400000000000000000000000000000000000F8 +:10B8500000000000000000000000000000000000E8 +:10B8600000000000000000000000000000000000D8 +:10B8700000000000000000000000000000000000C8 +:10B8800000000000000000000000000000000000B8 +:10B8900000000000000000000000000000000000A8 +:10B8A0000000000000000000000000000000000098 +:10B8B0000000000000000000000000000000000088 +:10B8C0000000000000000000000000000000000078 +:10B8D0000000000000000000000000000000000068 +:10B8E0000000000000000000000000000000000058 +:10B8F0000000000000000000000000000000000048 +:10B900000000000000000000000000000000000037 +:10B910000000000000000000000000000000000027 +:10B920000000000000000000000000000000000017 +:10B930000000000000000000000000000000000007 +:10B9400000000000000000000000000000000000F7 +:10B9500000000000000000000000000000000000E7 +:10B9600000000000000000000000000000000000D7 +:10B9700000000000000000000000000000000000C7 +:10B9800000000000000000000000000000000000B7 +:10B9900000000000000000000000000000000000A7 +:10B9A0000000000000000000000000000000000097 +:10B9B0000000000000000000000000000000000087 +:10B9C0000000000000000000000000000000000077 +:10B9D0000000000000000000000000000000000067 +:10B9E0000000000000000000000000000000000057 +:10B9F0000000000000000000000000000000000047 +:10BA00000000000000000000000000000000000036 +:10BA10000000000000000000000000000000000026 +:10BA20000000000000000000000000000000000016 +:10BA30000000000000000000000000000000000006 +:10BA400000000000000000000000000000000000F6 +:10BA500000000000000000000000000000000000E6 +:10BA600000000000000000000000000000000000D6 +:10BA700000000000000000000000000000000000C6 +:10BA800000000000000000000000000000000000B6 +:10BA900000000000000000000000000000000000A6 +:10BAA0000000000000000000000000000000000096 +:10BAB0000000000000000000000000000000000086 +:10BAC0000000000000000000000000000000000076 +:10BAD0000000000000000000000000000000000066 +:10BAE0000000000000000000000000000000000056 +:10BAF0000000000000000000000000000000000046 +:10BB00000000000000000000000000000000000035 +:10BB10000000000000000000000000000000000025 +:10BB20000000000000000000000000000000000015 +:10BB30000000000000000000000000000000000005 +:10BB400000000000000000000000000000000000F5 +:10BB500000000000000000000000000000000000E5 +:10BB600000000000000000000000000000000000D5 +:10BB700000000000000000000000000000000000C5 +:10BB800000000000000000000000000000000000B5 +:10BB900000000000000000000000000000000000A5 +:10BBA0000000000000000000000000000000000095 +:10BBB0000000000000000000000000000000000085 +:10BBC0000000000000000000000000000000000075 +:10BBD0000000000000000000000000000000000065 +:10BBE0000000000000000000000000000000000055 +:10BBF0000000000000000000000000000000000045 +:10BC00000000000000000000000000000000000034 +:10BC10000000000000000000000000000000000024 +:10BC20000000000000000000000000000000000014 +:10BC30000000000000000000000000000000000004 +:10BC400000000000000000000000000000000000F4 +:10BC500000000000000000000000000000000000E4 +:10BC600000000000000000000000000000000000D4 +:10BC700000000000000000000000000000000000C4 +:10BC800000000000000000000000000000000000B4 +:10BC900000000000000000000000000000000000A4 +:10BCA0000000000000000000000000000000000094 +:10BCB0000000000000000000000000000000000084 +:10BCC0000000000000000000000000000000000074 +:10BCD0000000000000000000000000000000000064 +:10BCE0000000000000000000000000000000000054 +:10BCF0000000000000000000000000000000000044 +:10BD00000000000000000000000000000000000033 +:10BD10000000000000000000000000000000000023 +:10BD20000000000000000000000000000000000013 +:10BD30000000000000000000000000000000000003 +:10BD400000000000000000000000000000000000F3 +:10BD500000000000000000000000000000000000E3 +:10BD600000000000000000000000000000000000D3 +:10BD700000000000000000000000000000000000C3 +:10BD800000000000000000000000000000000000B3 +:10BD900000000000000000000000000000000000A3 +:10BDA0000000000000000000000000000000000093 +:10BDB0000000000000000000000000000000000083 +:10BDC0000000000000000000000000000000000073 +:10BDD0000000000000000000000000000000000063 +:10BDE0000000000000000000000000000000000053 +:10BDF0000000000000000000000000000000000043 +:10BE00000000000000000000000000000000000032 +:10BE10000000000000000000000000000000000022 +:10BE20000000000000000000000000000000000012 +:10BE30000000000000000000000000000000000002 +:10BE400000000000000000000000000000000000F2 +:10BE500000000000000000000000000000000000E2 +:10BE600000000000000000000000000000000000D2 +:10BE700000000000000000000000000000000000C2 +:10BE800000000000000000000000000000000000B2 +:10BE900000000000000000000000000000000000A2 +:10BEA0000000000000000000000000000000000092 +:10BEB0000000000000000000000000000000000082 +:10BEC0000000000000000000000000000000000072 +:10BED0000000000000000000000000000000000062 +:10BEE0000000000000000000000000000000000052 +:10BEF0000000000000000000000000000000000042 +:10BF00000000000000000000000000000000000031 +:10BF10000000000000000000000000000000000021 +:10BF20000000000000000000000000000000000011 +:10BF30000000000000000000000000000000000001 +:10BF400000000000000000000000000000000000F1 +:10BF500000000000000000000000000000000000E1 +:10BF600000000000000000000000000000000000D1 +:10BF700000000000000000000000000000000000C1 +:10BF800000000000000000000000000000000000B1 +:10BF900000000000000000000000000000000000A1 +:10BFA0000000000000000000000000000000000091 +:10BFB0000000000000000000000000000000000081 +:10BFC0000000000000000000000000000000000071 +:10BFD0000000000000000000000000000000000061 +:10BFE0000000000000000000000000000000000051 +:10BFF0000000000000000000000000000000000041 +:10C000000000000000000000000000000000000030 +:10C010000000000000000000000000000000000020 +:10C020000000000000000000000000000000000010 +:10C030000000000000000000000000000000000000 +:10C0400000000000000000000000000000000000F0 +:10C0500000000000000000000000000000000000E0 +:10C0600000000000000000000000000000000000D0 +:10C0700000000000000000000000000000000000C0 +:10C0800000000000000000000000000000000000B0 +:10C0900000000000000000000000000000000000A0 +:10C0A0000000000000000000000000000000000090 +:10C0B0000000000000000000000000000000000080 +:10C0C0000000000000000000000000000000000070 +:10C0D0000000000000000000000000000000000060 +:10C0E0000000000000000000000000000000000050 +:10C0F0000000000000000000000000000000000040 +:10C10000000000000000000000000000000000002F +:10C11000000000000000000000000000000000001F +:10C12000000000000000000000000000000000000F +:10C1300000000000000000000000000000000000FF +:10C1400000000000000000000000000000000000EF +:10C1500000000000000000000000000000000000DF +:10C1600000000000000000000000000000000000CF +:10C1700000000000000000000000000000000000BF +:10C1800000000000000000000000000000000000AF +:10C19000000000000000000000000000000000009F +:10C1A000000000000000000000000000000000008F +:10C1B000000000000000000000000000000000007F +:10C1C000000000000000000000000000000000006F +:10C1D000000000000000000000000000000000005F +:10C1E000000000000000000000000000000000004F +:10C1F000000000000000000000000000000000003F +:10C20000000000000000000000000000000000002E +:10C21000000000000000000000000000000000001E +:10C22000000000000000000000000000000000000E +:10C2300000000000000000000000000000000000FE +:10C2400000000000000000000000000000000000EE +:10C2500000000000000000000000000000000000DE +:10C2600000000000000000000000000000000000CE +:10C2700000000000000000000000000000000000BE +:10C2800000000000000000000000000000000000AE +:10C29000000000000000000000000000000000009E +:10C2A000000000000000000000000000000000008E +:10C2B000000000000000000000000000000000007E +:10C2C000000000000000000000000000000000006E +:10C2D000000000000000000000000000000000005E +:10C2E000000000000000000000000000000000004E +:10C2F000000000000000000000000000000000003E +:10C30000000000000000000000000000000000002D +:10C31000000000000000000000000000000000001D +:10C32000000000000000000000000000000000000D +:10C3300000000000000000000000000000000000FD +:10C3400000000000000000000000000000000000ED +:10C3500000000000000000000000000000000000DD +:10C3600000000000000000000000000000000000CD +:10C3700000000000000000000000000000000000BD +:10C3800000000000000000000000000000000000AD +:10C39000000000000000000000000000000000009D +:10C3A000000000000000000000000000000000008D +:10C3B000000000000000000000000000000000007D +:10C3C000000000000000000000000000000000006D +:10C3D000000000000000000000000000000000005D +:10C3E000000000000000000000000000000000004D +:10C3F000000000000000000000000000000000003D +:10C40000000000000000000000000000000000002C +:10C41000000000000000000000000000000000001C +:10C42000000000000000000000000000000000000C +:10C4300000000000000000000000000000000000FC +:10C4400000000000000000000000000000000000EC +:10C4500000000000000000000000000000000000DC +:10C4600000000000000000000000000000000000CC +:10C4700000000000000000000000000000000000BC +:10C4800000000000000000000000000000000000AC +:10C49000000000000000000000000000000000009C +:10C4A000000000000000000000000000000000008C +:10C4B000000000000000000000000000000000007C +:10C4C000000000000000000000000000000000006C +:10C4D000000000000000000000000000000000005C +:10C4E000000000000000000000000000000000004C +:10C4F000000000000000000000000000000000003C +:10C50000000000000000000000000000000000002B +:10C51000000000000000000000000000000000001B +:10C52000000000000000000000000000000000000B +:10C5300000000000000000000000000000000000FB +:10C5400000000000000000000000000000000000EB +:10C5500000000000000000000000000000000000DB +:10C5600000000000000000000000000000000000CB +:10C5700000000000000000000000000000000000BB +:10C5800000000000000000000000000000000000AB +:10C59000000000000000000000000000000000009B +:10C5A000000000000000000000000000000000008B +:10C5B000000000000000000000000000000000007B +:10C5C000000000000000000000000000000000006B +:10C5D000000000000000000000000000000000005B +:10C5E000000000000000000000000000000000004B +:10C5F000000000000000000000000000000000003B +:10C60000000000000000000000000000000000002A +:10C61000000000000000000000000000000000001A +:10C62000000000000000000000000000000000000A +:10C6300000000000000000000000000000000000FA +:10C6400000000000000000000000000000000000EA +:10C6500000000000000000000000000000000000DA +:10C6600000000000000000000000000000000000CA +:10C6700000000000000000000000000000000000BA +:10C6800000000000000000000000000000000000AA +:10C69000000000000000000000000000000000009A +:10C6A000000000000000000000000000000000008A +:10C6B000000000000000000000000000000000007A +:10C6C000000000000000000000000000000000006A +:10C6D000000000000000000000000000000000005A +:10C6E000000000000000000000000000000000004A +:10C6F000000000000000000000000000000000003A +:10C700000000000000000000000000000000000029 +:10C710000000000000000000000000000000000019 +:10C720000000000000000000000000000000000009 +:10C7300000000000000000000000000000000000F9 +:10C7400000000000000000000000000000000000E9 +:10C7500000000000000000000000000000000000D9 +:10C7600000000000000000000000000000000000C9 +:10C7700000000000000000000000000000000000B9 +:10C7800000000000000000000000000000000000A9 +:10C790000000000000000000000000000000000099 +:10C7A0000000000000000000000000000000000089 +:10C7B0000000000000000000000000000000000079 +:10C7C0000000000000000000000000000000000069 +:10C7D0000000000000000000000000000000000059 +:10C7E0000000000000000000000000000000000049 +:10C7F0000000000000000000000000000000000039 +:10C800000000000000000000000000000000000028 +:10C810000000000000000000000000000000000018 +:10C820000000000000000000000000000000000008 +:10C8300000000000000000000000000000000000F8 +:10C8400000000000000000000000000000000000E8 +:10C8500000000000000000000000000000000000D8 +:10C8600000000000000000000000000000000000C8 +:10C8700000000000000000000000000000000000B8 +:10C8800000000000000000000000000000000000A8 +:10C890000000000000000000000000000000000098 +:10C8A0000000000000000000000000000000000088 +:10C8B0000000000000000000000000000000000078 +:10C8C0000000000000000000000000000000000068 +:10C8D0000000000000000000000000000000000058 +:10C8E0000000000000000000000000000000000048 +:10C8F0000000000000000000000000000000000038 +:10C900000000000000000000000000000000000027 +:10C910000000000000000000000000000000000017 +:10C920000000000000000000000000000000000007 +:10C9300000000000000000000000000000000000F7 +:10C9400000000000000000000000000000000000E7 +:10C9500000000000000000000000000000000000D7 +:10C9600000000000000000000000000000000000C7 +:10C9700000000000000000000000000000000000B7 +:10C9800000000000000000000000000000000000A7 +:10C990000000000000000000000000000000000097 +:10C9A0000000000000000000000000000000000087 +:10C9B0000000000000000000000000000000000077 +:10C9C0000000000000000000000000000000000067 +:10C9D0000000000000000000000000000000000057 +:10C9E0000000000000000000000000000000000047 +:10C9F0000000000000000000000000000000000037 +:10CA00000000000000000000000000000000000026 +:10CA10000000000000000000000000000000000016 +:10CA20000000000000000000000000000000000006 +:10CA300000000000000000000000000000000000F6 +:10CA400000000000000000000000000000000000E6 +:10CA500000000000000000000000000000000000D6 +:10CA600000000000000000000000000000000000C6 +:10CA700000000000000000000000000000000000B6 +:10CA800000000000000000000000000000000000A6 +:10CA90000000000000000000000000000000000096 +:10CAA0000000000000000000000000000000000086 +:10CAB0000000000000000000000000000000000076 +:10CAC0000000000000000000000000000000000066 +:10CAD0000000000000000000000000000000000056 +:10CAE0000000000000000000000000000000000046 +:10CAF0000000000000000000000000000000000036 +:10CB00000000000000000000000000000000000025 +:10CB10000000000000000000000000000000000015 +:10CB20000000000000000000000000000000000005 +:10CB300000000000000000000000000000000000F5 +:10CB400000000000000000000000000000000000E5 +:10CB500000000000000000000000000000000000D5 +:10CB600000000000000000000000000000000000C5 +:10CB700000000000000000000000000000000000B5 +:10CB800000000000000000000000000000000000A5 +:10CB90000000000000000000000000000000000095 +:10CBA0000000000000000000000000000000000085 +:10CBB0000000000000000000000000000000000075 +:10CBC0000000000000000000000000000000000065 +:10CBD0000000000000000000000000000000000055 +:10CBE0000000000000000000000000000000000045 +:10CBF0000000000000000000000000000000000035 +:10CC00000000000000000000000000000000000024 +:10CC10000000000000000000000000000000000014 +:10CC20000000000000000000000000000000000004 +:10CC300000000000000000000000000000000000F4 +:10CC400000000000000000000000000000000000E4 +:10CC500000000000000000000000000000000000D4 +:10CC600000000000000000000000000000000000C4 +:10CC700000000000000000000000000000000000B4 +:10CC800000000000000000000000000000000000A4 +:10CC90000000000000000000000000000000000094 +:10CCA0000000000000000000000000000000000084 +:10CCB0000000000000000000000000000000000074 +:10CCC0000000000000000000000000000000000064 +:10CCD0000000000000000000000000000000000054 +:10CCE0000000000000000000000000000000000044 +:10CCF0000000000000000000000000000000000034 +:10CD00000000000000000000000000000000000023 +:10CD10000000000000000000000000000000000013 +:10CD20000000000000000000000000000000000003 +:10CD300000000000000000000000000000000000F3 +:10CD400000000000000000000000000000000000E3 +:10CD500000000000000000000000000000000000D3 +:10CD600000000000000000000000000000000000C3 +:10CD700000000000000000000000000000000000B3 +:10CD800000000000000000000000000000000000A3 +:10CD90000000000000000000000000000000000093 +:10CDA0000000000000000000000000000000000083 +:10CDB0000000000000000000000000000000000073 +:10CDC0000000000000000000000000000000000063 +:10CDD0000000000000000000000000000000000053 +:10CDE0000000000000000000000000000000000043 +:10CDF0000000000000000000000000000000000033 +:10CE00000000000000000000000000000000000022 +:10CE10000000000000000000000000000000000012 +:10CE20000000000000000000000000000000000002 +:10CE300000000000000000000000000000000000F2 +:10CE400000000000000000000000000000000000E2 +:10CE500000000000000000000000000000000000D2 +:10CE600000000000000000000000000000000000C2 +:10CE700000000000000000000000000000000000B2 +:10CE800000000000000000000000000000000000A2 +:10CE90000000000000000000000000000000000092 +:10CEA0000000000000000000000000000000000082 +:10CEB0000000000000000000000000000000000072 +:10CEC0000000000000000000000000000000000062 +:10CED0000000000000000000000000000000000052 +:10CEE0000000000000000000000000000000000042 +:10CEF0000000000000000000000000000000000032 +:10CF00000000000000000000000000000000000021 +:10CF10000000000000000000000000000000000011 +:10CF20000000000000000000000000000000000001 +:10CF300000000000000000000000000000000000F1 +:10CF400000000000000000000000000000000000E1 +:10CF500000000000000000000000000000000000D1 +:10CF600000000000000000000000000000000000C1 +:10CF700000000000000000000000000000000000B1 +:10CF800000000000000000000000000000000000A1 +:10CF90000000000000000000000000000000000091 +:10CFA0000000000000000000000000000000000081 +:10CFB0000000000000000000000000000000000071 +:10CFC0000000000000000000000000000000000061 +:10CFD0000000000000000000000000000000000051 +:10CFE0000000000000000000000000000000000041 +:10CFF0000000000000000000000000000000000031 +:10D000000000000000000000000000000000000020 +:10D010000000000000000000000000000000000010 +:10D020000000000000000000000000000000000000 +:10D0300000000000000000000000000000000000F0 +:10D0400000000000000000000000000000000000E0 +:10D0500000000000000000000000000000000000D0 +:10D0600000000000000000000000000000000000C0 +:10D0700000000000000000000000000000000000B0 +:10D0800000000000000000000000000000000000A0 +:10D090000000000000000000000000000000000090 +:10D0A0000000000000000000000000000000000080 +:10D0B0000000000000000000000000000000000070 +:10D0C0000000000000000000000000000000000060 +:10D0D0000000000000000000000000000000000050 +:10D0E0000000000000000000000000000000000040 +:10D0F0000000000000000000000000000000000030 +:10D10000000000000000000000000000000000001F +:10D11000000000000000000000000000000000000F +:10D1200000000000000000000000000000000000FF +:10D1300000000000000000000000000000000000EF +:10D1400000000000000000000000000000000000DF +:10D1500000000000000000000000000000000000CF +:10D1600000000000000000000000000000000000BF +:10D1700000000000000000000000000000000000AF +:10D18000000000000000000000000000000000009F +:10D19000000000000000000000000000000000008F +:10D1A000000000000000000000000000000000007F +:10D1B000000000000000000000000000000000006F +:10D1C000000000000000000000000000000000005F +:10D1D000000000000000000000000000000000004F +:10D1E000000000000000000000000000000000003F +:10D1F000000000000000000000000000000000002F +:10D20000000000000000000000000000000000001E +:10D21000000000000000000000000000000000000E +:10D2200000000000000000000000000000000000FE +:10D2300000000000000000000000000000000000EE +:10D2400000000000000000000000000000000000DE +:10D2500000000000000000000000000000000000CE +:10D2600000000000000000000000000000000000BE +:10D2700000000000000000000000000000000000AE +:10D28000000000000000000000000000000000009E +:10D29000000000000000000000000000000000008E +:10D2A000000000000000000000000000000000007E +:10D2B000000000000000000000000000000000006E +:10D2C000000000000000000000000000000000005E +:10D2D000000000000000000000000000000000004E +:10D2E000000000000000000000000000000000003E +:10D2F000000000000000000000000000000000002E +:10D30000000000000000000000000000000000001D +:10D31000000000000000000000000000000000000D +:10D3200000000000000000000000000000000000FD +:10D3300000000000000000000000000000000000ED +:10D3400000000000000000000000000000000000DD +:10D3500000000000000000000000000000000000CD +:10D3600000000000000000000000000000000000BD +:10D3700000000000000000000000000000000000AD +:10D38000000000000000000000000000000000009D +:10D39000000000000000000000000000000000008D +:10D3A000000000000000000000000000000000007D +:10D3B000000000000000000000000000000000006D +:10D3C000000000000000000000000000000000005D +:10D3D000000000000000000000000000000000004D +:10D3E000000000000000000000000000000000003D +:10D3F000000000000000000000000000000000002D +:10D40000000000000000000000000000000000001C +:10D41000000000000000000000000000000000000C +:10D4200000000000000000000000000000000000FC +:10D4300000000000000000000000000000000000EC +:10D4400000000000000000000000000000000000DC +:10D4500000000000000000000000000000000000CC +:10D4600000000000000000000000000000000000BC +:10D4700000000000000000000000000000000000AC +:10D48000000000000000000000000000000000009C +:10D49000000000000000000000000000000000008C +:10D4A000000000000000000000000000000000007C +:10D4B000000000000000000000000000000000006C +:10D4C000000000000000000000000000000000005C +:10D4D000000000000000000000000000000000004C +:10D4E000000000000000000000000000000000003C +:10D4F000000000000000000000000000000000002C +:10D50000000000000000000000000000000000001B +:10D51000000000000000000000000000000000000B +:10D5200000000000000000000000000000000000FB +:10D5300000000000000000000000000000000000EB +:10D5400000000000000000000000000000000000DB +:10D5500000000000000000000000000000000000CB +:10D5600000000000000000000000000000000000BB +:10D5700000000000000000000000000000000000AB +:10D58000000000000000000000000000000000009B +:10D59000000000000000000000000000000000008B +:10D5A000000000000000000000000000000000007B +:10D5B000000000000000000000000000000000006B +:10D5C000000000000000000000000000000000005B +:10D5D000000000000000000000000000000000004B +:10D5E000000000000000000000000000000000003B +:10D5F000000000000000000000000000000000002B +:10D60000000000000000000000000000000000001A +:10D61000000000000000000000000000000000000A +:10D6200000000000000000000000000000000000FA +:10D6300000000000000000000000000000000000EA +:10D6400000000000000000000000000000000000DA +:10D6500000000000000000000000000000000000CA +:10D6600000000000000000000000000000000000BA +:10D6700000000000000000000000000000000000AA +:10D68000000000000000000000000000000000009A +:10D69000000000000000000000000000000000008A +:10D6A000000000000000000000000000000000007A +:10D6B000000000000000000000000000000000006A +:10D6C000000000000000000000000000000000005A +:10D6D000000000000000000000000000000000004A +:10D6E000000000000000000000000000000000003A +:10D6F000000000000000000000000000000000002A +:10D700000000000000000000000000000000000019 +:10D710000000000000000000000000000000000009 +:10D7200000000000000000000000000000000000F9 +:10D7300000000000000000000000000000000000E9 +:10D7400000000000000000000000000000000000D9 +:10D7500000000000000000000000000000000000C9 +:10D7600000000000000000000000000000000000B9 +:10D7700000000000000000000000000000000000A9 +:10D780000000000000000000000000000000000099 +:10D790000000000000000000000000000000000089 +:10D7A0000000000000000000000000000000000079 +:10D7B0000000000000000000000000000000000069 +:10D7C0000000000000000000000000000000000059 +:10D7D0000000000000000000000000000000000049 +:10D7E0000000000000000000000000000000000039 +:10D7F0000000000000000000000000000000000029 +:10D800000000000000000000000000000000000018 +:10D810000000000000000000000000000000000008 +:10D8200000000000000000000000000000000000F8 +:10D8300000000000000000000000000000000000E8 +:10D8400000000000000000000000000000000000D8 +:10D8500000000000000000000000000000000000C8 +:10D8600000000000000000000000000000000000B8 +:10D8700000000000000000000000000000000000A8 +:10D880000000000000000000000000000000000098 +:10D890000000000000000000000000000000000088 +:10D8A0000000000000000000000000000000000078 +:10D8B0000000000000000000000000000000000068 +:10D8C0000000000000000000000000000000000058 +:10D8D0000000000000000000000000000000000048 +:10D8E0000000000000000000000000000000000038 +:10D8F0000000000000000000000000000000000028 +:10D900000000000000000000000000000000000017 +:10D910000000000000000000000000000000000007 +:10D9200000000000000000000000000000000000F7 +:10D9300000000000000000000000000000000000E7 +:10D9400000000000000000000000000000000000D7 +:10D9500000000000000000000000000000000000C7 +:10D9600000000000000000000000000000000000B7 +:10D9700000000000000000000000000000000000A7 +:10D980000000000000000000000000000000000097 +:10D990000000000000000000000000000000000087 +:10D9A0000000000000000000000000000000000077 +:10D9B0000000000000000000000000000000000067 +:10D9C0000000000000000000000000000000000057 +:10D9D0000000000000000000000000000000000047 +:10D9E0000000000000000000000000000000000037 +:10D9F0000000000000000000000000000000000027 +:10DA00000000000000000000000000000000000016 +:10DA10000000000000000000000000000000000006 +:10DA200000000000000000000000000000000000F6 +:10DA300000000000000000000000000000000000E6 +:10DA400000000000000000000000000000000000D6 +:10DA500000000000000000000000000000000000C6 +:10DA600000000000000000000000000000000000B6 +:10DA700000000000000000000000000000000000A6 +:10DA80000000000000000000000000000000000096 +:10DA90000000000000000000000000000000000086 +:10DAA0000000000000000000000000000000000076 +:10DAB0000000000000000000000000000000000066 +:10DAC0000000000000000000000000000000000056 +:10DAD0000000000000000000000000000000000046 +:10DAE0000000000000000000000000000000000036 +:10DAF0000000000000000000000000000000000026 +:10DB00000000000000000000000000000000000015 +:10DB10000000000000000000000000000000000005 +:10DB200000000000000000000000000000000000F5 +:10DB300000000000000000000000000000000000E5 +:10DB400000000000000000000000000000000000D5 +:10DB500000000000000000000000000000000000C5 +:10DB600000000000000000000000000000000000B5 +:10DB700000000000000000000000000000000000A5 +:10DB80000000000000000000000000000000000095 +:10DB90000000000000000000000000000000000085 +:10DBA0000000000000000000000000000000000075 +:10DBB0000000000000000000000000000000000065 +:10DBC0000000000000000000000000000000000055 +:10DBD0000000000000000000000000000000000045 +:10DBE0000000000000000000000000000000000035 +:10DBF0000000000000000000000000000000000025 +:10DC00000000000000000000000000000000000014 +:10DC10000000000000000000000000000000000004 +:10DC200000000000000000000000000000000000F4 +:10DC300000000000000000000000000000000000E4 +:10DC400000000000000000000000000000000000D4 +:10DC500000000000000000000000000000000000C4 +:10DC600000000000000000000000000000000000B4 +:10DC700000000000000000000000000000000000A4 +:10DC80000000000000000000000000000000000094 +:10DC90000000000000000000000000000000000084 +:10DCA0000000000000000000000000000000000074 +:10DCB0000000000000000000000000000000000064 +:10DCC0000000000000000000000000000000000054 +:10DCD0000000000000000000000000000000000044 +:10DCE0000000000000000000000000000000000034 +:10DCF0000000000000000000000000000000000024 +:10DD00000000000000000000000000000000000013 +:10DD10000000000000000000000000000000000003 +:10DD200000000000000000000000000000000000F3 +:10DD300000000000000000000000000000000000E3 +:10DD400000000000000000000000000000000000D3 +:10DD500000000000000000000000000000000000C3 +:10DD600000000000000000000000000000000000B3 +:10DD700000000000000000000000000000000000A3 +:10DD80000000000000000000000000000000000093 +:10DD90000000000000000000000000000000000083 +:10DDA0000000000000000000000000000000000073 +:10DDB0000000000000000000000000000000000063 +:10DDC0000000000000000000000000000000000053 +:10DDD0000000000000000000000000000000000043 +:10DDE0000000000000000000000000000000000033 +:10DDF0000000000000000000000000000000000023 +:10DE00000000000000000000000000000000000012 +:10DE10000000000000000000000000000000000002 +:10DE200000000000000000000000000000000000F2 +:10DE300000000000000000000000000000000000E2 +:10DE400000000000000000000000000000000000D2 +:10DE500000000000000000000000000000000000C2 +:10DE600000000000000000000000000000000000B2 +:10DE700000000000000000000000000000000000A2 +:10DE80000000000000000000000000000000000092 +:10DE90000000000000000000000000000000000082 +:10DEA0000000000000000000000000000000000072 +:10DEB0000000000000000000000000000000000062 +:10DEC0000000000000000000000000000000000052 +:10DED0000000000000000000000000000000000042 +:10DEE0000000000000000000000000000000000032 +:10DEF0000000000000000000000000000000000022 +:10DF00000000000000000000000000000000000011 +:10DF10000000000000000000000000000000000001 +:10DF200000000000000000000000000000000000F1 +:10DF300000000000000000000000000000000000E1 +:10DF400000000000000000000000000000000000D1 +:10DF500000000000000000000000000000000000C1 +:10DF600000000000000000000000000000000000B1 +:10DF700000000000000000000000000000000000A1 +:10DF80000000000000000000000000000000000091 +:10DF90000000000000000000000000000000000081 +:10DFA0000000000000000000000000000000000071 +:10DFB0000000000000000000000000000000000061 +:10DFC0000000000000000000000000000000000051 +:10DFD0000000000000000000000000000000000041 +:10DFE0000000000000000000000000000000000031 +:10DFF0000000000000000000000000000000000021 +:10E000000000000000000000000000000000000010 +:10E010000000000000000000000000000000000000 +:10E0200000000000000000000000000000000000F0 +:10E0300000000000000000000000000000000000E0 +:10E0400000000000000000000000000000000000D0 +:10E0500000000000000000000000000000000000C0 +:10E0600000000000000000000000000000000000B0 +:10E0700000000000000000000000000000000000A0 +:10E080000000000000000000000000000000000090 +:10E090000000000000000000000000000000000080 +:10E0A0000000000000000000000000000000000070 +:10E0B0000000000000000000000000000000000060 +:10E0C0000000000000000000000000000000000050 +:10E0D0000000000000000000000000000000000040 +:10E0E0000000000000000000000000000000000030 +:10E0F0000000000000000000000000000000000020 +:10E10000000000000000000000000000000000000F +:10E1100000000000000000000000000000000000FF +:10E1200000000000000000000000000000000000EF +:10E1300000000000000000000000000000000000DF +:10E1400000000000000000000000000000000000CF +:10E1500000000000000000000000000000000000BF +:10E1600000000000000000000000000000000000AF +:10E17000000000000000000000000000000000009F +:10E18000000000000000000000000000000000008F +:10E19000000000000000000000000000000000007F +:10E1A000000000000000000000000000000000006F +:10E1B000000000000000000000000000000000005F +:10E1C000000000000000000000000000000000004F +:10E1D000000000000000000000000000000000003F +:10E1E000000000000000000000000000000000002F +:10E1F000000000000000000000000000000000001F +:10E20000000000000000000000000000000000000E +:10E2100000000000000000000000000000000000FE +:10E2200000000000000000000000000000000000EE +:10E2300000000000000000000000000000000000DE +:10E2400000000000000000000000000000000000CE +:10E2500000000000000000000000000000000000BE +:10E2600000000000000000000000000000000000AE +:10E27000000000000000000000000000000000009E +:10E28000000000000000000000000000000000008E +:10E29000000000000000000000000000000000007E +:10E2A000000000000000000000000000000000006E +:10E2B000000000000000000000000000000000005E +:10E2C000000000000000000000000000000000004E +:10E2D000000000000000000000000000000000003E +:10E2E000000000000000000000000000000000002E +:10E2F000000000000000000000000000000000001E +:10E30000000000000000000000000000000000000D +:10E3100000000000000000000000000000000000FD +:10E3200000000000000000000000000000000000ED +:10E3300000000000000000000000000000000000DD +:10E3400000000000000000000000000000000000CD +:10E3500000000000000000000000000000000000BD +:10E3600000000000000000000000000000000000AD +:10E37000000000000000000000000000000000009D +:10E38000000000000000000000000000000000008D +:10E39000000000000000000000000000000000007D +:10E3A000000000000000000000000000000000006D +:10E3B000000000000000000000000000000000005D +:10E3C000000000000000000000000000000000004D +:10E3D000000000000000000000000000000000003D +:10E3E000000000000000000000000000000000002D +:10E3F000000000000000000000000000000000001D +:10E40000000000000000000000000000000000000C +:10E4100000000000000000000000000000000000FC +:10E4200000000000000000000000000000000000EC +:10E4300000000000000000000000000000000000DC +:10E4400000000000000000000000000000000000CC +:10E4500000000000000000000000000000000000BC +:10E4600000000000000000000000000000000000AC +:10E47000000000000000000000000000000000009C +:10E48000000000000000000000000000000000008C +:10E49000000000000000000000000000000000007C +:10E4A000000000000000000000000000000000006C +:10E4B000000000000000000000000000000000005C +:10E4C000000000000000000000000000000000004C +:10E4D000000000000000000000000000000000003C +:10E4E000000000000000000000000000000000002C +:10E4F000000000000000000000000000000000001C +:10E50000000000000000000000000000000000000B +:10E5100000000000000000000000000000000000FB +:10E5200000000000000000000000000000000000EB +:10E5300000000000000000000000000000000000DB +:10E5400000000000000000000000000000000000CB +:10E5500000000000000000000000000000000000BB +:10E5600000000000000000000000000000000000AB +:10E57000000000000000000000000000000000009B +:10E58000000000000000000000000000000000008B +:10E59000000000000000000000000000000000007B +:10E5A000000000000000000000000000000000006B +:10E5B000000000000000000000000000000000005B +:10E5C000000000000000000000000000000000004B +:10E5D000000000000000000000000000000000003B +:10E5E000000000000000000000000000000000002B +:10E5F000000000000000000000000000000000001B +:10E60000000000000000000000000000000000000A +:10E6100000000000000000000000000000000000FA +:10E6200000000000000000000000000000000000EA +:10E6300000000000000000000000000000000000DA +:10E6400000000000000000000000000000000000CA +:10E6500000000000000000000000000000000000BA +:10E6600000000000000000000000000000000000AA +:10E67000000000000000000000000000000000009A +:10E68000000000000000000000000000000000008A +:10E69000000000000000000000000000000000007A +:10E6A000000000000000000000000000000000006A +:10E6B000000000000000000000000000000000005A +:10E6C000000000000000000000000000000000004A +:10E6D000000000000000000000000000000000003A +:10E6E000000000000000000000000000000000002A +:10E6F000000000000000000000000000000000001A +:10E700000000000000000000000000000000000009 +:10E7100000000000000000000000000000000000F9 +:10E7200000000000000000000000000000000000E9 +:10E7300000000000000000000000000000000000D9 +:10E7400000000000000000000000000000000000C9 +:10E7500000000000000000000000000000000000B9 +:10E7600000000000000000000000000000000000A9 +:10E770000000000000000000000000000000000099 +:10E780000000000000000000000000000000000089 +:10E790000000000000000000000000000000000079 +:10E7A0000000000000000000000000000000000069 +:10E7B0000000000000000000000000000000000059 +:10E7C0000000000000000000000000000000000049 +:10E7D0000000000000000000000000000000000039 +:10E7E0000000000000000000000000000000000029 +:10E7F0000000000000000000000000000000000019 +:10E800000000000000000000000000000000000008 +:10E8100000000000000000000000000000000000F8 +:10E8200000000000000000000000000000000000E8 +:10E8300000000000000000000000000000000000D8 +:10E8400000000000000000000000000000000000C8 +:10E8500000000000000000000000000000000000B8 +:10E8600000000000000000000000000000000000A8 +:10E870000000000000000000000000000000000098 +:10E880000000000000000000000000000000000088 +:10E890000000000000000000000000000000000078 +:10E8A0000000000000000000000000000000000068 +:10E8B0000000000000000000000000000000000058 +:10E8C0000000000000000000000000000000000048 +:10E8D0000000000000000000000000000000000038 +:10E8E0000000000000000000000000000000000028 +:10E8F0000000000000000000000000000000000018 +:10E900000000000000000000000000000000000007 +:10E9100000000000000000000000000000000000F7 +:10E9200000000000000000000000000000000000E7 +:10E9300000000000000000000000000000000000D7 +:10E9400000000000000000000000000000000000C7 +:10E9500000000000000000000000000000000000B7 +:10E9600000000000000000000000000000000000A7 +:10E970000000000000000000000000000000000097 +:10E980000000000000000000000000000000000087 +:10E990000000000000000000000000000000000077 +:10E9A0000000000000000000000000000000000067 +:10E9B0000000000000000000000000000000000057 +:10E9C0000000000000000000000000000000000047 +:10E9D0000000000000000000000000000000000037 +:10E9E0000000000000000000000000000000000027 +:10E9F0000000000000000000000000000000000017 +:10EA00000000000000000000000000000000000006 +:10EA100000000000000000000000000000000000F6 +:10EA200000000000000000000000000000000000E6 +:10EA300000000000000000000000000000000000D6 +:10EA400000000000000000000000000000000000C6 +:10EA500000000000000000000000000000000000B6 +:10EA600000000000000000000000000000000000A6 +:10EA70000000000000000000000000000000000096 +:10EA80000000000000000000000000000000000086 +:10EA90000000000000000000000000000000000076 +:10EAA0000000000000000000000000000000000066 +:10EAB0000000000000000000000000000000000056 +:10EAC0000000000000000000000000000000000046 +:10EAD0000000000000000000000000000000000036 +:10EAE0000000000000000000000000000000000026 +:10EAF0000000000000000000000000000000000016 +:10EB00000000000000000000000000000000000005 +:10EB100000000000000000000000000000000000F5 +:10EB200000000000000000000000000000000000E5 +:10EB300000000000000000000000000000000000D5 +:10EB400000000000000000000000000000000000C5 +:10EB500000000000000000000000000000000000B5 +:10EB600000000000000000000000000000000000A5 +:10EB70000000000000000000000000000000000095 +:10EB80000000000000000000000000000000000085 +:10EB90000000000000000000000000000000000075 +:10EBA0000000000000000000000000000000000065 +:10EBB0000000000000000000000000000000000055 +:10EBC0000000000000000000000000000000000045 +:10EBD0000000000000000000000000000000000035 +:10EBE0000000000000000000000000000000000025 +:10EBF0000000000000000000000000000000000015 +:10EC00000000000000000000000000000000000004 +:10EC100000000000000000000000000000000000F4 +:10EC200000000000000000000000000000000000E4 +:10EC300000000000000000000000000000000000D4 +:10EC400000000000000000000000000000000000C4 +:10EC500000000000000000000000000000000000B4 +:10EC600000000000000000000000000000000000A4 +:10EC70000000000000000000000000000000000094 +:10EC80000000000000000000000000000000000084 +:10EC90000000000000000000000000000000000074 +:10ECA0000000000000000000000000000000000064 +:10ECB0000000000000000000000000000000000054 +:10ECC0000000000000000000000000000000000044 +:10ECD0000000000000000000000000000000000034 +:10ECE0000000000000000000000000000000000024 +:10ECF0000000000000000000000000000000000014 +:10ED00000000000000000000000000000000000003 +:10ED100000000000000000000000000000000000F3 +:10ED200000000000000000000000000000000000E3 +:10ED300000000000000000000000000000000000D3 +:10ED400000000000000000000000000000000000C3 +:10ED500000000000000000000000000000000000B3 +:10ED600000000000000000000000000000000000A3 +:10ED70000000000000000000000000000000000093 +:10ED80000000000000000000000000000000000083 +:10ED90000000000000000000000000000000000073 +:10EDA0000000000000000000000000000000000063 +:10EDB0000000000000000000000000000000000053 +:10EDC0000000000000000000000000000000000043 +:10EDD0000000000000000000000000000000000033 +:10EDE0000000000000000000000000000000000023 +:10EDF0000000000000000000000000000000000013 +:10EE00000000000000000000000000000000000002 +:10EE100000000000000000000000000000000000F2 +:10EE200000000000000000000000000000000000E2 +:10EE300000000000000000000000000000000000D2 +:10EE400000000000000000000000000000000000C2 +:10EE500000000000000000000000000000000000B2 +:10EE600000000000000000000000000000000000A2 +:10EE70000000000000000000000000000000000092 +:10EE80000000000000000000000000000000000082 +:10EE90000000000000000000000000000000000072 +:10EEA0000000000000000000000000000000000062 +:10EEB0000000000000000000000000000000000052 +:10EEC0000000000000000000000000000000000042 +:10EED0000000000000000000000000000000000032 +:10EEE0000000000000000000000000000000000022 +:10EEF0000000000000000000000000000000000012 +:10EF00000000000000000000000000000000000001 +:10EF100000000000000000000000000000000000F1 +:10EF200000000000000000000000000000000000E1 +:10EF300000000000000000000000000000000000D1 +:10EF400000000000000000000000000000000000C1 +:10EF500000000000000000000000000000000000B1 +:10EF600000000000000000000000000000000000A1 +:10EF70000000000000000000000000000000000091 +:10EF80000000000000000000000000000000000081 +:10EF90000000000000000000000000000000000071 +:10EFA0000000000000000000000000000000000061 +:10EFB0000000000000000000000000000000000051 +:10EFC0000000000000000000000000000000000041 +:10EFD0000000000000000000000000000000000031 +:10EFE0000000000000000000000000000000000021 +:10EFF000000000000000000000000002007100009E +:00000001FF diff --git a/tests/list_test.rs b/tests/list_test.rs new file mode 100644 index 0000000..827ca27 --- /dev/null +++ b/tests/list_test.rs @@ -0,0 +1,98 @@ +use assert_cmd::Command; +use serial_test::serial; + +#[cfg(target_os = "macos")] +const NUPHY_AIR60_SMK_ENTRY: &str = "\ +ID 05ac:024f manufacturer=\"contact@carlossless.io\" product=\"SMK Keyboard\" + path=\".+\" interface_number=0 + report_descriptor=\\[05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 75 08 95 01 81 01 05 07 19 00 29 FF 15 00 26 FF 00 75 08 95 06 81 00 05 08 19 01 29 05 15 00 25 01 75 01 95 05 91 02 75 03 95 01 91 01 C0\\] + feature_report_ids=\\[\\] + usage_page=0x0001 usage=0x0006 + path=\".+\" interface_number=1 + report_descriptor=\\[05 01 09 80 A1 01 85 01 19 81 29 83 15 00 25 01 75 01 95 03 81 02 95 05 81 01 C0 05 0C 09 01 A1 01 85 02 19 00 2A 3C 02 15 00 26 3C 02 75 10 95 01 81 00 C0 06 00 FF 09 01 A1 01 85 05 19 01 29 02 15 00 26 FF 00 75 08 95 05 B1 02 C0 05 01 09 06 A1 01 85 06 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 05 07 19 00 29 9F 15 00 25 01 75 01 95 A0 81 02 C0\\] + feature_report_ids=\\[5\\] + usage_page=0x0001 usage=0x0006 + usage_page=0x0001 usage=0x0080 + usage_page=0x000c usage=0x0001 + usage_page=0xff00 usage=0x0001 +"; + +#[cfg(target_os = "linux")] +const NUPHY_AIR60_SMK_ENTRY: &str = "\ +ID 05ac:024f manufacturer=\"contact@carlossless.io\" product=\"SMK Keyboard\" + path=\".+\" interface_number=0 + report_descriptor=\\[05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 75 08 95 01 81 01 05 07 19 00 29 FF 15 00 26 FF 00 75 08 95 06 81 00 05 08 19 01 29 05 15 00 25 01 75 01 95 05 91 02 75 03 95 01 91 01 C0\\] + feature_report_ids=\\[\\] + path=\".+\" interface_number=1 + report_descriptor=\\[05 01 09 80 A1 01 85 01 19 81 29 83 15 00 25 01 75 01 95 03 81 02 95 05 81 01 C0 05 0C 09 01 A1 01 85 02 19 00 2A 3C 02 15 00 26 3C 02 75 10 95 01 81 00 C0 06 00 FF 09 01 A1 01 85 05 19 01 29 02 15 00 26 FF 00 75 08 95 05 B1 02 C0 05 01 09 06 A1 01 85 06 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 05 07 19 00 29 9F 15 00 25 01 75 01 95 A0 81 02 C0\\] + feature_report_ids=\\[5\\] +"; + +#[cfg(target_os = "windows")] +const NUPHY_AIR60_SMK_ENTRY: &str = "\ +ID 05ac:024f manufacturer=\"contact@carlossless.io\" product=\"SMK Keyboard\" + interface_number=0 + path=\".+\" usage_page=0x0001 usage=0x0006 + report_descriptor=\\[05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 75 08 95 01 81 03 19 00 29 FF 15 00 26 FF 00 75 08 95 06 81 00 05 08 19 01 29 05 15 00 25 01 75 01 95 05 91 02 75 03 95 01 91 03 C0\\] + feature_report_ids=\\[\\] + interface_number=1 + path=\".+\" usage_page=0x0001 usage=0x0080 + report_descriptor=\\[05 01 09 80 A1 01 85 01 19 81 29 83 15 00 25 01 75 01 95 03 81 02 75 05 95 01 81 03 C0\\] + feature_report_ids=\\[\\] + interface_number=1 + path=\".+\" usage_page=0x000c usage=0x0001 + report_descriptor=\\[05 0C 09 01 A1 01 85 02 19 00 2A 3C 02 15 00 26 3C 02 75 10 95 01 81 00 C0\\] + feature_report_ids=\\[\\] + interface_number=1 + path=\".+\" usage_page=0xff00 usage=0x0001 + report_descriptor=\\[06 00 FF 09 01 A1 01 85 05 19 01 29 02 15 00 26 FF 00 75 08 95 05 B1 02 C0\\] + feature_report_ids=\\[5\\] + interface_number=1 + path=\".+\" usage_page=0x0001 usage=0x0006 + report_descriptor=\\[05 01 09 06 A1 01 85 06 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 19 00 29 9F 15 00 25 01 75 01 95 A0 81 02 C0\\] + feature_report_ids=\\[\\] +"; + +#[test] +#[serial] +fn test_list_devices() { + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd.arg("list").assert(); + assert + .success() + .stdout(predicates::str::is_match(NUPHY_AIR60_SMK_ENTRY).unwrap()); +} + +#[test] +#[serial] +fn test_list_with_vid_filter() { + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd.arg("list").args(&["--vendor_id", "0x05ac"]).assert(); + assert + .success() + .stdout(predicates::str::is_match(NUPHY_AIR60_SMK_ENTRY).unwrap()); +} + +#[test] +#[serial] +fn test_list_with_pid_filter() { + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd.arg("list").args(&["--product_id", "0x024f"]).assert(); + assert + .success() + .stdout(predicates::str::is_match(NUPHY_AIR60_SMK_ENTRY).unwrap()); +} + +#[test] +#[serial] +fn test_list_with_vid_and_pid_filter() { + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("list") + .args(&["--vendor_id", "0x05ac"]) + .args(&["--product_id", "0x024f"]) + .assert(); + assert + .success() + .stdout(predicates::str::is_match(NUPHY_AIR60_SMK_ENTRY).unwrap()); +} diff --git a/tests/read_test.rs b/tests/read_test.rs new file mode 100644 index 0000000..ca89cae --- /dev/null +++ b/tests/read_test.rs @@ -0,0 +1,146 @@ +use std::fs; + +use assert_cmd::Command; +use serial_test::serial; + +#[macro_use] +pub mod common; + +#[test] +#[serial] +fn test_read() { + let file = test_filename!("hex"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("read") + .args(&["--device", "nuphy-air60"]) + .arg(&file) + .assert(); + assert.success().stderr(predicates::str::contains( + "MD5: 662c8707c4be0e0712e30336b0e7cfd1", + )); + + let computed_md5 = md5::compute(fs::read(&file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "6594e5a1ab671deb40f36483a84ad61f" + ); +} + +#[test] +#[serial] +fn test_read_bin() { + let file = test_filename!("bin"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("read") + .args(&["--device", "nuphy-air60"]) + .arg(&file) + .assert(); + assert.success().stderr(predicates::str::contains( + "MD5: 662c8707c4be0e0712e30336b0e7cfd1", + )); + + let computed_md5 = md5::compute(fs::read(&file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "662c8707c4be0e0712e30336b0e7cfd1" + ); +} + +#[test] +#[serial] +fn test_read_bootloader() { + let file = test_filename!("hex"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("read") + .args(&["--device", "nuphy-air60"]) + .args(&["--section", "bootloader"]) + .arg(&file) + .assert(); + assert.success().stderr(predicates::str::contains( + "MD5: 3e0ebd0c440af5236d7ff8872343f85d", + )); + + let computed_md5 = md5::compute(fs::read(&file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "65956adbe2e77369d3581ebabb1592f7" + ); +} + +#[test] +#[serial] +fn test_read_full() { + let file = test_filename!("hex"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("read") + .args(&["--device", "nuphy-air60"]) + .args(&["--section", "full"]) + .arg(&file) + .assert(); + assert.success().stderr(predicates::str::contains( + "MD5: 3f87adb2125bcc5beee424a3af5272e9", + )); + + let computed_md5 = md5::compute(fs::read(&file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "e6f497f108dbe82f8d340562eb88fe44" + ); +} + +#[test] +#[serial] +fn test_read_custom_part() { + let file = test_filename!("hex"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("read") + .args(&["--platform", "sh68f90"]) + .args(&["--vendor_id", "0x05ac"]) + .args(&["--product_id", "0x024f"]) + .args(&["--isp_iface_num", "1"]) + .args(&["--isp_report_id", "5"]) + .args(&["--firmware_size", "61440"]) + .arg(&file) + .assert(); + assert.success().stderr(predicates::str::contains( + "MD5: 662c8707c4be0e0712e30336b0e7cfd1", + )); + + let computed_md5 = md5::compute(fs::read(&file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "6594e5a1ab671deb40f36483a84ad61f" + ); +} + +#[test] +#[serial] +fn test_read_forced_format_bin() { + let file = test_filename!("hex"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("read") + .args(&["--device", "nuphy-air60"]) + .args(&["--format", "bin"]) + .arg(&file) + .assert(); + assert + .success() + .stderr(predicates::str::contains( + "Warning: binary file has hex extension. This might be unintended.", + )) + .stderr(predicates::str::contains( + "MD5: 662c8707c4be0e0712e30336b0e7cfd1", + )); + + let computed_md5 = md5::compute(fs::read(&file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "662c8707c4be0e0712e30336b0e7cfd1" + ); +} diff --git a/tests/write_test.rs b/tests/write_test.rs new file mode 100644 index 0000000..84238ed --- /dev/null +++ b/tests/write_test.rs @@ -0,0 +1,92 @@ +use std::fs; + +use assert_cmd::Command; +use serial_test::serial; + +#[macro_use] +pub mod common; + +use common::get_fixture_path; + +#[test] +#[serial] +fn test_write() { + let file = get_fixture_path("nuphy-air60_smk.hex"); + let mut cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = cmd + .arg("write") + .args(&["--device", "nuphy-air60"]) + .arg(file) + .assert(); + assert.success(); +} + +#[test] +#[serial] +fn test_write_and_readback() { + let fixture_file = get_fixture_path("nuphy-air60_smk.hex"); + let mut write_cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = write_cmd + .arg("write") + .args(&["--device", "nuphy-air60"]) + .arg(&fixture_file) + .assert(); + assert.success(); + + let output_file = test_filename!("hex"); + let mut read_cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = read_cmd + .arg("read") + .args(&["--device", "nuphy-air60"]) + .arg(&output_file) + .assert(); + assert.success().stderr(predicates::str::contains( + "MD5: 662c8707c4be0e0712e30336b0e7cfd1", + )); + + let computed_md5 = md5::compute(fs::read(&output_file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "6594e5a1ab671deb40f36483a84ad61f" + ); +} + +#[test] +#[serial] +fn test_write_custom_and_readback() { + let fixture_file = get_fixture_path("nuphy-air60_smk.hex"); + let mut write_cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = write_cmd + .arg("write") + .args(&["--platform", "sh68f90"]) + .args(&["--vendor_id", "0x05ac"]) + .args(&["--product_id", "0x024f"]) + .args(&["--firmware_size", "61440"]) + .args(&["--isp_iface_num", "1"]) + .args(&["--isp_report_id", "5"]) + .arg(&fixture_file) + .assert(); + assert.success(); + + let output_file = test_filename!("hex"); + let mut read_cmd = Command::cargo_bin("sinowealth-kb-tool").unwrap(); + let assert = read_cmd + .arg("read") + .args(&["--platform", "sh68f90"]) + .args(&["--vendor_id", "0x05ac"]) + .args(&["--product_id", "0x024f"]) + .args(&["--firmware_size", "61440"]) + .args(&["--isp_iface_num", "1"]) + .args(&["--isp_report_id", "5"]) + .arg(&output_file) + .assert(); + assert.success().stderr(predicates::str::contains( + "MD5: 662c8707c4be0e0712e30336b0e7cfd1", + )); + + let computed_md5 = md5::compute(fs::read(&output_file).unwrap()); + assert_eq!( + format!("{:x}", computed_md5), + "6594e5a1ab671deb40f36483a84ad61f" + ); +}