From 0c1cc2f379d9e550d8699ef358470d4e9f5ac6eb Mon Sep 17 00:00:00 2001 From: "tristan.champomier" Date: Fri, 13 Nov 2020 23:04:36 +0100 Subject: [PATCH] Added firmware and tools for SILead Touchscreen. --- firmware/README.md | 20 + .../ReadMe.txt | 3 + .../SileadTouch.fw | 1 + .../SileadTouch.sys | Bin 0 -> 84480 bytes firmware/silead_ts.fw | Bin 0 -> 19428 bytes tools/AUTHORS.md | 3 + tools/Firmware/Silead.pm | 530 ++++++++++++++++++ tools/LICENSE | 339 +++++++++++ tools/SileadTouch.fw | 1 + tools/autoconvert | 82 +++ tools/fw_extractor | 36 ++ tools/fwtool | 143 +++++ tools/scanwindrv | 129 +++++ tools/silead_ts.fw | Bin 0 -> 19428 bytes tools/unscramble | 52 ++ tools/untscfg | 47 ++ 16 files changed, 1386 insertions(+) create mode 100644 firmware/README.md create mode 100644 firmware/Touch screen calibration files Touch/ReadMe.txt create mode 100644 firmware/Touch screen calibration files Touch/SileadTouch.fw create mode 100644 firmware/Touch screen calibration files Touch/SileadTouch.sys create mode 100644 firmware/silead_ts.fw create mode 100644 tools/AUTHORS.md create mode 100644 tools/Firmware/Silead.pm create mode 100644 tools/LICENSE create mode 100644 tools/SileadTouch.fw create mode 100755 tools/autoconvert create mode 100755 tools/fw_extractor create mode 100755 tools/fwtool create mode 100755 tools/scanwindrv create mode 100644 tools/silead_ts.fw create mode 100755 tools/unscramble create mode 100755 tools/untscfg diff --git a/firmware/README.md b/firmware/README.md new file mode 100644 index 0000000..83e84c6 --- /dev/null +++ b/firmware/README.md @@ -0,0 +1,20 @@ +cube/i10 +-------- + +| Item | Description | +|---------------------------|-------------| +| Manufacturer | Cube | +| Device | i10 | +| Website | http://www.cube-tablet.com/cube-i10-10-6-inch-dual-boot-tablet.html | +| Vendor driver (Windows) | http://techtablets.com/download/cube/i10/Windows%208.1%20Drivers/i10%20Windows%208.1%20drivers%20and%20touchscreen%20config%20files.zip or https://drive.google.com/open?id=0B3eEskvA0DSXZ0RZRVJnR2t1RE0 (drivers for Windows 8.1) http://pan.baidu.com/s/1pKabwdP (system image for i10-R) http://pan.baidu.com/s/1kT8gooJ (system image for i10-BW) http://pan.baidu.com/s/1eQz3bN0 (system image for i10-W) http://pan.baidu.com/s/1kT5yzbT (system image for i10-W) | +| Extracted firmware | [Touch screen calibration files Touch/SileadTouch.fw](Touch screen calibration files Touch/SileadTouch.fw) | +| Firmware for gslx680-acpi | [silead_ts.fw](silead_ts.fw) | +| Display resolution | 1366x768 | +| Touch panel resolution | 1366x768 (unverified) | +| Touch controller | ? | +| Multitouch support | Yes (10) (unverified) | +| Finger tracking | Yes | +| Mirrored horizontally | No | +| Mirrored vertically | No | +| Axes swapped | No | +| Comments | ./fwtool -c SileadTouch.fw -3 -m 1680 -w 1366 -h 768 -t 10 silead_ts.fw | diff --git a/firmware/Touch screen calibration files Touch/ReadMe.txt b/firmware/Touch screen calibration files Touch/ReadMe.txt new file mode 100644 index 0000000..accc7ff --- /dev/null +++ b/firmware/Touch screen calibration files Touch/ReadMe.txt @@ -0,0 +1,3 @@ +Move these files to C;/windows/system32/drivers and reboot. +This will restore the touch screen. +Techtablets.com \ No newline at end of file diff --git a/firmware/Touch screen calibration files Touch/SileadTouch.fw b/firmware/Touch screen calibration files Touch/SileadTouch.fw new file mode 100644 index 0000000..f089f6f --- /dev/null +++ b/firmware/Touch screen calibration files Touch/SileadTouch.fw @@ -0,0 +1 @@ +ը󅂁𺸸뻿뼤𰹸餸𹰸𹰸길𽹸𻺸𼤸𱸸𼸸𹸾𹸼𹺼𾼤龸鸸츸줸츸𰸼𱸸𱸸𹼸뤸鸸뤸鸸𼸸𹸰𹤧𹸸𹸸𰸸𺺹𺸹𿸾긱𹸸줸𹼹𹱹餸𺹺𺽺𺱺餸𻺻𻾻黱ꤸ𻸺𼸼𾸽鸰ꤸ𹽹깱𺸹뤅𺽺꺱𻸺뤸𻽻𻱻餸뤸줅𻸺𿸾鸱뤸𹻹𹿹鹱뤅𺻺𺿺麱뤸𻻻𻿻黱뤅𻸺𿸾鸱뤸𹻹𹿹鹱뤅𺻺𺿺麱뤸𻻻𻿻黱뤅𻸺𿸾鸱뤸𹻹𹿹鹱뤅𺻺𺿺麱뤸𻻻𻿻黱뤅𻸺𿸾鸱뤸𹻹𹿹鹱뤅𺻺𺿺麱뤸𻻻𻿻黱뤅𻤅𹸹𹸸𺸤𹸤𰤸𼤅𼤸𾸸븤ɨը󅂧᥻أυ+2+2+2𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𾰤𸸸뤸𹸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𹰹𸸤鱽𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤븸𾰤𸸸뤸𸸸𿸤𸸸𿼤𿰤뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸼸鸸𼰤𸸹뤸鸸𽸤𸸸𽼤𸸸𽰤𸼸뤸𸰸𾸤𾼤𹸹𾰤𹼹뤸𹰹𿸤𿼤𸸹𿰤𰸰뤸鱰𸸤𸸸𸼤𸸸𸰤𸸸뤸𰸾𹸤𸸸𹼤𸸸𹰤𸸸뤸𹸾𺸤𹸼𺼤𸸸𺰤𸸸뤸𸸸𻸤𰸰𻼤𰸰𻰤𰸰뤸𰸰𼸤𰸰𼼤𰸰𼰤𰸰뤸𰸰𽸤𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸼸𹸤𸸸𹼤𹼸鹼𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𻸤𻼤𸸸𻰤𸸸뤸𸸸𼸤𰸸𼼤𸸹𼰤𸸸뤸𸼸𽸤𸸸𽼤𸸸𽰤𸸸뤸𹺼𾸤𺸹𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸹸츸𸼤𸻸𸰤𸽹뤸𸿹𹸤𸱹𹼤깿鹾𹰤𸸸뤸𸸸𺸤𸸸𺼤𺰤뤸𻸤𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸾𼰤𸰹뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸹츸𾸤𸸹𾼤𸸹𾰤𸸸鸸뤸𸸸鸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸾𸸤𸼤츹𸰤긹뤸𹸤𹼤𹰤뤸𺸤𺼤𺻰𺰤𺻼뤸𺻸𻸤𻼤𺺰𻰤𺺼뤸𼺸𼸤𸹸𼼤𸱸𼰤𹹹뤸𸺸𽸤𽼤𹺹𽰤𸸸츸뤸𸸸𾸤𸸸𾼤𸼸𾰤븰뤸𸸻𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸼤𸸸𸰤뤸𸸸𹸤𹼤𸸸𹰤뤸𸹸𺸤𺼤𸸸𺰤뤸𸸹𻸤𻼤𸸸𻰤뤸𸸸𼸤𼼤𸸸𼰤뤸𸸸𽸤𽼤𸸸𽰤뤸𸸸𾸤𾼤𸸸𾰤뤸𸸸𿸤𿼤𸸸𿰤뤸𸸸𸸤𸸻𸼤𸸼𸰤𸸾鸸뤸𸸾𹸤𸸾𹼤𸸽𹰤𸸽길뤸𸸽𺸤𸸽𺼤𸸽𺰤𸸽뤸𸸽𻸤𸸼븸𻼤𸸾𻰤𸸽뤸𸸽𼸤𸸾𼼤𸸾𼰤𸻽뤸𸸽𽸤𸸽𽼤𸺽𽰤𸺽뤸𸸹븺𾸤𸸾𾼤𸸾𾰤𸸸뤸𸸼𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸼𸼤𸸻𸰤𸸺뤸𸸹𹸤𸸹𹼤𸸻𹰤𸸼뤸𸸿𺸤𸸿𺼤𸸿𺰤𸸾븸뤸𸸰𻸤𸸾𻼤𸸽츸𻰤𸸾뤸𸸽𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸽𸼤𸸼𸰤𸸾뤸𸸽𹸤𸸾𹼤𸸼븸𹰤𸸽뤸𸸾𺸤𸸽𺼤𸸼𺰤𸸽鸸뤸𸸽𻸤𸸼𻼤𸸻鸸𻰤𸸸뤸𸸹𼸤𸸾鸸𼼤𸸾𼰤𸸾뤸𸸾鸸𽸤𸸿𽼤𸸾𽰤𸸾뤸𸸼츸𾸤𸸽𾼤𸸼𾰤𸸻길뤸𸸺𿸤𸸹븸𿼤𸸹鸸𿰤𸸹뤸𸸻븸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸼤𸸸𸰤𸸸뤸𸸸齰𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸뽸𼰤𸸸콸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸鸰𾰤𸸸뤸𸸸껼𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸콰뤸𸸤𸹸𸼤𸹸𸰤𸹸뤸𺻻𹸤麹𹼤鼹𹰤뤸𺻻𺸤麹𺼤𺽸𺰤鼹뤸𻸤𸹸𻼤𰺹𻰤𰹰뤸𸹸𼸤𸹸𼼤鼹𼰤鸸뤸𸹸𽸤鸹𽼤麹𽰤鼹뤸龹𾸤鰹𾼤鹸𾰤빸뤸𿸤𱸹𿼤𱺹𿰤𱼹뤸𱾹𸸤𱰹𸼤鹸𸰤빸뤸𹸤𰼹𹼤𸹸𹰤𸹸뤸𰺹𺸤𰹱𺼤𰺹𺰤𰹱뤸𰹰𻸤𸹸𻼤𸹸𻰤𸹸뤸빸𼸤빸𼼤𸹸𼰤𸹸뤸𺿸𽸤龹𽼤鸸𽰤𸹸뤸𼸸𾸤𸹸𾼤𸹸𾰤뤸𸹸𿸤𸻹𿼤𰺹𿰤𸻺뤸𰺹𸸤𸼤𼸸𸰤𸹸뤸𼸸𹸤𸹸𹼤𼸸𹰤𸹸뤸𼸸𺸤𸹸𺼤𺰤𰺹뤸𰹱𻸤𸹸𻼤𸹸𻰤𸹸뤸𼸤𸹸𼼤𸻸𼰤𰺹뤸黰𽸤𸻸𽼤𰺹𽰤𰹱뤸𸹸𾸤𸹸𾼤𸹸𾰤뤸𸹸𿸤𸹸𿼤𸹸𿰤𸹸뤸鿰𸸤𸹸𸼤𸹸𸰤𸹸뤸𹸤𸹸𹼤麺𹰤𸺰뤸𸹸𺸤𸹸𺼤𱸰𺰤뤸𸹸𻸤𻼤𸹸𻰤𸹸뤸𸽸𼸤𰼹鸸𼼤鸸𼰤𸹸뤸𽸤𸹸𽼤𽰤꺸뤸𱾹𾸤𾼤븺𾰤𱰹뤸길𿸤켸𿼤鸾𿰤갹뤸𱰸𸸤길𸼤麰𸰤𹾰뤸꾹𹸤鸸𹼤𰻺꾸𹰤꺸뤸꼸𺸤븹𺼤鿸𺰤𹾰뤸𸹸𻸤뺸𻼤鸼𻰤𸼰뤸鿸𼸤꾸𼼤𼰤꼸뤸𹾰𽸤鿸𽼤뺸𽰤뺺뤸갸𾸤鿸𾼤𹾰𾰤꺸뤸뺸𿸤鸼𿼤𿰤갸뤸鿸𸸤𹾰𸼤𸹸𸰤뺺뤸꾸𹸤꼸𹼤鿸𹰤뤸鿸𺸤길𺼤𰺸𺰤뺺뤸켺𻸤𰻺𻼤길𻰤븸뤸鸿𼸤麾𼼤麾𼰤𱰸뤸黻𽸤𽼤켸𽰤뤸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𰻽𸼤𰺸𸰤𰻻뤸鸾𹸤𸺰𹼤𸹸𹰤鸾뤸𸺰𺸤𸹸𺼤鸾𺰤𸺰뤸𸹸𻸤鸾𻼤𸺰𻰤𸹸뤸鸾𼸤𸺰𼼤𸹸𼰤𸿻빰뤸𰾹𽸤𸽹𽼤𰼸𽰤뼺븸뤸𸿻븸𾸤𰾹𾼤𰼹𾰤뼺븸뤸𸽸𿸤𸹸𿼤𸹸𿰤𰼰뤸𸸤𸹸𸼤𸹸𸰤𸿻븸뤸𰾹𹸤𰼹𹼤뼺븸𹰤𸹸뤸𸹸𺸤뼼𺼤밸𺰤𸹸뤸鿽𻸤鱺𻼤鿻𻰤龹븹뤸龸𼸤𰹱𼼤𸹸𼰤𸹸뤸𽸤鸸𽼤鸸𽰤鸹뤸鸹𾸤鸺𾼤鸺𾰤鸻뤸鸻𿸤𿼤𰹱븸𿰤𸹸뤸𸹸𸸤뼼𸼤밸𸰤𸹸뤸鿽𹸤鱻𹼤鿺𹰤龹븹뤸龸𺸤𰹱𺼤𸹸𺰤𸹸뤸𻸤𻼤鸸𻰤鸸뤸鸹𼸤鸹𼼤鸺𼰤鸺뤸鸻𽸤鸻𽼤𽰤뤸𰹱븸𾸤𸹸𾼤𸹸𾰤뼼뤸밸𿸤𸹸𿼤𸹸𿰤𰺹뤸𺿻𸸤龹𸼤뺺븸𸰤𸹸뤸𸻻𹸤𰺹𹼤龹𹰤뤸𸹸𺸤𸹸𺼤𸹸𺰤龹뤸𰻼𻸤𰺹𻼤𰹰𻰤𸹸뤸𼸸𼸤𸹸𼼤𸹸𼰤𸹸뤸鿽𽸤鱻𽼤鿺𽰤龹븹뤸龸𾸤𰹱𾼤𸹸𾰤뤸鸸𿸤鸸𿼤鸹𿰤鸹뤸鸺𸸤鸺𸼤鸻𸰤鸻뤸𹸤𰹱븸𹼤𸹸𹰤龹뤸𰻼𺸤𰺺𺼤𰹰𺰤𸹸뤸𸻻𻸤𰺹𻼤龹𻰤뤸𸹸𼸤𸹸𼼤𸹸𼰤뼼뤸밸𽸤𸹸𽼤𰺹𽰤𺿻뤸龹𾸤뺺븸𾼤𸹸𾰤뼼뤸밸𿸤𸹸𿼤뼰𿰤鸸뤸𸹸𸸤빼𸼤𰺹𸰤뺹뤸𰺸𹸤𰺸𹼤𰻺𹰤鹻뤸𺸤츸𺼤𱼹𺰤𱾹뤸𰻺𻸤캸𻼤𱰹𻰤𰻺꺸뤸鸸𼸤鸺𼼤𱰸𼰤麺뤸黺𽸤𽼤𱼸鸸𽰤𱾸뤸𾸤𾼤𰻺𾰤뤸𸹸𿸤𰺸𿼤𰺸𿰤껺뤸𰺸𸸤𰺸𸼤𰻺𸰤𱺸龸뤸𱻺龸𹸤츸𹼤𱹻𹰤뤸𱸸麸𺸤鸺𺼤鸻𺰤𱿻뤸鸻𻸤鸻𻼤𱺸龸𻰤꾸뤸𱻺龸𼸤𰺹𼼤참𼰤𰻺뤸𰺺길𽸤𱽺鰸𽼤𰺹𽰤뺺뤸𱹺麸𾸤鸺𾼤𱿺𾰤뤸뺺𿸤鹸𿼤𰺹𿰤麻뤸𰺺𸸤꾸𸼤麺𸰤𹼰뤸𱱺𹸤𸻻뺸𹼤𰺹𹰤뺸뤸𹸰𺸤𰻻𺼤𸻻뺸𺰤𰺹뤸뺸𻸤𰻻𻼤𻰤𱸸뤸𼸤鹺𼼤鹼𼰤쾹뤸뺸𽸤긺븸𽼤𰺽꼸𽰤꺹뤸𱺰𾸤𸺰𾼤鸸𾰤긹뤸𱰸𿸤𰺸𿼤뺹𿰤뺺뤸뺸𸸤鸻𸼤기𸰤뤸𱰸𹸤𹼤𱸸𹰤鹼뤸쾹𺸤黼𺼤𱺹𺰤𹰰뤸긹𻸤𰻺꾸𻼤𰺸𻰤𱰸뤸뺸𼸤길𼼤𱺸𼰤龸뤸𽸤𱰸𽼤긺븸𽰤길뤸𰹰𾸤𸹸𾼤𸹸𾰤𸹸뤸긿𿸤𿼤𿰤𸻻뺸뤸𱾹𸸤𱰹𸼤𰻺꺸𸰤鸻뤸鹻𹸤𱰸𹼤黺𹰤뤸麸𺸤𺼤𸹸𺰤뤸뺸𻸤𰻻𻼤龸𻰤鰸뤸𱸹𼸤𼼤𸹸𼰤𹸰뤸길𽸤𽼤𱸺𽰤𱸸뤸길𾸤𾼤𾰤뤸鰹𿸤뺸𿼤齸𿰤鰸뤸𸸤鼹𸼤뺸𸰤鼰뤸鰸𹸤鰸𹼤𹰤𱸹뤸鹸𺸤𱸹𺼤𺰤𱺹뤸龺𻸤𹺰𻼤鸹𻰤𹸰뤸鸹𼸤龺𼼤𹰰𼰤龺뤸𽸤𸹸𽼤𱼹𽰤𱸹뤸𾸤𱺹𾼤麸𾰤𸼰뤸龹𿸤鹸𿼤麻𿰤𰺹뤸𰻺𸸤鸺븸𸼤龺𸰤𹰰뤸龺𹸤鹸𹼤麻𹰤𰺹뤸𰻺𺸤𹸰𺼤鸹𺰤𹺰뤸𰺹𻸤鼺𻼤𺼰𻰤鸸뤸𸻸𼸤鸸𼼤𰺹𼰤𹸰뤸𽸤鸸𽼤龸𽰤鼺뤸𸼰𾸤𰺹𾼤𰺹𾰤𰸰꼸뤸𸺰𿸤𱺹𿼤𸻸𿰤鸸뤸𰺹𸸤뺸𸼤鸼𸰤𹰰뤸麸𹸤麼𹼤븹𹰤𹼰뤸𰺺븹𺸤𰺺𺼤黼𺰤鸾뤸𱺹𻸤𱼹𻼤𻰤𱸹뤸𼸤鼸鸸𼼤뺸𼰤齸뤸𽸤鼹𽼤𽰤뤸𱰹𾸤𱾹𾼤麺𾰤𹺰뤸𰺹𿸤𰺺븸𿼤𰻺𿰤鸸뤸黿𸸤𸺰𸼤𱰸𸰤뺸뤸黺𹸤𹼤뺺𹰤뤸𸹸𺸤𺼤참𺰤뺸뤸𱰹𻸤鸸𻼤𸻻븸𻰤꼸뤸𹽻빰𼸤𸻺𼼤𰺹𼰤𱾹鸻뤸뺺븸𽸤𸻹𽼤찺𽰤黼뤸븺𾸤龹𾼤𹺰𾰤鰹뤸𸻸𿸤鸸𿼤𰺹𿰤꼸뤸참𸸤𸻻𸼤𱰸길𸰤鹻뤸麸𹸤龺𹼤𹾰𹰤꺱뤸븼𺸤뺸𺼤𰺸𺰤깾뤸鸼𻸤𺺰𻼤龹𻰤鸸뤸뺸𼸤黼𼼤鰸𼰤꺱뤸𸻹𽸤鸸𽼤𰺹𽰤黼뤸𸺰𾸤𸻺𾼤𰺹𾰤黼뤸𹺰𿸤꺱𿼤𹹸𿰤𱸹뤸𼸸𸸤𹻸𸼤𸻸𸰤𱾹뤸鰹𹸤𱰹𹼤꺸𹰤𱰸뤸뺸𺸤黺𺼤𺰤뺺뤸꺱𻸤鸸𻼤𰺻𻰤鼹뤸𱸼𼸤𰻻𼼤깾𼰤麹뤸𽸤켸𽼤𽰤𱰹뤸뺸𾸤𱾸齸𾼤𱺹꺽𾰤鸼뤸𸺰𿸤鹰𿼤鸸𿰤𰺾뤸𰸱𸸤𸺰𸼤𸰤뤸鼸𹸤鸸𹼤𰺾𹰤𰸱뤸𻺰𺸤𱰸𺼤𺰤𸺰뤸𰺸𻸤鸾𻼤𺰰𻰤𱰸뤸븺𼸤𱰸𼼤黺𼰤뤸뺸𽸤龺𽼤𸾰𽰤𸻸뤸𰺹𾸤𰺸鰸𾼤𹸰𾰤뺺뤸뺹𿸤𰻺𿼤뺺𿰤뺸뤸쾸𸸤鸸𸼤𱾸𸰤참뤸𱸸𹸤껻𹼤𱼸𹰤꾺뤸𱰸𺸤𰻻𺼤𱰹𺰤𱸹뤸뺸𻸤𰺸븸𻼤鸸𻰤𱼹뤸찺𼸤뺺𼼤麺𼰤𱻻뤸麸𽸤麾𽼤쾺𽰤쾺뤸츺𾸤𹺰𾼤麸𾰤𸻸뤸𰺹𿸤𿼤𰺸鸸𿰤븸뤸𰺹𸸤뺺𸼤𸰤𻺰뤸𸻺𹸤𰺹𹼤鸸𹰤麸뤸𹸰𺸤𰺹𺼤鸸𺰤𰺹뤸黼𻸤𹺰𻼤𸹸𻰤뺸뤸𰸰𼸤𹺰𼼤𰺹𼰤뺺뤸𽸤𱸹𽼤𽰤뤸𸹸𾸤𾼤𾰤뤸𼸸𿸤𱸹𿼤𹽻뺸𿰤뤸뺸𸸤𱰹鸿𸼤뺺𸰤𸻻븸뤸참𹸤𰺹𹼤찺𹰤뺸뤸𱸹鸿𺸤뺺𺼤빼𺰤𸻸뤸鸹𻸤𱺹𻼤麹𻰤鼹뤸龹𼸤𰺹𼼤𹿸𼰤뺺뤸𱾹𽸤鹻𽼤쾺𽰤뤸𸻺𾸤𾼤𰺹𾰤뺺뤸𸻻𿸤𰺹𿼤븺𿰤븺뤸쾺𸸤븸𸼤齺𸰤뺸뤸鸸𹸤쾸𹼤켸𹰤𸺰뤸츸𺸤𰺽𺼤𰺸𺰤𹸰뤸黻𻸤麹𻼤𺹻빼𻰤𱰹뤸캸𼸤껻𼼤𰺽꼸𼰤𱺸鿰뤸𱺹𽸤캺𽼤𰺹𽰤캸뤸𱺸𾸤𺽻뺸𾼤𱺹𾰤캺뤸𱰹鸰𿸤캸𿼤𱺸𿰤𱺹뤸캺𸸤𰺹鸸𸼤켺𸰤鹼鸸뤸𹸤츺𹼤鹼鸿𹰤캸뤸𸻻𺸤𱺺鼸𺼤캺𺰤𸻻뤸鸸𻸤𰺹𻼤麸𻰤𸻸뤸𱾹𼸤𰺹𼼤𱼹𼰤𹱸뤸뺺븸𽸤鸹𽼤찺𽰤鼾뤸𸺰𾸤찺𾼤𱻺뾸𾰤𰺸뤸뾸𿸤𰻺𿼤鸺𿰤𱰹鸰뤸麻𸸤𰺸𸼤𱾹鸰𸰤𰺸뤸𱼹鸰𹸤캺븸𹼤뺺𹰤뺸뤸鸾𺸤𸺰𺼤𹿻븰𺰤뺸뤸鸰𻸤𱰹𻼤뺺𻰤麺븸뤸𼸤𱸹𼼤𼰤𱸹뤸𽸤𰺹𽼤鹻𽰤뺺뤸𸻺𾸤뺺𾼤𾰤뤸𿸤뺸𿼤𰸰𿰤𸺰뤸빰𸸤𰺹𸼤鹻𸰤뺺뤸뺸𹸤𰺸𹼤鸼𹰤𹺰뤸𸻻빰𺸤밾𺼤𸹸𺰤鸸뤸𸻻븼𻸤꾸𻼤𰺹𻰤븺뤸𼸤黼𼼤𰺹𼰤븺뤸𽸤𽼤鹸𽰤𰻺꾸뤸鸻𾸤黾𾼤𾰤븺뤸𿸤𸹸𿼤뺸𿰤鸸뤸𰺽𸸤𰻻𸼤𱾹𸰤븸뤸鰸𹸤𸻸𹼤𱼹𹰤𱰹뤸麾𺸤𸺰𺼤麾𺰤𹺰뤸麾𻸤뺸𻼤鸰𻰤𰻻뤸𰻺𼸤𹸰𼼤껻𼰤𺰰뤸鸺𽸤鸻𽼤𰻻𽰤𰺸뤸꼸𾸤𰹰𾼤𸹸𾰤𸹸뤸𸹸𿸤𰺿𿼤鸻𿰤𰻺뤸𰹰𸸤𸹸𸼤𸹸𸰤𸹸뤸鿻𹸤𰺸𹼤𹸰𹰤뺺뤸𰻻𺸤𰹰𺼤𸹸𺰤𸹸뤸𸹸𻸤𰺿𻼤꼸𻰤𰻺뤸𰹰𼸤𸹸𼼤𸹸𼰤𸹸뤸鿻𽸤𰺸𽼤뺺𽰤뺸뤸鸸𾸤𰺽𾼤𱾸𾰤𰻻뤸븸𿸤𿼤𱰸𿰤뤸𸹸𸸤𱰹𸼤꺸𸰤𱰸뤸뺸𹸤黺𹼤𹰤뺺뤸𺸤𸹸𺼤쾸𺰤참뤸𱹻𻸤𱽻𻼤𱸸𻰤𱼸뤸𸻸𼸤麺𼼤𰺹𼰤𱼸길뤸𱸸븸𽸤𱸺𽼤꼸𽰤𱸽鸸뤸𾸤𱸸𾼤𾰤𰺽뤸𰺸𿸤길𿼤𰻺𿰤鹿뤸鸾𸸤𸼤꺸𸰤뺸뤸𱰺븸𹸤龼𹼤꼸𹰤𹼰뤸𱾹𺸤𱼹𺼤갽𺰤길뤸𰻻𻸤鸿𻼤𰺺𻰤뤸꿻𼸤鸿𼼤龺𼰤𺼰뤸길𽸤뺸𽼤鸼𽰤𰺾뤸𰸰𾸤𺺰𾼤길𾰤뺸뤸龼𿸤𻰰𿼤길𿰤뺸뤸鸼𸸤𸼰𸼤鸼𸰤𹸰뤸긹𹸤𺼰𹼤𱾹𹰤길뤸龸𺸤𺼤鸿𺰤꺸뤸龼𻸤𻼤갸𻰤긹뤸𼸤𼼤뺸𼰤𰺸뤸뺺𽸤븺𽼤븺𽰤鹸뤸𰻺꾸𾸤鸻𾼤븺𾰤黾뤸𿸤븺𿼤𿰤𸹸뤸𸸤𰺸𸼤갸𸰤𰺹뤸鹾𹸤𰸱𹼤龹𹰤𸾰뤸鼹𺸤뺸𺼤龸𺰤𻰰뤸긹𻸤뺸𻼤龼𻰤𻰰뤸긹𼸤𱼸𼼤𱾸𼰤麸뤸𰺸𽸤긹𽼤븺𽰤기뤸𾸤𰺸𾼤뺸𾰤𰸰뤸𸺰𿸤긹𿼤龾𿰤𸺰뤸𰺹𸸤뺸𸼤龸𸰤𸺰뤸𰺹𹸤뺸𹼤龼𹰤𹺰뤸鿸𺸤𰺹𺼤뺺𺰤鿸뤸𹼰𻸤꺹𻼤𰺸𻰤鸺븸뤸鸿𼸤𰺸𼼤𰺺𼰤길뤸鸹𽸤𱰺𽼤𽰤길뤸𰺸𾸤𰻺𾼤鸾𾰤꼸뤸꾸𿸤𱸹𿼤𱻺鸸𿰤뤸걺𸸤鸿𸼤𸰤𰻻뤸𰻻𹸤鸿𹼤뺸𹰤𰺺뤸𺸤𺼤鸼𺰤𸼰뤸갸𻸤뺸𻼤𰺹𻰤뺺뤸𼸤𼼤걺𼰤길뤸꾸𽸤龸𽼤𽰤꼸鸸뤸꺸𾸤鸻𾼤龼𾰤뤸𱰸𿸤뺸𿼤𰸰𿰤𸺰뤸鸿𸸤뺸𸼤𰸰𸰤𸺰뤸𰸰𹸤𰸰𹼤𹺰𹰤긹뤸鸿𺸤𰸰𺼤𸺰𺰤뺸뤸𰸰𻸤𸺰𻼤𰸰𻰤뺸뤸𰸰𼸤𻺰𼼤긹𼰤𰸰뤸𸺰𽸤뺸𽼤뺸𽰤𰸰뤸𸺰𾸤뺸𾼤𹸰𾰤긹뤸𰸰𿸤𸺰𿼤긹𿰤𰸰뤸𸺰𸸤𰸰𸼤𹺰𸰤긹뤸긹𹸤𹼤𹰤뤸깺𺸤𺼤𺰤깻뤸길𻸤꾸𻼤鸿𻰤𸻸뤸𰺹𼸤𼼤鸿𼰤뺸뤸𽸤𰻻𽼤𰻻𽰤鸿뤸𾸤걻𾼤뺸𾰤𱸹뤸𱼹𿸤龸𿼤𰸰𿰤길뤸𸺰𸸤鸻𸼤뺸𸰤𰸰뤸𻺰𹸤길𹼤뺸𹰤鸾뤸𺺰𺸤鸻𺼤뺸𺰤龸뤸𺰰𻸤鸻𻼤𹸰𻰤길뤸뺸𼸤𰻻𼼤𰺸𼰤鸸뤸鸾𽸤鸻𽼤𰻻𽰤𰸱뤸𹺰𾸤길𾼤龺𾰤𸾰뤸鸸𿸤뺸𿼤𰺸𿰤黼뤸𹰰𸸤鸸𸼤뺸𸰤𰺸뤸龸𹸤𹰰𹼤麹𹰤𺽸뤸𱰹𺸤鰹麸𺼤𱾹麸𺰤鸸뤸𻸤𹺰𻼤꺸𻰤뤸꺹𼸤𰺺𼼤麻븸𼰤𰺽뤸𰺸𽸤𰻺𽼤鸸𽰤뺸뤸𾸤𰻻𾼤𰻻𾰤𱺽뤸鸿𿸤𿼤꼽𿰤꾸뤸𸸤𰺸븸𸼤갸𸰤𰻺뤸꿺𹸤꼸𹼤꺸𹰤鸾븸뤸꼸𺸤꺽𺼤鿼𺰤𹼰뤸𰻺𻸤鸸𻼤𺺰𻰤𰺸뤸꼸𼸤꼸𼼤𰺸𼰤꿺뤸뺸𽸤鸼𽼤𹼰𽰤𱰸뤸뺸븹𾸤鸼𾼤𻾰𾰤麹뤸黺𿸤𿼤𱾹麸𿰤鼾뤸𸸤鸻𸼤鸸𸰤𹺰뤸긺𹸤긺𹼤𹰤뤸𱼹𺸤뺸𺼤麰𺰤𱾹뤸鰸𻸤𻼤뺸𻰤𱾸뤸鸾𼸤𸺰𼼤𱱺鸸𼰤뺺뤸뺸𽸤𱼸鸸𽼤뺺𽰤뺸뤸𾸤븸𾼤𾰤켺뤸켸𿸤𸻸𿼤𱰸𿰤𰺹뤸鹻𸸤뺸𸼤뺽𸰤鸼뤸𸺰𹸤𸻸𹼤𹰤𸼰뤸𰺹𺸤鸺𺼤𰻺𺰤븸뤸𻼰𻸤𱿻븸𻼤𹸰𻰤𱾹뤸𹾰𼸤𸻸𼼤鸺𼰤𰺹뤸𰻺𽸤븸𽼤𻾰𽰤𱾹뤸𱿻븸𾸤𸻸𾼤𱺹𾰤𰺸뤸뺹𿸤𱾸븸𿼤𰸰鸸𿰤𸺰뤸鸹𸸤껻𸼤鸺𸰤꾸뤸꾸𹸤참𹼤𸻻𹰤𱰸길뤸𸻸𺸤𰺹𺼤𰺸븸𺰤𱰸뤸𹸰𻸤찺𻼤껻𻰤鸺뤸꾸𼸤꾸𼼤𸻸𼰤참뤸𰺹𽸤𱰸길𽼤𰻺𽰤𰺸뤸뺺𾸤뺸𾼤鸸𾰤𰺸뤸𿸤뺺𿼤𿰤𰻻뤸츸𸸤𰺺𸼤麺𸰤𸺰뤸껸𹸤𸻻븸𹼤鸹𹰤뺸뤸鸸𺸤𰺼𺼤𰸰𺰤뺸뤸𸺰𻸤긹𻼤鸸𻰤𰺾뤸齾𼸤뺺𼼤뺸𼰤𹸰뤸뺺𽸤𸻻븸𽼤𰺹𽰤뤸𾸤𾼤𾰤齼뤸𸹸𿸤𸻻븼𿼤𿰤𰺹뤸鼺𸸤𸰰𸼤븺𸰤븺뤸麹𹸤𰻺뾸𹼤뺸𹰤鸾뤸𸺰𺸤麸𺼤븼𺰤𸹸뤸뺸𻸤鸾𻼤𹺰𻰤鼾뤸𼸤𰻺뾸𼼤𹸰𼰤뺸뤸鼺𽸤𹺰𽼤鼺𽰤𹱹뤸鹻𾸤뺸𾼤鸼𾰤𹺰뤸鹻𿸤뺸𿼤鸼𿰤𺺰뤸뺸𸸤𼸸𸼤𸹸𸰤뺸뤸븼𹸤𸹸𹼤뾻𹰤𱸹뤸뽸𺸤𱸹𺼤𹸰𺰤뺸뤸𹰰𻸤鼺𻼤𰸰뺸𻰤𻺰뤸뺸𼸤𱸸𼼤𼰤𱹻뤸𽸤𸹸𽼤𹸰𽰤뺸뤸𹰰𾸤鼺𾼤𸻻빰𾰤鸸뤸𰺹𿸤麸𿼤𸻻뺸𿰤𰺹뤸鸸𸸤麸𸼤뻾𸰤𱸹뤸뺸𹸤뺺𹼤𹸰𹰤뺸뤸𹰰𺸤鼺𺼤𱸹𺰤𱺹뤸뺸𻸤븼𻼤𱼹𻰤𹹸뤸찾𼸤𱸹𼼤𹸰𼰤뺸뤸𻰰𽸤뺸𽼤𽰤𺻸뤸𱺹𾸤뺸𾼤븼𾰤𱼸뤸鼺𿸤𻺰𿼤뺸𿰤𱸹뤸𸸤𱺹𸼤뺸𸰤鸾뤸𺺰𹸤뺸𹼤븼𹰤𸹸뤸뺸𺸤鼸𺼤𹺰𺰤𸻹뤸𰺹𻸤鼸𻼤𻰰𻰤𺹸뤸鸸𼸤𸻻빰𼼤𰺹𼰤뤸𽸤𽼤𽰤뤸𸹸𾸤𾼤𾰤龾뤸𸺰𿸤긹𿼤𸻹𿰤꼹뤸𰺹𸸤꺰𸼤龺𸰤꾸뤸𹺰𹸤갹𹼤뺸𹰤𰻻뤸𰺸𺸤뺺𺼤龺𺰤𸰰뤸뺸𻸤鸻븹𻼤껿𻰤𹸰뤸𼸤鸻븹𼼤𰺸𼰤뺺뤸𽸤𽼤𰺹𽰤뤸𾸤𸻹𾼤鸸𾰤𰺹뤸黼𿸤𱼹𿼤𹺰𿰤𱾹뤸𸻻빰𸸤𰺹𸼤𹸰𸰤麸뤸𹸤𻺰𹼤뺸븸𹰤뤸𱾹𺸤𱾸𺼤𺰤뤸𱼸𻸤𱾹츸𻼤캸𻰤𸻸뤸븸𼸤鰸𼼤𱸹𼰤참븸뤸𱾸𽸤븸𽼤鼸𽰤麸뤸𰺾𾸤𰸰꼸𾼤𾰤𱼸뤸뺸𿸤𱼺𿼤𸻹𿰤𰺹뤸麰𸸤𸻻빰𸼤𰺹𸰤𸺰뤸켺𹸤𸻸𹼤븾𹰤𱸹뤸𸹸𺸤𺼤𸹸𺰤뤸𻸤𸻸𻼤긹𻰤鹸뤸꾹𼸤𰻺𼼤꾸𼰤뤸𽸤븺𽼤꾹𽰤뺸뤸븸𾸤鰸𾼤𸻸𾰤꺹뤸꼹𿸤뺸𿼤龰𿰤鰸뤸𰻺𸸤갸𸼤뺸𸰤뤸𰺽𹸤𰺸𹼤𰺸𹰤鹾뤸뺹븸𺸤𰺺𺼤뺺𺰤꼸鸸뤸뺸𻸤龰𻼤𻰤갸뤸꾸𼸤뺸𼼤븸𼰤뤸꼹𽸤𽼤𽰤뤸𹹸𾸤뺸𾼤븼𾰤𱸹뤸뺸𿸤鸸𿼤𹹸𿰤𱰸뤸𰸰𸸤𸺰𸼤麸𸰤뺸뤸鸸𹸤鸻𹼤뺸𹰤꺸뤸鸻𺸤𰺹𺼤𰺺𺰤뤸𱿻꾸𻸤𰹰𻼤𸹸𻰤𸹸뤸𸹸𼸤꺿꼸𼼤찺𼰤뺸뤸븼𽸤𸹸𽼤𽰤뺸뤸븼𾸤𹹸𾼤龼𾰤龸뤸뺸𿸤龼𿼤𹹸𿰤𰺾뤸𰸱𸸤𸺰𸼤𱸹𸰤龿뤸𸹸𹸤𹼤𸹸𹰤𰺹뤸𹸰𺸤뺺𺼤븺𺰤𻹸뤸뺸𻸤긹𻼤鸾𻰤𹺰뤸𻻸𼸤𸻹𼼤𰺹𼰤뺺뤸븺𽸤븺𽼤𽰤뤸𸹸𾸤𾼤𾰤븺뤸𿸤𸹸𿼤𿰤뺸뤸鸾𸸤𸺰𸼤𸹸𸰤뺸뤸鸾𹸤𹺰𹼤𹹸𹰤뤸𸹸𺸤뺸𺼤鸸𺰤𰺸뤸鸻𻸤뺺𻼤黻𻰤麸뤸𹻸𼸤뺸𼼤븼𼰤켸뤸𸹸𽸤𽼤𽰤뤸뺸𾸤鸾𾼤𸺰𾰤𸻸뤸鸸𿸤𰺹𿼤꼸𿰤黾뤸𹺰𸸤𹹸𸼤뺸𸰤鸾뤸𹺰𹸤𱸹𹼤뿸𹰤𸹸뤸鸸𺸤뺸𺼤𰺸𺰤鸻뤸뺺𻸤鹼𻼤麸𻰤𹻸뤸𱺹𼸤뺸𼼤븼𼰤켸뤸𸹸𽸤𽼤𽰤뤸뺸𾸤鸾𾼤𸺰𾰤𹹸뤸참𿸤𰻻𿼤𰸰𿰤𺺰뤸뺸𸸤뺸𸼤鸾𸰤𻺰뤸뺸𹸤뺸𹼤鸾𹰤𻺰뤸뺸𺸤𹹸𺼤츺𺰤븺뤸𹸰𻸤캸𻼤鸾𻰤𹺰뤸𰺹𼸤鸸𼼤뺸𼰤鸼뤸鰸𽸤𰸰꺼𽼤𰺹𽰤麸뤸뺺𾸤𹸰𾼤븺𾰤𹺰뤸𸻸𿸤𸻸𿼤𰺹𿰤뺺뤸캸𸸤𹸰𸼤츸𸰤𹸰뤸뺺𹸤뻱𹼤𸹸𹰤𹻸뤸뺸𺸤𱺹𺼤븼𺰤츸뤸뺸𻸤𰺸𻼤鸰𻰤黾뤸𹺰𼸤뺺𼼤뺸𼰤鸾뤸𻺰𽸤뺺𽼤𰺹𽰤뺺뤸뺸𾸤鸾𾼤𻺰𾰤뺸뤸鸸𿸤𰻻𿼤𰸰𿰤𺺰뤸𸻸𸸤뺸𸼤길𸰤𹸰뤸𰺹𹸤𰺺꼸𹼤뺺𹰤뤸𺸤𹽸𺼤참𺰤𰺹黸뤸길𻸤𰸰𻼤𸺰𻰤𱸹뤸뺸𼸤𰺹𼼤뺺𼰤븸뤸뺸𽸤𱾸길𽼤鸾𽰤븺뤸𸰰𾸤𸻻𾼤길𾰤𸻹뤸븸𿸤𹺰𿼤𱼹𿰤뺸뤸𰺸𸸤𰺹𸼤뺺𸰤𸻸뤸븾𹸤𸹸𹼤𸹸𹰤鸸뤸뺸𺸤𰺽𺼤𰻻𺰤鹸뤸黼𻸤鰸𻼤𸻹𻰤𱾹뤸𱰸𼸤麾𼼤𸼰𼰤꾸뤸뺸𽸤𰻻𽼤𹸰𽰤𰺸뤸뺸𾸤𰺽𾼤뺺𾰤鸸뤸뺸𿸤𰺽𿼤𰻻𿰤黸뤸𸸤鹸𸼤𸰤𸹸뤸𹸤𹼤𹰤𸺰뤸𸹸𺸤뺸𺼤鸸𺰤𱰸뤸뺸𻸤黸𻼤𹺰𻰤𸹸뤸鸸𼸤뺸𼼤𰺸𼰤鸼뤸𸺰𽸤黾𽼤𹺰𽰤𸹸뤸𾸤𰸰뾸𾼤𾰤𸺰뤸𱾹𿸤𿼤𹻸𿰤𱼹뤸麰𸸤𹼰𸼤鸹𸰤𰻺뤸𱰸𹸤빺𹼤鹺𹰤鰹뤸츸𺸤鸻𺼤黼𺰤𺾰뤸𱼸鸸𻸤鸸𻼤𺺰𻰤뺸뤸뺸𼸤黼𼼤𺼰𼰤𱼸鸸뤸뺸𽸤麰𽼤𺺰𽰤鸸뤸뺸𾸤黼𾼤𺾰𾰤𱼸鸸뤸鸸𿸤𱼸鸸𿼤麰𿰤뤸𱰸𸸤鼸𸼤𻼰𸰤뤸𱾸𹸤𰺸뾸𹼤븸𹰤뤸𱼹𺸤𱾹𺼤뺸𺰤鸾뤸𺺰𻸤𱾸𻼤븸𻰤𻼰뤸뺸𼸤𱾸𼼤𼰤뤸뺸𽸤𻸰𽼤鸸𽰤𰺽뤸𰻻𾸤뺺𾼤𾰤鼺뤸𸺰𿸤𸹸𿼤鸸𿰤𰺸뤸鸾𸸤𹺰𸼤뺺𸰤𰺸뤸𹸰𹸤뺺𹼤𰺹𹰤뺺뤸츸𺸤𺼤캸𺰤뺸뤸𰺸𻸤뺺𻼤鸸𻰤뺸뤸黼𼸤𹰰𼼤𰺸𼰤뺺뤸𽸤𽼤𽰤뺸뤸鸾𾸤𹺰𾼤𸹸𾰤뺸뤸𰺸𿸤鸸𿼤鸼𿰤鰸뤸뺺𸸤𸼤鿺𸰤𸺰뤸븺𹸤뺸𹼤鸸𹰤꾽뤸𰻺𺸤𺼤껻𺰤븹뤸꼹𻸤鰸𻼤鹸𻰤𻹸뤸𰺸𼸤뺹𼼤龼𼰤꼼뤸鸿𽸤鿼𽼤𽰤𰺸뤸껿𾸤龰𾼤𹼰𾰤갹뤸갹𿸤븹𿼤𹼰𿰤𰺹뤸𰺹𸸤𰸱𸼤𸺰𸰤𸻻빰뤸길𹸤𰺹𹼤麸𹰤뤸𺸤𺼤뺸𺰤𰻻뤸𰸰𻸤𹺰𻼤𸹸𻰤鸸뤸뺸𼸤鿼𼼤𹰰𼰤𸹸뤸뺸𽸤𰻻𽼤𰺸𽰤鸸뤸龸𾸤𱼸𾼤뺽麹𾰤鸾뤸𸺰𿸤𰺸𿼤갹𿰤븺뤸갰𸸤𸼤𰺸𸰤긹뤸뺸𹸤龸𹼤𹰰𹰤꼹뤸𱾹𺸤꼹𺼤뺸𺰤龰뤸𹰰𻸤𸻸𻼤𻰤𰺹뤸鸿𼸤꺸𼼤齺麹𼰤뺸뤸鸼𽸤𻾰𽼤꼸鸸𽰤𰻺鸹뤸𾸤𰺸𾼤𾰤갹뤸𱰹𿸤꾸𿼤𿰤뺸뤸龰𸸤𹺰𸼤갸𸰤뺸뤸龸𹸤𻺰𹼤뺹𹰤찺븸뤸뺹𺸤鸾𺼤𻰰𺰤꼸鸸뤸뺸𻸤𰺸𻼤𹸰𻰤뺺뤸뺹𼸤鸾𼼤𹺰𼰤鿺뤸찺븸𽸤𹸰𽼤𽰤뤸꾸𾸤꼸鸸𾼤뺸𾰤龰뤸𿸤꺸𿼤길𿰤뺸뤸龸𸸤𸼤𱾸𸰤꼹뤸갹𹸤꾸𹼤𹰤𰺸뤸뺸𺸤鸾𺼤𻺰𺰤鹿뤸𹸰𻸤븺𻼤뺸꾻𻰤鿼뤸꼾𼸤갸𼼤鿺𼰤뤸𽸤뺸꾻𽼤龰𽰤𸰰뤸길𾸤뺸𾼤𰺹𾰤뺺뤸𿸤𿼤𿰤길뤸뺸𸸤鹻𸼤𸰤龹뤸鸸𹸤븸𹼤𹰰𹰤黻뤸鼹𺸤빸𺼤鹸𺰤鰹뤸鼾𻸤𸺰𻼤鸹𻰤𸻸뤸𱾹𼸤𱺹𼼤𱰸𼰤𰺸뤸鸰𽸤𰺸𽼤黾𽰤𸺰뤸𰻺𾸤뺸𾼤뺺𾰤𱺸뤸麾𿸤𿼤𱰸𿰤뤸𱸸𸸤븹𸼤𹼰𸰤𱺹뤸𰻺𹸤𰺸𹼤鸸𹰤뺸뤸𱺸𺸤鸸𺼤麼𺰤뤸鸻𻸤𰺺𻼤𰺸𻰤뺸뤸𰹰𼸤𸹸𼼤𸹸𼰤𸹸뤸鸿븸𽸤뺽𽼤鼸𽰤𺾰뤸鸹𾸤𸻸𾼤𱼹𾰤𱺹뤸𰺸𿸤鸰𿼤𰺸𿰤𱱺뤸黾𸸤𸺰𸼤𱾹𸰤鼺뤸𺼰𹸤뺸븸𹼤뺸𹰤鸼뤸𹾰𺸤𱰹𺼤鸾𺰤𺼰뤸𱰹𻸤𹸰𻼤𰺸𻰤뺸븸뤸𱰺𼸤𰺸𼼤꺰𼰤뺸뤸𰻻𽸤𰸰𽼤𸺰𽰤𱺸뤸뺸𾸤𰺽길𾼤𱱻𾰤麾뤸𿸤찺𿼤븽鸸𿰤鰸뤸鸸𸸤𸼤鸽𸰤龸뤸뺸𹸤븸𹼤𹰤鼸鸹뤸𺸤𺼤𺰤뺸뤸鸾𻸤𸺰𻼤𸹸𻰤뺸뤸鸸𼸤뺸𼼤鼸𼰤𹼰뤸麽뺸𽸤鼹𽼤𱰹𽰤뺸뤸黸𾸤𹼰𾼤𸻸𾰤𰺹뤸𰺸𿸤鸸𿼤𱾸𿰤뺸뤸뺺븸𸸤𱰸𸼤뺸𸰤黸뤸鸻𹸤𹼤𱾸𹰤𱸸뤸𺸤캸𺼤뺸𺰤𰻺뤸𰺸𻸤쾸𻼤𻰤𺾰뤸鸸𼸤𱰹𼼤뺸𼰤黸뤸𹼰𽸤𸻸𽼤𱼹𽰤鸼뤸뺸𾸤𰺺𾼤뺺𾰤𱰸뤸뺸𿸤黸𿼤𿰤鸻뤸鸸𸸤뺸𸼤鼸𸰤鼸鸾뤸𹸤麸𹼤𹰤뤸𺸤𺼤鼾𺰤𸺰뤸𸹸𻸤뺸𻼤鼼𻰤𹾰뤸鸹𼸤뺸𼼤鼸𼰤𹼰뤸𽸤𱾹𽼤뺸𽰤븸뤸𹼰𾸤𸻸𾼤뺸𾰤𰺹뤸鸻𿸤鸻𿼤𱰸𿰤뺸뤸뺺𸸤𱾸𸼤뺸𸰤븸뤸鸻𹸤𹼤𱰸𹰤𱸸뤸𺸤캸𺼤𱾹𺰤鼰뤸𹼰𻸤𱼹𻼤𰻺鸸𻰤𰺸뤸鸸𼸤뺸𼼤𱾸𼰤𱼸뤸븹𽸤𽼤鸻𽰤𰺺뤸𰺸𾸤鸹𾼤𰹰𾰤𸹸뤸𸹸𿸤𸹸𿼤𱼿鰸𿰤뺽뤸麰𸸤𺾰𸼤𱼹𸰤𱾹뤸뺸𹸤븸𹼤𹼰𹰤𰻺뺸뤸𹹸𺸤𱰸𺼤𱺹𺰤鸸뤸𸼰𻸤鹺𻼤뺸𻰤鸼뤸𻾰𼸤뺸𼼤鸾𼰤𻼰뤸븺𽸤𹸰𽼤뺸𽰤뺸뤸𰺺𾸤뺺𾼤뺸𾰤𰻻뤸𰸰𿸤𸺰𿼤𱾸𿰤뺺뤸뺸𸸤𰺽𸼤껰𸰤껻뤸𰺸𹸤𰻻𹼤뺺𹰤뺸뤸븸𺸤𺼤𱰸𺰤鸸뤸뺸𻸤鼸𻼤𻰤𱾹뤸𼸤𼼤𼰤齸뤸鿾𽸤𸺰𽼤긹𽰤뺸뤸龸𾸤𹼰𾼤𹱸𾰤𰺹뤸鹸𿸤𿼤鸰𿰤鿾뤸꺹𸸤𸺰𸼤𰺹𸰤갹뤸𹸤鸻𹼤𹰤븹뤸𸾰𺸤鸿𺼤꺸𺰤𰺸뤸갰𻸤𻼤𻰤鸾뤸𺺰𼸤길𼼤𱿻𼰤𰹰뤸𸹸𽸤𸹸𽼤𸹸𽰤𰺿뤸𰺽𾸤껰𾼤껿𾰤𰺸뤸갹𿸤鸰𿼤鿸𿰤𹼰뤸껻𸸤𰻺𸼤鸸𸰤꾹뤸뺸𹸤𰺺𹼤뺺𹰤갸뤸뺸𺸤鿸𺼤𺰤鸿뤸길𻸤뺸𻼤龸𻰤뤸𼸤𼼤𼰤뤸참𽸤黺𽼤𸺰𽰤꺹뤸뺸𾸤龼𾼤𹼰𾰤𹻸뤸꾹𿸤뺸𿼤븸𿰤𻼰뤸꺸𸸤𹽸𸼤𱸹𸰤𰺽뤸𰺸𹸤걺𹼤𰺹麸𹰤뤸龰𺸤𺼰𺼤꾸𺰤𰺹鹱뤸뺸𻸤龰𻼤𺾰𻰤꾸뤸뺸𼸤龰𼼤𺼰𼰤꾸뤸뺸𽸤𰸰𽼤𸺰𽰤𱾸뤸鸸𾸤𰻻𾼤븸𾰤𺰰뤸𿸤𰺺𿼤꾸𿰤𹸰뤸𸸤𸼤鸸𸰤뺸뤸𹸤鸿𹼤𹰤𰻻뤸𰻻𺸤鸿𺼤뺸𺰤𰺽뤸𻸤鸿𻼤뺸𻰤꼸븸뤸𼸤뺸𼼤龰𼰤𹼰뤸鸿𽸤긹𽼤뺸𽰤𰸰뤸𺺰𾸤뺸𾼤鸸𾰤𰺸뤸𰻻𿸤龰𿼤𹰰𿰤뤸𻺰𸸤뺸𸼤𰻻𸰤龰뤸𹰰𹸤꾹𹼤뺸𹰤龰뤸𹰰𺸤𰺺𺼤𺰤𹺰뤸꾸𻸤꾹𻼤갽𻰤鸿뤸𼸤뺸𼼤𰺺𼰤뺺뤸鸸𽸤븹𽼤𺼰𽰤꼸鸸뤸뺸𾸤𰸰𾼤𸺰𾰤𰺹뤸𰺸𿸤븸𿼤𻺰𿰤𰺹뤸뺸𸸤𰺸𸼤麸𸰤뺸뤸꼸𹸤𹼤𰻻𹰤𰻻뤸갸𺸤鸿𺼤걺𺰤뺸뤸𻸤𰺺𻼤뺺𻰤꼸鸸뤸뺸𼸤龰𼼤𼰤뺸뤸꾹𽸤꾸𽼤뺸𽰤븸뤸𾸤𰺽𾼤꺸𾰤뺸뤸龼𿸤𿼤꾹𿰤뤸𸸤뺸𸼤鸸𸰤𰺸뤸참𹸤꼸𹼤𱰸𹰤𰹰뤸𸹸𺸤𸹸𺼤𸹸𺰤鿻뤸麸𻸤𱾹𻼤𰻺𻰤참뤸鹸𼸤꼸𼼤껻𼰤𱾸뤸𽸤𽼤麸𽰤뺸뤸鸾𾸤𸺰𾼤𰺹𾰤뺸뤸鸾𿸤𺺰𿼤뺸𿰤𰺹뤸뺺𸸤뺸𸼤鸾𸰤𸺰뤸뺸𹸤껸𹼤𰻻𹰤𰺸뤸뺺𺸤𸻸𺼤븾𺰤𸹸뤸𸹸𻸤𻼤꺹𻰤뺸뤸龼𼸤𹰰𼼤𼰤𸻸뤸갽𽸤길𽼤꾸븹𽰤뤸갸𾸤꼹𾼤𻹸𾰤鸿뤸뺸𿸤鿼𿼤𸼰𿰤꺸뤸뺸𸸤鿼𸼤𺰰𸰤뺸뤸뺸𹸤꺰𹼤𹰤𰺸뤸뺺𺸤뺸𺼤뺺𺰤뺸뤸뺺𻸤븺𻼤뺸𻰤龼뤸꾸븹𼸤𼼤갸𼰤뤸𽸤𽼤뺸𽰤𰸰뤸𹺰𾸤𸹸𾼤뺸𾰤鸾뤸𸺰𿸤鼹𿼤𰺸𿰤뺺뤸뺸𸸤鼰𸼤𹰰𸰤鹸뤸麹𹸤뺸𹼤鼼𹰤𹰰뤸쾸𺸤𸻸𺼤鰸𺰤龸뤸뺸𻸤鸾𻼤𹰰𻰤𸻸뤸𰺹𼸤鸼븸𼼤뺸𼰤黼뤸𸾰𽸤𸻸𽼤𱸹𽰤뤸𱺹𾸤麺𾼤𸺰𾰤𸻸뤸뺸𿸤鸾𿼤𺺰𿰤뺸뤸𱸹𸸤븼𸼤𱺹𸰤뺸뤸鸾𹸤𹺰𹼤𸻸𹰤뺸뤸鸾𺸤𺺰𺼤뺸𺰤𱸹뤸𱺹𻸤븼𻼤켸𻰤뺸뤸鸾𼸤𹺰𼼤𸻸𼰤뺸뤸鸾𽸤𸺰𽼤鸹𽰤𱸹뤸븼𾸤𱺹𾼤𾰤𱸹뤸𱺹𿸤𱼹𿼤𿰤쾸뤸麺𸸤𸺰𸼤𸻸𸰤뺸뤸鸾𹸤𸺰𹼤𱸹𹰤𱺹뤸븼𺸤𱼹𺼤𹸰𺰤𱼹뤸븺𻸤𱼹𻼤𱸹𻰤𱺹뤸𼸤𱾹𼼤麺𼰤𺺰뤸뺸𽸤뺸𽼤鸾𽰤𻺰뤸뺸𾸤뺸𾼤𰺹𾰤뺺뤸뺸𿸤참𿼤뺺𿰤뾸뤸𰻺꺸𸸤鸻𸼤麸𸰤𱰸뤸𹸰𹸤찺𹼤꺰𹰤뤸𰺸𺸤뺺𺼤𸻸𺰤鰸뤸麸𻸤뺸𻼤鼼𻰤뤸龸𼸤鼸鸸𼼤뺸𼰤鼰뤸𽸤鸽𽼤𽰤뤸뺸𾸤鸾𾼤𸺰𾰤𱰹뤸뺸𿸤黸𿼤鰸𿰤꺸뤸뺸𸸤𰻻𸼤𰸰𸰤뤸𱰸𹸤𹼤븺𹰤븺뤸𺸤𸹸𺼤𰺺𺰤齰뤸𰻻꾸𻸤麸𻼤𰻻𻰤𸼰뤸𱸹𼸤𰺸𼼤𱹻𼰤뤸𸹸𽸤𽼤𽰤鹸뤸뺸𾸤鸿𾼤𸺰𾰤龹뤸鰹𿸤𺻸𿼤𰺹𿰤鼹뤸캸븸𸸤켸𸼤𸰤츸븹뤸𰺹𹸤츺븸𹼤𹰤鸸뤸鹺뺸𺸤麹𺼤츸𺰤캸뤸𻸤켸𻼤츺𻰤뺸뤸鸽𼸤𰺸𼼤齼𼰤龸뤸𽸤鰸𽼤龹𽰤뺸뤸븸𾸤𹰰𾼤𺻸𾰤鹺뤸𰺹𿸤鼹𿼤캸𿰤켸뤸𸸤츸𸼤𰺹𸰤츺뤸𹸤鸽뺸𹼤鸸𹰤鹺뺸뤸麹𺸤츸𺼤캸𺰤뤸켸𻸤츺𻼤龸𻰤뺸뤸븸𼸤𼼤𺻸𼰤뤸𽸤𽼤𻿸𽰤鹾뤸긹𾸤鸾𾼤뺸𾰤뤸븸𿸤𰺸𿼤𰺽𿰤𱰹뤸𸸤꼹𸼤𰻻𸰤뺺뤸걺𹸤꾹𹼤鸿𹰤뺸뤸𰺸𺸤𰺽𺼤𰻻𺰤뺺뤸꺹𻸤𻼤갽𻰤鸿뤸뺸𼸤𰺸𼼤鸻븸𼰤𰺽뤸𰻻𽸤뺺𽼤鸾𽰤뺸뤸𾸤鸿𾼤𾰤뤸뺸𿸤𰺸𿼤븸𿰤𰺽뤸𰻻𸸤뺺𸼤𸰤뤸𹸤뺸𹼤븼𹰤츸뤸鸸𺸤𰻺꾸𺼤𰺺𺰤뤸𰺸𻸤𰻻𻼤뺺𻰤𹹸뤸뺸𼸤븼𼼤𱸹𼰤뺸뤸鸰𽸤꼸𽼤뺸𽰤𰺸뤸뺺𾸤鸸𾼤뺸𾰤黼뤸𺰰𿸤뺸𿼤뺸𿰤鸼뤸𸰰𸸤뺸𸼤鼺𸰤𸺰뤸𸹸𹸤𰺸𹼤뺺𹰤뺸뤸鸾𺸤𺾰𺼤븺𺰤𹸰뤸뺸𻸤𰺹𻼤뺺𻰤뺸뤸鸸𼸤𰺾𼼤鸸𼰤참뤸𰻻𽸤𰸰𽼤𸺰𽰤鸸뤸𹸰𾸤鸹𾼤𸻻뺸𾰤𰺹뤸鸸𿸤뺸𿼤黼𿰤𻺰뤸븺𸸤뺸𸼤鸾𸰤𻺰뤸븺𹸤鸸𹼤𸻸𹰤𰸰꼸뤸𻺰𺸤븺𺼤鸸𺰤뺸뤸黼𻸤鰸𻼤뺸𻰤뺸뤸𰻻𼸤𰸰𼼤𹺰𼰤𰸰꺸뤸뺸𽸤鸾𽼤𺺰𽰤뺸뺻뤸𰸰꺸𾸤𺺰𾼤뺸뺻𾰤𰸰꺸뤸𻺰𿸤븺𿼤뺸뺻𿰤鸾뤸𺺰𸸤븺𸼤뺸𸰤𰺸뤸뺺𹸤뺻𹼤鸼𹰤𸾰뤸𸹸𺸤븺𺼤뺸뺻𺰤뺺뤸뺸뺻𻸤뺺𻼤鸹𻰤뺸뤸鼸𼸤鰸𼼤𸹸𼰤뺸뺻뤸뺺𽸤麹𽼤뺸𽰤鼼뤸鰸𾸤鸸𾼤𾰤𱸸뤸𿸤麸𿼤뺸𿰤鼸뤸𸸤뺸뺻𸼤𸰤뤸𹸤참𹼤黺𹰤𺺰뤸븺𺸤鸸𺼤𰻻𺰤𰸰뤸𹺰𻸤𸻸𻼤뺸𻰤鸾뤸𺺰𼸤뺸𼼤𸻸𼰤𰺺꼸뤸뺺𽸤븺𽼤𹸰𽰤븺뤸鸾𾸤𻺰𾼤븺𾰤뺸뤸𰺸𿸤鸼𿼤𸾰𿰤뺺뤸뺸𸸤뺺𸼤뺸𸰤뺺뤸鸹𹸤뺸𹼤鼸𹰤鰸뤸븺𺸤뺸𺼤鸸𺰤꼸뤸뺸뺻𻸤𰺸𻼤뺺𻰤뤸𱸸𼸤𼼤鸸𼰤뤸𽸤𽼤𸻸𽰤𰺹뤸뺺𾸤뺺𾼤鼹𾰤뺸뤸鼰𿸤鰸𿼤麹𿰤𰺸뤸鸼𸸤鹺뾸𸼤鸸𸰤켼뤸𱸹𹸤𹼤캼𹰤麸뤸鼾𺸤𺼤츺𺰤뺸뤸鸾𻸤𸺰𻼤鸿𻰤븼뤸𱸸𼸤鸿𼼤뺸𼰤𰻺뤸꾸𽸤鸻𽼤뺸𽰤𰻺뤸鸻𾸤뺸𾼤鸻𾰤𰻺鸸뤸麸𿸤鼸鸸𿼤뺸𿰤鼰뤸𸸤麹𸼤𸰤뤸𹸤𱸹𹼤뺸𹰤麸뤸鰸𺸤𱺹𺼤麸𺰤뤸뺸𻸤龼𻼤𻰤鹸뤸𹼰𼸤𱰹𼼤𸻸𼰤鸹뤸갽𽸤뺸𽼤𽰤븸뤸𹼰𾸤𰺸𾼤𰻺𾰤꼸뤸𱼸𿸤쾸龿𿼤鸾𿰤𰺸뤸꾹𸸤긽𸼤꼸鸸𸰤鿾뤸𸼰𹸤𰺽𹼤鸻𹰤𱰸뤸븹𺸤븸𺼤𺰤鸾뤸麸𻸤꺸𻼤뺸𻰤龼뤸𼸤갸𼼤𰻺꾸𼰤걺꺸뤸껰𽸤𰹰𽼤𸹸𽰤𸹸뤸𸹸𾸤꾿𾼤鸺𾰤𰻻뤸𰹰𿸤𸹸𿼤𸹸𿰤𸹸뤸갿𸸤껿𸼤𰸰𸰤鸾뤸𸺰𹸤𱰸𹼤뺸𹰤鸾뤸𺺰𺸤鸾𺼤𱰸𺰤黾뤸𺼰𻸤鹸𻼤黺𻰤𺼰뤸𱰹𼸤鸰𼼤𰻺𼰤黼뤸𻾰𽸤鸸𽼤뺸𽰤𰻺뤸黸𾸤𻾰𾼤𱰸𾰤뺸뤸鸾𿸤𺺰𿼤𿰤鿾뤸𻰰𸸤𸼤𰹰𸰤𸹸뤸𸹸𹸤𸹸𹼤븸𹰤𹺰뤸𺸤𹸰𺼤𺰤𻼰뤸𻸤𹸰𻼤𰻺꾸𻰤𰻺꾸뤸𰺸𼸤𼼤鸿𼰤뤸𸻸𽸤갸𽼤鸿𽰤麺뤸𱸸𾸤뺸𾼤麸𾰤뤸𱺸𿸤𿼤𿰤𸹸뤸𸸤참𸼤𰻻𸰤𰸰뤸𹺰𹸤𸹸𹼤뺸𹰤鸾뤸𹺰𺸤𸹸𺼤뺸𺰤鸾뤸𸺰𻸤𸹸𻼤뺸𻰤𰺽뤸鸸𼸤黼𼼤鰸𼰤𸹸뤸쾸𽸤𽼤𹼰𽰤𰺸뤸뺸𾸤鸾𾼤𻺰𾰤븺뤸뺸𿸤鸾𿼤𹺰𿰤𰸰꺸뤸𹸰𸸤븺𸼤𻺰𸰤참뤸𹸤𸾰𹼤𰺸𹰤참뤸𸻸𺸤껻𺼤𰺹𺰤𱰸길뤸黰𻸤麻𻼤븸𻰤𸾰뤸𸻺𼸤𰺸𼼤𹸰𼰤뺺뤸鹸𽸤뺸𽼤鸼𽰤𸺰뤸鸹𾸤麸𾼤븺𾰤𰻺뺸뤸𱺸𿸤뺸𿼤𱸹𿰤鸾뤸𸺰𸸤鸸𸼤𸰤𸹸뤸뺸𹸤鸸𹼤𰺽𹰤꼸뤸𰺸𺸤𰻺𺼤麸𺰤鰸뤸𸹸𻸤鼺𻼤𻰤𰻺뺸뤸𸻸𼸤뺺𼼤鸹𼰤뺸뤸뺸𽸤鸰𽼤𽰤뺺뤸鸸𾸤뺸𾼤뺺𾰤黾뤸𹼰𿸤𱸹𿼤𱸹𿰤𸻸뤸麹𸸤𸼤𸻸𸰤龹뤸𱺸𹸤鸹𹼤鼹𹰤𱿺뺸뤸𰺸븸𺸤鹸𺼤𱰸𺰤켹뤸뺹븸𻸤찹𻼤𰺽𻰤꼸뤸𰺸𼸤鸻𼼤𰹰𼰤𸹸뤸𸹸𽸤𸹸𽼤𰺿𽰤𰹰뤸𸹸𾸤𸹸𾼤𸹸𾰤鿻뤸𰻺𿸤꼸𿼤𰺸𿰤鸸뤸鼺𸸤𸼤뺺븹𸰤캺뤸𹸤𹼤𹰤麹뤸뺸𺸤鼼𺼤鸹𺰤鰸뤸𰻺뺸𻸤𱺸𻼤뺸𻰤鸾뤸𸺰𼸤𱸹𼼤𼰤𸹸뤸𰺹𽸤麸𽼤鰸𽰤𰻺뤸麹𾸤鸸𾼤뺸𾰤뤸鼸𿸤𿼤𿰤뤸𸻸𸸤𰺹𸼤뺺𸰤븺뤸鸹𹸤𰺸𹼤𰺸𹰤캼뤸츼𺸤𱸸𺼤𱺸𺰤𱼹뤸𻸤𱾹𻼤麺𻰤𸺰뤸鸸𼸤𹸰𼼤긹𼰤鼺뤸𽸤𰺸𽼤긹𽰤뤸𾸤𾼤뺹𾰤𰸰뤸𹺰𿸤𸻸𿼤𰺹𿰤뺺뤸븺𸸤鸸𸼤뺸𸰤黼뤸갹𹸤鹸𹼤𹰰𹰤뤸뺸𺸤𰻻𺼤𰸰𺰤𺺰뤸뺸𻸤鹸𻼤뺸𻰤𰸰뤸𻺰𼸤뺸𼼤𸻺𼰤鸸뤸𰺹𽸤黼𽼤𹺰𽰤뺸뤸𰸰𾸤𻺰𾼤뺸𾰤뺸뤸𰸰𿸤𺺰𿼤븸𿰤뺸뤸𰸰𸸤𹺰𸼤갹𸰤뺸뤸츸𹸤븼𹼤𹻸𹰤뺸뤸𰺹𺸤뺺𺼤𹸰𺰤븸뤸𸻸𻸤𰺹𻼤𹸰𻰤뺺뤸𼸤𱸹𼼤鹸𼰤鹺쾸뤸뺸𽸤鸾𽼤𺺰𽰤鸽뤸齾𾸤𹺰𾼤鿾𾰤뺸뤸鸾𿸤𹺰𿼤𺱺𿰤𹸰뤸鰹𸸤𸺰𸼤𱸸𸰤븺뤸𹸰𹸤븺𹼤𹰤𱺹뤸鰹𺸤齺𺼤𹺰𺰤븹뤸뺹𻸤鸾𻼤𺺰𻰤븺뤸뺸𼸤𼼤𰺸𼰤𹸰뤸뺺𽸤뺹𽼤鸾𽰤𸺰뤸齾𾸤뺸𾼤𰺸𾰤뺺뤸뺹𿸤鸾𿼤𻺰𿰤鸽뤸齾𸸤𹺰𸼤길𸰤뺸뤸𰺹𹸤𹸰𹼤뺺𹰤뺸뤸길𺸤𰺹𺼤뺺𺰤𹸰뤸븺𻸤鸸𻼤𰻻𻰤𰸰뤸𼸤鿺𼼤𼰤麹뤸뺸𽸤鼼𽼤鰸𽰤𰻻뤸𰸰𾸤𸺰𾼤뾸𾰤뺸뤸껸𿸤𰺸𿼤𰻻𿰤꾸뤸鼸𸸤龸𸼤𱺹𸰤켹뤸𹸤𱸹𹼤麺𹰤𹺰뤸𰺹𺸤켹𺼤鸸𺰤𺺰뤸뺸𻸤뺸𻼤𱸹𻰤𰸰뤸𸺰𼸤𱺹𼼤𼰤𸹸뤸麺𽸤𺺰𽼤뺸𽰤𰺹뤸𰻺𾸤𹸰𾼤鰺츸𾰤뺸뤸𰺸𿸤鸾𿼤𿰤뺺뤸𸸤麸𸼤齺𸰤𻺰뤸鸽𹸤븺𹼤븺𹰤鸽뤸齾𺸤𺼤鹺쾸𺰤뤸𺺰𻸤븺𻼤뺸𻰤鸾뤸𸺰𼸤鿾𼼤뺸𼰤鸾뤸𹺰𽸤鿾𽼤𸻸𽰤뺺뤸뺸𾸤뺺𾼤𹺰𾰤鹸뤸뺸𿸤齼𿼤鰸𿰤𱾹뤸𱱺쾸𸸤뺸𸼤𰻻𸰤𰸰뤸𻺰𹸤鸽𹼤𰻺븹𹰤𰸰븸뤸𻺰𺸤鸽𺼤麹𺰤뾸뤸뺸𻸤鸾𻼤𹺰𻰤麸뤸뺸𼸤鿺𼼤𸺰𼰤뺺뤸𹸰𽸤뺸𽼤뺸𽰤𹸰뤸뺺𾸤鼾𾼤𾰤뾸뤸鸽𿸤뺸𿼤齼𿰤뤸𱱺쾸𸸤𸼤𸰤뤸𹸤𸹸𹼤뺸𹰤鸾뤸𺺰𺸤뺸𺼤𰺸𺰤鸾뤸𹺰𻸤뺺𻼤뺸𻰤길뤸𰺹𼸤뺺𼼤뺸𼰤鸾뤸𸺰𽸤𸻻빰𽼤븺𽰤鸹뤸𾸤𱸹𾼤𹹸𾰤뤸𱸹𿸤鸰𿼤𿰤𸹸뤸𸸤𱸹𸼤鸸𸰤𰻻뤸𰸰𹸤𻺰𹼤븺𹰤𰻻뤸𰸰𺸤𻺰𺼤뺸𺰤뺸뤸뺺𻸤뺸𻼤뺺𻰤뤸𱸹𼸤𰺹𼼤뺺𼰤뤸𽸤뺸𽼤鸾𽰤𻺰뤸뺸𾸤뺸𾼤뺺𾰤븺뤸뺸𿸤鸾𿼤𻺰𿰤뺹뤸뺸𸸤뺺𸼤븺𸰤뺹뤸𰸰𹸤𸺰𹼤𸹸𹰤뺸뤸鸾𺸤𹰰𺼤𰺹𺰤뺺뤸𻸤𸹸𻼤뺸𻰤𰻻뤸𰸰𼸤𹺰𼼤𱰹𼰤뺸뤸黸𽸤鰸𽼤𸻻빰𽰤𱾹뤸𰻺꺸𾸤鸸𾼤麸𾰤𱰸뤸뺸𿸤黸𿼤𿰤𰻺꺸뤸鸸𸸤𰸰꾸𸼤𻺰𸰤뺸뤸뺸𹸤鹻𹼤𰺹𹰤麸뤸뺺𺸤뺸𺼤鸾𺰤𻺰뤸참𻸤뺸𻼤𰻻𻰤𰸰뤸𺺰𼸤참𼼤뺸𼰤𰺹뤸뺺𽸤참𽼤𰻻𽰤𰸰뤸𹺰𾸤뺸𾼤鸾𾰤𻺰뤸鸸𿸤뺸𿼤鸾𿰤𺺰뤸뺸𸸤鸸𸼤뺸𸰤꾸뤸𰺹𹸤뺺𹼤뺸𹰤鸾뤸𺺰𺸤뺸𺼤뺸𺰤𰸰뤸𸺰𻸤黺𻼤뺸𻰤𰺹뤸뺺𼸤𻾰𼼤뺸𼰤뺸뤸길𽸤𰺹𽼤뺺𽰤뺸뤸鸾𾸤𺺰𾼤鸸𾰤𰺸뤸鸰𿸤黾𿼤𸺰𿰤뺺뤸뺸𸸤길𸼤𰺹𸰤뺺뤸鸸𹸤𸻻빰𹼤麸𹰤뤸𸹸𺸤𺼤참𺰤𰻻뤸𰸰𻸤𺺰𻼤뺹𻰤𸻸뤸𰺺길𼸤𹸰𼼤뺺𼰤鸾뤸𸺰𽸤껻𽼤𰸰꺸𽰤𺺰뤸뺸𾸤껻𾼤𰻻𾰤𰺸뤸꾸𿸤鸼𿼤𺺰𿰤뺸뤸뺸𸸤鸾𸼤𺺰𸰤𰺹뤸𰺹𹸤뺺𹼤𹸰𹰤𱸹뤸鸾𺸤𸺰𺼤𱸹𺰤뤸𰺸𻸤𻼤𸹸𻰤뺸뤸鸸𼸤꾸𼼤𰺸𼰤𰺹뤸뺺𽸤𽼤𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤齸𸰤齸뤸𸸸𹸤뼱𹼤𼱼𹰤뤸𺸤𺼤𱺽뾽𺰤갹뤸뼿𻸤밹𻼤鰰𻰤鰾뤸뼸뾼𼸤칻𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𼼾뤸𻹻𿸤𻸻𿼤𸸸𿰤𻹻黼뤸𻼻黸 \ No newline at end of file diff --git a/firmware/Touch screen calibration files Touch/SileadTouch.sys b/firmware/Touch screen calibration files Touch/SileadTouch.sys new file mode 100644 index 0000000000000000000000000000000000000000..fc869f663cbb6e4b18e74cc6bd878ee76898ff6b GIT binary patch literal 84480 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 literal 0 HcmV?d00001 diff --git a/firmware/silead_ts.fw b/firmware/silead_ts.fw new file mode 100644 index 0000000000000000000000000000000000000000..59cb875d7b99b714273d8bfab10cc4b5a37b20a6 GIT binary patch literal 19428 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 literal 0 HcmV?d00001 diff --git a/tools/AUTHORS.md b/tools/AUTHORS.md new file mode 100644 index 0000000..c1622f1 --- /dev/null +++ b/tools/AUTHORS.md @@ -0,0 +1,3 @@ +fw_extractor is (c) 2013-2014 by Joe Burmeister +fwtool, unscramble, untscfg and autoconvert are (c) 2015-2016 by Gregor Riepl +scanwindrv is (c) 2018 by Gregor Riepl , based on an example script by Bernhard Übelacker \ No newline at end of file diff --git a/tools/Firmware/Silead.pm b/tools/Firmware/Silead.pm new file mode 100644 index 0000000..9a14763 --- /dev/null +++ b/tools/Firmware/Silead.pm @@ -0,0 +1,530 @@ +package Firmware::Silead; + +use strict; +use IO::File; + +our $MAGIC = 'GSLX'; +our $FORMAT = 1; +our $HEADER_SIZE = 24; +our $PAGE_SIZE = 132; + +sub _unpack_header { + my ($header) = @_; + return (unpack '(a4a4S4C4L)<', $header); +} + +sub _unpack_page { + my ($buffer) = @_; + return (unpack '(S2a128)<', $buffer); +} + +sub _pack_header { + my ($model, @params) = @_; + return pack '(a4a4S4C4L)<', $MAGIC, $model, $FORMAT, @params +} + +sub _pack_page { + my ($page, $data) = @_; + return pack '(S2a128)<', $page, length $data, $data; +} + +sub new { + my ($class) = @_; + return bless { + pages => { }, + model => '', + touches => 0, + width => 0, + height => 0, + swapped => 0, + xmirrored => 0, + ymirrored => 0, + tracking => 0, + }, ref $class ? ref $class : $class; +} + +sub load { + my ($class, $handle) = @_; + if (!ref $handle) { + $handle = IO::File->new($handle, 'r'); + } + if (!defined $handle) { + $@ = "Invalid file handle"; + return undef; + } + binmode $handle; + read $handle, my $header, $HEADER_SIZE; + my ($magic, $model, $format, $touches, $width, $height, $swapped, $xmirrored, $ymirrored, $tracking, $pages) = _unpack_header $header; + if ($magic ne $MAGIC) { + $@ = "Invalid magic $magic"; + return undef; + } + if ($format ne $FORMAT) { + $@ = "Invalid file format $format"; + return undef; + } + my $self = bless { + pages => { }, + model => $model, + touches => $touches, + width => $width, + height => $height, + swapped => $swapped, + xmirrored => $xmirrored, + ymirrored => $ymirrored, + tracking => $tracking, + }, ref $class ? ref $class : $class; + for (my $i = 0; $i < $pages; $i++) { + read $handle, my $buffer, $PAGE_SIZE; + my ($address, $size, $data) = _unpack_page $buffer; + if (!$self->set_page($address, substr $data, 0, $size)) { + return undef; + } + } + return $self; +} + +sub save { + my ($self, $handle) = @_; + if (!ref $handle) { + $handle = IO::File->new($handle, 'w'); + } + if (!defined $handle) { + $@ = "Invalid file handle"; + return 0; + } + binmode $handle; + my @pages = $self->get_pages; + my $header = _pack_header $self->model, $self->touches, $self->width, $self->height, $self->swapped, $self->xmirrored, $self->ymirrored, $self->tracking, scalar(@pages); + print $handle $header; + for my $page (@pages) { + my $pagedata = $self->get_page($page); + my $buffer = _pack_page $page, $pagedata; + print $handle $buffer; + } + return 1; +} + +sub unpack { + my ($class, $data) = @_; + my $header = substr $data, 0, $HEADER_SIZE; + my ($magic, $model, $format, $touches, $width, $height, $swapped, $xmirrored, $ymirrored, $tracking, $pages) = _unpack_header $header; + if ($magic ne $MAGIC) { + $@ = "Invalid magic $magic"; + return undef; + } + if ($format ne $FORMAT) { + $@ = "Invalid file format $format"; + return undef; + } + my $self = bless { + pages => { }, + model => $model, + touches => $touches, + width => $width, + height => $height, + swapped => $swapped, + xmirrored => $xmirrored, + ymirrored => $ymirrored, + tracking => $tracking, + }, ref $class ? ref $class : $class; + for (my $i = 0; $i < $pages; $i++) { + my $buffer = substr $HEADER_SIZE + $i * $PAGE_SIZE, $PAGE_SIZE; + my ($address, $size, $data) = _unpack_page $buffer ; + if (!$self->set_page($address, substr $data, 0, $size)) { + return undef; + } + } + return $self; +} + +sub pack { + my ($self) = @_; + my $data = ''; + my @pages = $self->get_pages; + my $header = _pack_header $self->model, $self->touches, $self->width, $self->height, $self->swapped, $self->xmirrored, $self->ymirrored, $self->tracking, scalar(@pages); + $data .= $header; + for my $page (@pages) { + my $pagedata = $self->get_page($page); + my $buffer = _pack_page $page, $pagedata; + $data .= $buffer; + } + return $data; +} + +sub import_scrambled { + my ($self, $input) = @_; + my $tscfg = ''; + for my $byte (split //, $input) { + my $descrambled = chr(ord($byte) ^ 0x88); + $tscfg .= $descrambled; + } + return $self->import_tscfg($tscfg); +} + +sub import_tscfg { + my ($self, $input) = @_; + my ($cfg, $fw) = (0, ''); + for my $line (split /\n/, $input) { + if ($cfg and $line =~ /};/) { + $cfg = 0; + } + if ($line =~ /TS_CFG_DATA|GSLX68X_FW/) { + $cfg = 1; + } + if ($cfg) { + $line =~ s/\s//g; + $line = lc($line); + if ($line =~ /{0x([0-9a-f]+),0x([0-9a-f]+)},/) { + my $address = hex($1); + my $data = hex($2); + $fw .= pack '(LL)<', $address, $data; + } + } + } + return $self->import_fw($fw); +} + +sub import_fw { + my ($self, $input) = @_; + + my $length = length $input; + + my ($page, $lastaddr, $data); + for (my $offset = 0; $offset + 7 < $length; $offset += 8) { + my $buffer = substr $input, $offset, 8; + my ($addr, $value) = unpack '(L2)<', $buffer; + if ($addr == 0xf0) { + if (defined $data) { + $self->set_page($page, $data) or return 0; + } + $page = $value; + $lastaddr = undef; + $data = ''; + printf "Got page 0x%02x\n", $page; + } else { + if (!defined $page) { + $@ = "Invalid firmware: page command missing at start"; + return 0; + } + if ($addr > 128) { + $@ = sprintf "Invalid firmware: invalid address %d at page 0x%02x, max 128", $addr, $page; + return 0; + } + if (defined $lastaddr and $addr != $lastaddr + 4) { + $@ = sprintf "Invalid firmware: non-consecutive at page 0x%02x, address 0x%02x, expected 0x%02x", $page, $addr, $lastaddr + 4; + return 0; + } + $data .= substr $buffer, 4, 4; + $lastaddr = $addr; + } + } + if (defined $page and defined $data) { + # the last page has not been stored yet + return $self->set_page($page, $data); + } + return 1; +} + +sub export_fw { + my ($self) = @_; + my $data = ''; + my @pages = $self->get_pages; + for my $page (@pages) { + my $pagedata = $self->get_page($page); + $data .= pack '(L2)<', 0xf0, $page; + my $length = length $pagedata; + for (my $offset = 0; $offset + 3 < $length; $offset += 4) { + my $word = substr $pagedata, $offset, 4; + $data .= pack '(La4)<', $offset, $word; + } + } + return $data; +} + +sub set_page { + my ($self, $page, $data) = @_; + if ($page > 0xff) { + $@ = "Invalid page number $page"; + return 0; + } + if (length $data > 128) { + $@ = "Page too large"; + return 0; + } + $self->{pages}->{$page} = $data; + return 1; +} + +sub delete_page { + my ($self, $page) = @_; + if (!exists $self->{pages}->{$page}) { + $@ = "Page number $page does not exist"; + return 0; + } + delete $self->{pages}->{$page}; + return 1; +} + +sub get_pages { + my ($self) = @_; + return sort { $a <=> $b } keys %{$self->{pages}}; +} + +sub get_page { + my ($self, $page) = @_; + return $self->{pages}->{$page}; +} + +sub touches { + return shift->{touches}; +} + +sub set_touches { + my ($self, $value) = @_; + $self->{touches} = $value; +} + +sub model { + return shift->{model}; +} + +sub set_model { + my ($self, $value) = @_; + $self->{model} = $value; +} + +sub width { + return shift->{width}; +} + +sub set_width { + my ($self, $value) = @_; + $self->{width} = $value; +} + +sub height { + return shift->{height}; +} + +sub set_height { + my ($self, $value) = @_; + $self->{height} = $value; +} + +sub swapped { + return shift->{swapped}; +} + +sub set_swapped { + my ($self, $value) = @_; + $self->{swapped} = $value; +} + +sub xmirrored { + return shift->{xmirrored}; +} + +sub set_xmirrored { + my ($self, $value) = @_; + $self->{xmirrored} = $value; +} + +sub ymirrored { + return shift->{ymirrored}; +} + +sub set_ymirrored { + my ($self, $value) = @_; + $self->{ymirrored} = $value; +} + +sub tracking { + return shift->{tracking}; +} + +sub set_tracking { + my ($self, $value) = @_; + $self->{tracking} = $value; +} + +=head1 NAME + +Firmware::Silead - Silead touchscren firmware packager + +=head1 SYNOPSIS + + use Firmware::Silead; + my $rep = Firmware::Silead->new(); + printf "width=%d height=%d num_touches=%d\n", $req->width, $rep->height, $rep->touches; + $rep->add_page(0x00, "\0" x 128); + $rep->save('firmware.fw'); + + $rep = Firmware::Silead->load('firmware.fw'); + print unpack('H*', $req->get_page(0x00)); + +=head1 DESCRIPTION + +=head2 Constructors + +On error, all constructors set C<$@> to a description +of the error and return C. + +=head3 C + +Creates a new firmware image without data. + +=head3 C + +Loads a firmware image from a file. +C<$io> may be a file handle or a file name. + +=head3 C + +Unpacks a firmware image from a byte string. + +=head2 Import/Export + +These methods allow importing firmware data from various formats. +Limited export is also available. + +Note: Page order is not preserved when importing firmware. +Pages are always sorted sequentially. + +=head3 C + +Import a firmware image from a scrambled TS_CFG.h byte string, as used in the form +of SileadTouch.fw by newer Windows drivers. + +=head3 C + +Import a firmware image from a plain TS_CFG.h byte string, as used by older +Windows drivers. + +=head3 C + +Import a firmware image in legacy format, as used by most other Linux and +Android drivers. + +=head3 C + +Export a firmware image into legacy format, as usable by most other Linux and +Android drivers. A binary string is returned. + +=head2 Storage + +=head3 C + +Saves the firmware data to a file. +C<$io> may be a file handle or a file name. + +=head3 C + +Packs a firmware image into a byte string and returns it. + +=head2 Accessors + +=head3 C + C + +Gets/sets the controller model ID. +The ID is a 4-character ASCII string identifying the +particular controller supported by this firmware. + +Examples: 1680, 3682 + +=head3 C + C + +Gets/sets the panel width. + +=head3 C + C + +Gets/sets the panel height. + +=head3 C + C + +Gets/sets the number of supported touch points. + +=head3 C + C + +Gets/sets the axis swapping flag. +If true, the X and Y axes are swapped. + +=head3 C + C + +Gets/sets the X axis mirroring flag. +If true, the X axis is inverted. + +=head3 C + C + +Gets/sets the y axis mirroring flag. +If true, the Y axis is inverted. + +=head3 C + C + +Gets/sets the software tracking flag. +If true, hardware finger tracking is not available and +driver finger tracking will be used instead. + +=head2 Page access + +On error, all page accessors set C<$@> to a description +of the error. They return 1 on success, 0 on error. + +=head3 C + +Returns the list of defined pages (their page addresses, actually). + +=head3 C + +Returns the binary data for page number C<$page_no>. + +=head3 C + +Stores the data of page number C<$page_no>. Automatically defines +the page if it did not exist previously. + +=head3 C + +Removes page C<$page_no>. + +=head1 FIRMWARE FORMAT + +=head2 New-style firmware file format, version 1 + + Offset | Type | Description + ------------------------------------------------------------------- + 0 | u8[4] | ASCII 'GSLX' (magic) + 4 | u8[4] | Touchscreen model (ASCII string) + 8 | u16le | File format version (1) + 10 | u16le | Number of supported touch events + 12 | u16le | Panel width (0..4095) + 14 | u16le | Panel height (0..4095) + 16 | u8 | 1 if X and Y axis are swapped, 0 otherwise + 17 | u8 | 1 if X axis is mirrored, 0 otherwise + 18 | u8 | 1 if Y axis is mirrored, 0 otherwise + 19 | u8 | 0 if finger tracking is supported by hardware, + | | 1 if the driver needs to provide it + 20 | u32le | Number of memory pages that follow (N) + 24 | u16le | Memory page 1: Page address + 26 | u16le | Memory page 1: Effective size in bytes + 28 | u8[128] | Memory page 1: Data (must be 0 padded) + ... + 24+N*132 | u16le | Memory page N: Page address + 26+N*132 | u16le | Memory page N: Effective size in bytes + 28+N*132 | u8[128] | Memory page N: Data (must be 0 padded) + +=head1 AUTHOR + +Gregor Riepl + +=cut + +1; diff --git a/tools/LICENSE b/tools/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/tools/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/tools/SileadTouch.fw b/tools/SileadTouch.fw new file mode 100644 index 0000000..f089f6f --- /dev/null +++ b/tools/SileadTouch.fw @@ -0,0 +1 @@ +ը󅂁𺸸뻿뼤𰹸餸𹰸𹰸길𽹸𻺸𼤸𱸸𼸸𹸾𹸼𹺼𾼤龸鸸츸줸츸𰸼𱸸𱸸𹼸뤸鸸뤸鸸𼸸𹸰𹤧𹸸𹸸𰸸𺺹𺸹𿸾긱𹸸줸𹼹𹱹餸𺹺𺽺𺱺餸𻺻𻾻黱ꤸ𻸺𼸼𾸽鸰ꤸ𹽹깱𺸹뤅𺽺꺱𻸺뤸𻽻𻱻餸뤸줅𻸺𿸾鸱뤸𹻹𹿹鹱뤅𺻺𺿺麱뤸𻻻𻿻黱뤅𻸺𿸾鸱뤸𹻹𹿹鹱뤅𺻺𺿺麱뤸𻻻𻿻黱뤅𻸺𿸾鸱뤸𹻹𹿹鹱뤅𺻺𺿺麱뤸𻻻𻿻黱뤅𻸺𿸾鸱뤸𹻹𹿹鹱뤅𺻺𺿺麱뤸𻻻𻿻黱뤅𻤅𹸹𹸸𺸤𹸤𰤸𼤅𼤸𾸸븤ɨը󅂧᥻أυ+2+2+2𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𾰤𸸸뤸𹸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𹰹𸸤鱽𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤븸𾰤𸸸뤸𸸸𿸤𸸸𿼤𿰤뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸼸鸸𼰤𸸹뤸鸸𽸤𸸸𽼤𸸸𽰤𸼸뤸𸰸𾸤𾼤𹸹𾰤𹼹뤸𹰹𿸤𿼤𸸹𿰤𰸰뤸鱰𸸤𸸸𸼤𸸸𸰤𸸸뤸𰸾𹸤𸸸𹼤𸸸𹰤𸸸뤸𹸾𺸤𹸼𺼤𸸸𺰤𸸸뤸𸸸𻸤𰸰𻼤𰸰𻰤𰸰뤸𰸰𼸤𰸰𼼤𰸰𼰤𰸰뤸𰸰𽸤𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸼸𹸤𸸸𹼤𹼸鹼𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𻸤𻼤𸸸𻰤𸸸뤸𸸸𼸤𰸸𼼤𸸹𼰤𸸸뤸𸼸𽸤𸸸𽼤𸸸𽰤𸸸뤸𹺼𾸤𺸹𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸹸츸𸼤𸻸𸰤𸽹뤸𸿹𹸤𸱹𹼤깿鹾𹰤𸸸뤸𸸸𺸤𸸸𺼤𺰤뤸𻸤𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸾𼰤𸰹뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸹츸𾸤𸸹𾼤𸸹𾰤𸸸鸸뤸𸸸鸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸾𸸤𸼤츹𸰤긹뤸𹸤𹼤𹰤뤸𺸤𺼤𺻰𺰤𺻼뤸𺻸𻸤𻼤𺺰𻰤𺺼뤸𼺸𼸤𸹸𼼤𸱸𼰤𹹹뤸𸺸𽸤𽼤𹺹𽰤𸸸츸뤸𸸸𾸤𸸸𾼤𸼸𾰤븰뤸𸸻𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸼤𸸸𸰤뤸𸸸𹸤𹼤𸸸𹰤뤸𸹸𺸤𺼤𸸸𺰤뤸𸸹𻸤𻼤𸸸𻰤뤸𸸸𼸤𼼤𸸸𼰤뤸𸸸𽸤𽼤𸸸𽰤뤸𸸸𾸤𾼤𸸸𾰤뤸𸸸𿸤𿼤𸸸𿰤뤸𸸸𸸤𸸻𸼤𸸼𸰤𸸾鸸뤸𸸾𹸤𸸾𹼤𸸽𹰤𸸽길뤸𸸽𺸤𸸽𺼤𸸽𺰤𸸽뤸𸸽𻸤𸸼븸𻼤𸸾𻰤𸸽뤸𸸽𼸤𸸾𼼤𸸾𼰤𸻽뤸𸸽𽸤𸸽𽼤𸺽𽰤𸺽뤸𸸹븺𾸤𸸾𾼤𸸾𾰤𸸸뤸𸸼𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸼𸼤𸸻𸰤𸸺뤸𸸹𹸤𸸹𹼤𸸻𹰤𸸼뤸𸸿𺸤𸸿𺼤𸸿𺰤𸸾븸뤸𸸰𻸤𸸾𻼤𸸽츸𻰤𸸾뤸𸸽𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸽𸼤𸸼𸰤𸸾뤸𸸽𹸤𸸾𹼤𸸼븸𹰤𸸽뤸𸸾𺸤𸸽𺼤𸸼𺰤𸸽鸸뤸𸸽𻸤𸸼𻼤𸸻鸸𻰤𸸸뤸𸸹𼸤𸸾鸸𼼤𸸾𼰤𸸾뤸𸸾鸸𽸤𸸿𽼤𸸾𽰤𸸾뤸𸸼츸𾸤𸸽𾼤𸸼𾰤𸸻길뤸𸸺𿸤𸸹븸𿼤𸸹鸸𿰤𸸹뤸𸸻븸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸼤𸸸𸰤𸸸뤸𸸸齰𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸뽸𼰤𸸸콸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸鸰𾰤𸸸뤸𸸸껼𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤𸸸𸰤𸸸뤸𸸸𹸤𸸸𹼤𸸸𹰤𸸸뤸𸸸𺸤𸸸𺼤𸸸𺰤𸸸뤸𸸸𻸤𸸸𻼤𸸸𻰤𸸸뤸𸸸𼸤𸸸𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸콰뤸𸸤𸹸𸼤𸹸𸰤𸹸뤸𺻻𹸤麹𹼤鼹𹰤뤸𺻻𺸤麹𺼤𺽸𺰤鼹뤸𻸤𸹸𻼤𰺹𻰤𰹰뤸𸹸𼸤𸹸𼼤鼹𼰤鸸뤸𸹸𽸤鸹𽼤麹𽰤鼹뤸龹𾸤鰹𾼤鹸𾰤빸뤸𿸤𱸹𿼤𱺹𿰤𱼹뤸𱾹𸸤𱰹𸼤鹸𸰤빸뤸𹸤𰼹𹼤𸹸𹰤𸹸뤸𰺹𺸤𰹱𺼤𰺹𺰤𰹱뤸𰹰𻸤𸹸𻼤𸹸𻰤𸹸뤸빸𼸤빸𼼤𸹸𼰤𸹸뤸𺿸𽸤龹𽼤鸸𽰤𸹸뤸𼸸𾸤𸹸𾼤𸹸𾰤뤸𸹸𿸤𸻹𿼤𰺹𿰤𸻺뤸𰺹𸸤𸼤𼸸𸰤𸹸뤸𼸸𹸤𸹸𹼤𼸸𹰤𸹸뤸𼸸𺸤𸹸𺼤𺰤𰺹뤸𰹱𻸤𸹸𻼤𸹸𻰤𸹸뤸𼸤𸹸𼼤𸻸𼰤𰺹뤸黰𽸤𸻸𽼤𰺹𽰤𰹱뤸𸹸𾸤𸹸𾼤𸹸𾰤뤸𸹸𿸤𸹸𿼤𸹸𿰤𸹸뤸鿰𸸤𸹸𸼤𸹸𸰤𸹸뤸𹸤𸹸𹼤麺𹰤𸺰뤸𸹸𺸤𸹸𺼤𱸰𺰤뤸𸹸𻸤𻼤𸹸𻰤𸹸뤸𸽸𼸤𰼹鸸𼼤鸸𼰤𸹸뤸𽸤𸹸𽼤𽰤꺸뤸𱾹𾸤𾼤븺𾰤𱰹뤸길𿸤켸𿼤鸾𿰤갹뤸𱰸𸸤길𸼤麰𸰤𹾰뤸꾹𹸤鸸𹼤𰻺꾸𹰤꺸뤸꼸𺸤븹𺼤鿸𺰤𹾰뤸𸹸𻸤뺸𻼤鸼𻰤𸼰뤸鿸𼸤꾸𼼤𼰤꼸뤸𹾰𽸤鿸𽼤뺸𽰤뺺뤸갸𾸤鿸𾼤𹾰𾰤꺸뤸뺸𿸤鸼𿼤𿰤갸뤸鿸𸸤𹾰𸼤𸹸𸰤뺺뤸꾸𹸤꼸𹼤鿸𹰤뤸鿸𺸤길𺼤𰺸𺰤뺺뤸켺𻸤𰻺𻼤길𻰤븸뤸鸿𼸤麾𼼤麾𼰤𱰸뤸黻𽸤𽼤켸𽰤뤸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𰻽𸼤𰺸𸰤𰻻뤸鸾𹸤𸺰𹼤𸹸𹰤鸾뤸𸺰𺸤𸹸𺼤鸾𺰤𸺰뤸𸹸𻸤鸾𻼤𸺰𻰤𸹸뤸鸾𼸤𸺰𼼤𸹸𼰤𸿻빰뤸𰾹𽸤𸽹𽼤𰼸𽰤뼺븸뤸𸿻븸𾸤𰾹𾼤𰼹𾰤뼺븸뤸𸽸𿸤𸹸𿼤𸹸𿰤𰼰뤸𸸤𸹸𸼤𸹸𸰤𸿻븸뤸𰾹𹸤𰼹𹼤뼺븸𹰤𸹸뤸𸹸𺸤뼼𺼤밸𺰤𸹸뤸鿽𻸤鱺𻼤鿻𻰤龹븹뤸龸𼸤𰹱𼼤𸹸𼰤𸹸뤸𽸤鸸𽼤鸸𽰤鸹뤸鸹𾸤鸺𾼤鸺𾰤鸻뤸鸻𿸤𿼤𰹱븸𿰤𸹸뤸𸹸𸸤뼼𸼤밸𸰤𸹸뤸鿽𹸤鱻𹼤鿺𹰤龹븹뤸龸𺸤𰹱𺼤𸹸𺰤𸹸뤸𻸤𻼤鸸𻰤鸸뤸鸹𼸤鸹𼼤鸺𼰤鸺뤸鸻𽸤鸻𽼤𽰤뤸𰹱븸𾸤𸹸𾼤𸹸𾰤뼼뤸밸𿸤𸹸𿼤𸹸𿰤𰺹뤸𺿻𸸤龹𸼤뺺븸𸰤𸹸뤸𸻻𹸤𰺹𹼤龹𹰤뤸𸹸𺸤𸹸𺼤𸹸𺰤龹뤸𰻼𻸤𰺹𻼤𰹰𻰤𸹸뤸𼸸𼸤𸹸𼼤𸹸𼰤𸹸뤸鿽𽸤鱻𽼤鿺𽰤龹븹뤸龸𾸤𰹱𾼤𸹸𾰤뤸鸸𿸤鸸𿼤鸹𿰤鸹뤸鸺𸸤鸺𸼤鸻𸰤鸻뤸𹸤𰹱븸𹼤𸹸𹰤龹뤸𰻼𺸤𰺺𺼤𰹰𺰤𸹸뤸𸻻𻸤𰺹𻼤龹𻰤뤸𸹸𼸤𸹸𼼤𸹸𼰤뼼뤸밸𽸤𸹸𽼤𰺹𽰤𺿻뤸龹𾸤뺺븸𾼤𸹸𾰤뼼뤸밸𿸤𸹸𿼤뼰𿰤鸸뤸𸹸𸸤빼𸼤𰺹𸰤뺹뤸𰺸𹸤𰺸𹼤𰻺𹰤鹻뤸𺸤츸𺼤𱼹𺰤𱾹뤸𰻺𻸤캸𻼤𱰹𻰤𰻺꺸뤸鸸𼸤鸺𼼤𱰸𼰤麺뤸黺𽸤𽼤𱼸鸸𽰤𱾸뤸𾸤𾼤𰻺𾰤뤸𸹸𿸤𰺸𿼤𰺸𿰤껺뤸𰺸𸸤𰺸𸼤𰻺𸰤𱺸龸뤸𱻺龸𹸤츸𹼤𱹻𹰤뤸𱸸麸𺸤鸺𺼤鸻𺰤𱿻뤸鸻𻸤鸻𻼤𱺸龸𻰤꾸뤸𱻺龸𼸤𰺹𼼤참𼰤𰻺뤸𰺺길𽸤𱽺鰸𽼤𰺹𽰤뺺뤸𱹺麸𾸤鸺𾼤𱿺𾰤뤸뺺𿸤鹸𿼤𰺹𿰤麻뤸𰺺𸸤꾸𸼤麺𸰤𹼰뤸𱱺𹸤𸻻뺸𹼤𰺹𹰤뺸뤸𹸰𺸤𰻻𺼤𸻻뺸𺰤𰺹뤸뺸𻸤𰻻𻼤𻰤𱸸뤸𼸤鹺𼼤鹼𼰤쾹뤸뺸𽸤긺븸𽼤𰺽꼸𽰤꺹뤸𱺰𾸤𸺰𾼤鸸𾰤긹뤸𱰸𿸤𰺸𿼤뺹𿰤뺺뤸뺸𸸤鸻𸼤기𸰤뤸𱰸𹸤𹼤𱸸𹰤鹼뤸쾹𺸤黼𺼤𱺹𺰤𹰰뤸긹𻸤𰻺꾸𻼤𰺸𻰤𱰸뤸뺸𼸤길𼼤𱺸𼰤龸뤸𽸤𱰸𽼤긺븸𽰤길뤸𰹰𾸤𸹸𾼤𸹸𾰤𸹸뤸긿𿸤𿼤𿰤𸻻뺸뤸𱾹𸸤𱰹𸼤𰻺꺸𸰤鸻뤸鹻𹸤𱰸𹼤黺𹰤뤸麸𺸤𺼤𸹸𺰤뤸뺸𻸤𰻻𻼤龸𻰤鰸뤸𱸹𼸤𼼤𸹸𼰤𹸰뤸길𽸤𽼤𱸺𽰤𱸸뤸길𾸤𾼤𾰤뤸鰹𿸤뺸𿼤齸𿰤鰸뤸𸸤鼹𸼤뺸𸰤鼰뤸鰸𹸤鰸𹼤𹰤𱸹뤸鹸𺸤𱸹𺼤𺰤𱺹뤸龺𻸤𹺰𻼤鸹𻰤𹸰뤸鸹𼸤龺𼼤𹰰𼰤龺뤸𽸤𸹸𽼤𱼹𽰤𱸹뤸𾸤𱺹𾼤麸𾰤𸼰뤸龹𿸤鹸𿼤麻𿰤𰺹뤸𰻺𸸤鸺븸𸼤龺𸰤𹰰뤸龺𹸤鹸𹼤麻𹰤𰺹뤸𰻺𺸤𹸰𺼤鸹𺰤𹺰뤸𰺹𻸤鼺𻼤𺼰𻰤鸸뤸𸻸𼸤鸸𼼤𰺹𼰤𹸰뤸𽸤鸸𽼤龸𽰤鼺뤸𸼰𾸤𰺹𾼤𰺹𾰤𰸰꼸뤸𸺰𿸤𱺹𿼤𸻸𿰤鸸뤸𰺹𸸤뺸𸼤鸼𸰤𹰰뤸麸𹸤麼𹼤븹𹰤𹼰뤸𰺺븹𺸤𰺺𺼤黼𺰤鸾뤸𱺹𻸤𱼹𻼤𻰤𱸹뤸𼸤鼸鸸𼼤뺸𼰤齸뤸𽸤鼹𽼤𽰤뤸𱰹𾸤𱾹𾼤麺𾰤𹺰뤸𰺹𿸤𰺺븸𿼤𰻺𿰤鸸뤸黿𸸤𸺰𸼤𱰸𸰤뺸뤸黺𹸤𹼤뺺𹰤뤸𸹸𺸤𺼤참𺰤뺸뤸𱰹𻸤鸸𻼤𸻻븸𻰤꼸뤸𹽻빰𼸤𸻺𼼤𰺹𼰤𱾹鸻뤸뺺븸𽸤𸻹𽼤찺𽰤黼뤸븺𾸤龹𾼤𹺰𾰤鰹뤸𸻸𿸤鸸𿼤𰺹𿰤꼸뤸참𸸤𸻻𸼤𱰸길𸰤鹻뤸麸𹸤龺𹼤𹾰𹰤꺱뤸븼𺸤뺸𺼤𰺸𺰤깾뤸鸼𻸤𺺰𻼤龹𻰤鸸뤸뺸𼸤黼𼼤鰸𼰤꺱뤸𸻹𽸤鸸𽼤𰺹𽰤黼뤸𸺰𾸤𸻺𾼤𰺹𾰤黼뤸𹺰𿸤꺱𿼤𹹸𿰤𱸹뤸𼸸𸸤𹻸𸼤𸻸𸰤𱾹뤸鰹𹸤𱰹𹼤꺸𹰤𱰸뤸뺸𺸤黺𺼤𺰤뺺뤸꺱𻸤鸸𻼤𰺻𻰤鼹뤸𱸼𼸤𰻻𼼤깾𼰤麹뤸𽸤켸𽼤𽰤𱰹뤸뺸𾸤𱾸齸𾼤𱺹꺽𾰤鸼뤸𸺰𿸤鹰𿼤鸸𿰤𰺾뤸𰸱𸸤𸺰𸼤𸰤뤸鼸𹸤鸸𹼤𰺾𹰤𰸱뤸𻺰𺸤𱰸𺼤𺰤𸺰뤸𰺸𻸤鸾𻼤𺰰𻰤𱰸뤸븺𼸤𱰸𼼤黺𼰤뤸뺸𽸤龺𽼤𸾰𽰤𸻸뤸𰺹𾸤𰺸鰸𾼤𹸰𾰤뺺뤸뺹𿸤𰻺𿼤뺺𿰤뺸뤸쾸𸸤鸸𸼤𱾸𸰤참뤸𱸸𹸤껻𹼤𱼸𹰤꾺뤸𱰸𺸤𰻻𺼤𱰹𺰤𱸹뤸뺸𻸤𰺸븸𻼤鸸𻰤𱼹뤸찺𼸤뺺𼼤麺𼰤𱻻뤸麸𽸤麾𽼤쾺𽰤쾺뤸츺𾸤𹺰𾼤麸𾰤𸻸뤸𰺹𿸤𿼤𰺸鸸𿰤븸뤸𰺹𸸤뺺𸼤𸰤𻺰뤸𸻺𹸤𰺹𹼤鸸𹰤麸뤸𹸰𺸤𰺹𺼤鸸𺰤𰺹뤸黼𻸤𹺰𻼤𸹸𻰤뺸뤸𰸰𼸤𹺰𼼤𰺹𼰤뺺뤸𽸤𱸹𽼤𽰤뤸𸹸𾸤𾼤𾰤뤸𼸸𿸤𱸹𿼤𹽻뺸𿰤뤸뺸𸸤𱰹鸿𸼤뺺𸰤𸻻븸뤸참𹸤𰺹𹼤찺𹰤뺸뤸𱸹鸿𺸤뺺𺼤빼𺰤𸻸뤸鸹𻸤𱺹𻼤麹𻰤鼹뤸龹𼸤𰺹𼼤𹿸𼰤뺺뤸𱾹𽸤鹻𽼤쾺𽰤뤸𸻺𾸤𾼤𰺹𾰤뺺뤸𸻻𿸤𰺹𿼤븺𿰤븺뤸쾺𸸤븸𸼤齺𸰤뺸뤸鸸𹸤쾸𹼤켸𹰤𸺰뤸츸𺸤𰺽𺼤𰺸𺰤𹸰뤸黻𻸤麹𻼤𺹻빼𻰤𱰹뤸캸𼸤껻𼼤𰺽꼸𼰤𱺸鿰뤸𱺹𽸤캺𽼤𰺹𽰤캸뤸𱺸𾸤𺽻뺸𾼤𱺹𾰤캺뤸𱰹鸰𿸤캸𿼤𱺸𿰤𱺹뤸캺𸸤𰺹鸸𸼤켺𸰤鹼鸸뤸𹸤츺𹼤鹼鸿𹰤캸뤸𸻻𺸤𱺺鼸𺼤캺𺰤𸻻뤸鸸𻸤𰺹𻼤麸𻰤𸻸뤸𱾹𼸤𰺹𼼤𱼹𼰤𹱸뤸뺺븸𽸤鸹𽼤찺𽰤鼾뤸𸺰𾸤찺𾼤𱻺뾸𾰤𰺸뤸뾸𿸤𰻺𿼤鸺𿰤𱰹鸰뤸麻𸸤𰺸𸼤𱾹鸰𸰤𰺸뤸𱼹鸰𹸤캺븸𹼤뺺𹰤뺸뤸鸾𺸤𸺰𺼤𹿻븰𺰤뺸뤸鸰𻸤𱰹𻼤뺺𻰤麺븸뤸𼸤𱸹𼼤𼰤𱸹뤸𽸤𰺹𽼤鹻𽰤뺺뤸𸻺𾸤뺺𾼤𾰤뤸𿸤뺸𿼤𰸰𿰤𸺰뤸빰𸸤𰺹𸼤鹻𸰤뺺뤸뺸𹸤𰺸𹼤鸼𹰤𹺰뤸𸻻빰𺸤밾𺼤𸹸𺰤鸸뤸𸻻븼𻸤꾸𻼤𰺹𻰤븺뤸𼸤黼𼼤𰺹𼰤븺뤸𽸤𽼤鹸𽰤𰻺꾸뤸鸻𾸤黾𾼤𾰤븺뤸𿸤𸹸𿼤뺸𿰤鸸뤸𰺽𸸤𰻻𸼤𱾹𸰤븸뤸鰸𹸤𸻸𹼤𱼹𹰤𱰹뤸麾𺸤𸺰𺼤麾𺰤𹺰뤸麾𻸤뺸𻼤鸰𻰤𰻻뤸𰻺𼸤𹸰𼼤껻𼰤𺰰뤸鸺𽸤鸻𽼤𰻻𽰤𰺸뤸꼸𾸤𰹰𾼤𸹸𾰤𸹸뤸𸹸𿸤𰺿𿼤鸻𿰤𰻺뤸𰹰𸸤𸹸𸼤𸹸𸰤𸹸뤸鿻𹸤𰺸𹼤𹸰𹰤뺺뤸𰻻𺸤𰹰𺼤𸹸𺰤𸹸뤸𸹸𻸤𰺿𻼤꼸𻰤𰻺뤸𰹰𼸤𸹸𼼤𸹸𼰤𸹸뤸鿻𽸤𰺸𽼤뺺𽰤뺸뤸鸸𾸤𰺽𾼤𱾸𾰤𰻻뤸븸𿸤𿼤𱰸𿰤뤸𸹸𸸤𱰹𸼤꺸𸰤𱰸뤸뺸𹸤黺𹼤𹰤뺺뤸𺸤𸹸𺼤쾸𺰤참뤸𱹻𻸤𱽻𻼤𱸸𻰤𱼸뤸𸻸𼸤麺𼼤𰺹𼰤𱼸길뤸𱸸븸𽸤𱸺𽼤꼸𽰤𱸽鸸뤸𾸤𱸸𾼤𾰤𰺽뤸𰺸𿸤길𿼤𰻺𿰤鹿뤸鸾𸸤𸼤꺸𸰤뺸뤸𱰺븸𹸤龼𹼤꼸𹰤𹼰뤸𱾹𺸤𱼹𺼤갽𺰤길뤸𰻻𻸤鸿𻼤𰺺𻰤뤸꿻𼸤鸿𼼤龺𼰤𺼰뤸길𽸤뺸𽼤鸼𽰤𰺾뤸𰸰𾸤𺺰𾼤길𾰤뺸뤸龼𿸤𻰰𿼤길𿰤뺸뤸鸼𸸤𸼰𸼤鸼𸰤𹸰뤸긹𹸤𺼰𹼤𱾹𹰤길뤸龸𺸤𺼤鸿𺰤꺸뤸龼𻸤𻼤갸𻰤긹뤸𼸤𼼤뺸𼰤𰺸뤸뺺𽸤븺𽼤븺𽰤鹸뤸𰻺꾸𾸤鸻𾼤븺𾰤黾뤸𿸤븺𿼤𿰤𸹸뤸𸸤𰺸𸼤갸𸰤𰺹뤸鹾𹸤𰸱𹼤龹𹰤𸾰뤸鼹𺸤뺸𺼤龸𺰤𻰰뤸긹𻸤뺸𻼤龼𻰤𻰰뤸긹𼸤𱼸𼼤𱾸𼰤麸뤸𰺸𽸤긹𽼤븺𽰤기뤸𾸤𰺸𾼤뺸𾰤𰸰뤸𸺰𿸤긹𿼤龾𿰤𸺰뤸𰺹𸸤뺸𸼤龸𸰤𸺰뤸𰺹𹸤뺸𹼤龼𹰤𹺰뤸鿸𺸤𰺹𺼤뺺𺰤鿸뤸𹼰𻸤꺹𻼤𰺸𻰤鸺븸뤸鸿𼸤𰺸𼼤𰺺𼰤길뤸鸹𽸤𱰺𽼤𽰤길뤸𰺸𾸤𰻺𾼤鸾𾰤꼸뤸꾸𿸤𱸹𿼤𱻺鸸𿰤뤸걺𸸤鸿𸼤𸰤𰻻뤸𰻻𹸤鸿𹼤뺸𹰤𰺺뤸𺸤𺼤鸼𺰤𸼰뤸갸𻸤뺸𻼤𰺹𻰤뺺뤸𼸤𼼤걺𼰤길뤸꾸𽸤龸𽼤𽰤꼸鸸뤸꺸𾸤鸻𾼤龼𾰤뤸𱰸𿸤뺸𿼤𰸰𿰤𸺰뤸鸿𸸤뺸𸼤𰸰𸰤𸺰뤸𰸰𹸤𰸰𹼤𹺰𹰤긹뤸鸿𺸤𰸰𺼤𸺰𺰤뺸뤸𰸰𻸤𸺰𻼤𰸰𻰤뺸뤸𰸰𼸤𻺰𼼤긹𼰤𰸰뤸𸺰𽸤뺸𽼤뺸𽰤𰸰뤸𸺰𾸤뺸𾼤𹸰𾰤긹뤸𰸰𿸤𸺰𿼤긹𿰤𰸰뤸𸺰𸸤𰸰𸼤𹺰𸰤긹뤸긹𹸤𹼤𹰤뤸깺𺸤𺼤𺰤깻뤸길𻸤꾸𻼤鸿𻰤𸻸뤸𰺹𼸤𼼤鸿𼰤뺸뤸𽸤𰻻𽼤𰻻𽰤鸿뤸𾸤걻𾼤뺸𾰤𱸹뤸𱼹𿸤龸𿼤𰸰𿰤길뤸𸺰𸸤鸻𸼤뺸𸰤𰸰뤸𻺰𹸤길𹼤뺸𹰤鸾뤸𺺰𺸤鸻𺼤뺸𺰤龸뤸𺰰𻸤鸻𻼤𹸰𻰤길뤸뺸𼸤𰻻𼼤𰺸𼰤鸸뤸鸾𽸤鸻𽼤𰻻𽰤𰸱뤸𹺰𾸤길𾼤龺𾰤𸾰뤸鸸𿸤뺸𿼤𰺸𿰤黼뤸𹰰𸸤鸸𸼤뺸𸰤𰺸뤸龸𹸤𹰰𹼤麹𹰤𺽸뤸𱰹𺸤鰹麸𺼤𱾹麸𺰤鸸뤸𻸤𹺰𻼤꺸𻰤뤸꺹𼸤𰺺𼼤麻븸𼰤𰺽뤸𰺸𽸤𰻺𽼤鸸𽰤뺸뤸𾸤𰻻𾼤𰻻𾰤𱺽뤸鸿𿸤𿼤꼽𿰤꾸뤸𸸤𰺸븸𸼤갸𸰤𰻺뤸꿺𹸤꼸𹼤꺸𹰤鸾븸뤸꼸𺸤꺽𺼤鿼𺰤𹼰뤸𰻺𻸤鸸𻼤𺺰𻰤𰺸뤸꼸𼸤꼸𼼤𰺸𼰤꿺뤸뺸𽸤鸼𽼤𹼰𽰤𱰸뤸뺸븹𾸤鸼𾼤𻾰𾰤麹뤸黺𿸤𿼤𱾹麸𿰤鼾뤸𸸤鸻𸼤鸸𸰤𹺰뤸긺𹸤긺𹼤𹰤뤸𱼹𺸤뺸𺼤麰𺰤𱾹뤸鰸𻸤𻼤뺸𻰤𱾸뤸鸾𼸤𸺰𼼤𱱺鸸𼰤뺺뤸뺸𽸤𱼸鸸𽼤뺺𽰤뺸뤸𾸤븸𾼤𾰤켺뤸켸𿸤𸻸𿼤𱰸𿰤𰺹뤸鹻𸸤뺸𸼤뺽𸰤鸼뤸𸺰𹸤𸻸𹼤𹰤𸼰뤸𰺹𺸤鸺𺼤𰻺𺰤븸뤸𻼰𻸤𱿻븸𻼤𹸰𻰤𱾹뤸𹾰𼸤𸻸𼼤鸺𼰤𰺹뤸𰻺𽸤븸𽼤𻾰𽰤𱾹뤸𱿻븸𾸤𸻸𾼤𱺹𾰤𰺸뤸뺹𿸤𱾸븸𿼤𰸰鸸𿰤𸺰뤸鸹𸸤껻𸼤鸺𸰤꾸뤸꾸𹸤참𹼤𸻻𹰤𱰸길뤸𸻸𺸤𰺹𺼤𰺸븸𺰤𱰸뤸𹸰𻸤찺𻼤껻𻰤鸺뤸꾸𼸤꾸𼼤𸻸𼰤참뤸𰺹𽸤𱰸길𽼤𰻺𽰤𰺸뤸뺺𾸤뺸𾼤鸸𾰤𰺸뤸𿸤뺺𿼤𿰤𰻻뤸츸𸸤𰺺𸼤麺𸰤𸺰뤸껸𹸤𸻻븸𹼤鸹𹰤뺸뤸鸸𺸤𰺼𺼤𰸰𺰤뺸뤸𸺰𻸤긹𻼤鸸𻰤𰺾뤸齾𼸤뺺𼼤뺸𼰤𹸰뤸뺺𽸤𸻻븸𽼤𰺹𽰤뤸𾸤𾼤𾰤齼뤸𸹸𿸤𸻻븼𿼤𿰤𰺹뤸鼺𸸤𸰰𸼤븺𸰤븺뤸麹𹸤𰻺뾸𹼤뺸𹰤鸾뤸𸺰𺸤麸𺼤븼𺰤𸹸뤸뺸𻸤鸾𻼤𹺰𻰤鼾뤸𼸤𰻺뾸𼼤𹸰𼰤뺸뤸鼺𽸤𹺰𽼤鼺𽰤𹱹뤸鹻𾸤뺸𾼤鸼𾰤𹺰뤸鹻𿸤뺸𿼤鸼𿰤𺺰뤸뺸𸸤𼸸𸼤𸹸𸰤뺸뤸븼𹸤𸹸𹼤뾻𹰤𱸹뤸뽸𺸤𱸹𺼤𹸰𺰤뺸뤸𹰰𻸤鼺𻼤𰸰뺸𻰤𻺰뤸뺸𼸤𱸸𼼤𼰤𱹻뤸𽸤𸹸𽼤𹸰𽰤뺸뤸𹰰𾸤鼺𾼤𸻻빰𾰤鸸뤸𰺹𿸤麸𿼤𸻻뺸𿰤𰺹뤸鸸𸸤麸𸼤뻾𸰤𱸹뤸뺸𹸤뺺𹼤𹸰𹰤뺸뤸𹰰𺸤鼺𺼤𱸹𺰤𱺹뤸뺸𻸤븼𻼤𱼹𻰤𹹸뤸찾𼸤𱸹𼼤𹸰𼰤뺸뤸𻰰𽸤뺸𽼤𽰤𺻸뤸𱺹𾸤뺸𾼤븼𾰤𱼸뤸鼺𿸤𻺰𿼤뺸𿰤𱸹뤸𸸤𱺹𸼤뺸𸰤鸾뤸𺺰𹸤뺸𹼤븼𹰤𸹸뤸뺸𺸤鼸𺼤𹺰𺰤𸻹뤸𰺹𻸤鼸𻼤𻰰𻰤𺹸뤸鸸𼸤𸻻빰𼼤𰺹𼰤뤸𽸤𽼤𽰤뤸𸹸𾸤𾼤𾰤龾뤸𸺰𿸤긹𿼤𸻹𿰤꼹뤸𰺹𸸤꺰𸼤龺𸰤꾸뤸𹺰𹸤갹𹼤뺸𹰤𰻻뤸𰺸𺸤뺺𺼤龺𺰤𸰰뤸뺸𻸤鸻븹𻼤껿𻰤𹸰뤸𼸤鸻븹𼼤𰺸𼰤뺺뤸𽸤𽼤𰺹𽰤뤸𾸤𸻹𾼤鸸𾰤𰺹뤸黼𿸤𱼹𿼤𹺰𿰤𱾹뤸𸻻빰𸸤𰺹𸼤𹸰𸰤麸뤸𹸤𻺰𹼤뺸븸𹰤뤸𱾹𺸤𱾸𺼤𺰤뤸𱼸𻸤𱾹츸𻼤캸𻰤𸻸뤸븸𼸤鰸𼼤𱸹𼰤참븸뤸𱾸𽸤븸𽼤鼸𽰤麸뤸𰺾𾸤𰸰꼸𾼤𾰤𱼸뤸뺸𿸤𱼺𿼤𸻹𿰤𰺹뤸麰𸸤𸻻빰𸼤𰺹𸰤𸺰뤸켺𹸤𸻸𹼤븾𹰤𱸹뤸𸹸𺸤𺼤𸹸𺰤뤸𻸤𸻸𻼤긹𻰤鹸뤸꾹𼸤𰻺𼼤꾸𼰤뤸𽸤븺𽼤꾹𽰤뺸뤸븸𾸤鰸𾼤𸻸𾰤꺹뤸꼹𿸤뺸𿼤龰𿰤鰸뤸𰻺𸸤갸𸼤뺸𸰤뤸𰺽𹸤𰺸𹼤𰺸𹰤鹾뤸뺹븸𺸤𰺺𺼤뺺𺰤꼸鸸뤸뺸𻸤龰𻼤𻰤갸뤸꾸𼸤뺸𼼤븸𼰤뤸꼹𽸤𽼤𽰤뤸𹹸𾸤뺸𾼤븼𾰤𱸹뤸뺸𿸤鸸𿼤𹹸𿰤𱰸뤸𰸰𸸤𸺰𸼤麸𸰤뺸뤸鸸𹸤鸻𹼤뺸𹰤꺸뤸鸻𺸤𰺹𺼤𰺺𺰤뤸𱿻꾸𻸤𰹰𻼤𸹸𻰤𸹸뤸𸹸𼸤꺿꼸𼼤찺𼰤뺸뤸븼𽸤𸹸𽼤𽰤뺸뤸븼𾸤𹹸𾼤龼𾰤龸뤸뺸𿸤龼𿼤𹹸𿰤𰺾뤸𰸱𸸤𸺰𸼤𱸹𸰤龿뤸𸹸𹸤𹼤𸹸𹰤𰺹뤸𹸰𺸤뺺𺼤븺𺰤𻹸뤸뺸𻸤긹𻼤鸾𻰤𹺰뤸𻻸𼸤𸻹𼼤𰺹𼰤뺺뤸븺𽸤븺𽼤𽰤뤸𸹸𾸤𾼤𾰤븺뤸𿸤𸹸𿼤𿰤뺸뤸鸾𸸤𸺰𸼤𸹸𸰤뺸뤸鸾𹸤𹺰𹼤𹹸𹰤뤸𸹸𺸤뺸𺼤鸸𺰤𰺸뤸鸻𻸤뺺𻼤黻𻰤麸뤸𹻸𼸤뺸𼼤븼𼰤켸뤸𸹸𽸤𽼤𽰤뤸뺸𾸤鸾𾼤𸺰𾰤𸻸뤸鸸𿸤𰺹𿼤꼸𿰤黾뤸𹺰𸸤𹹸𸼤뺸𸰤鸾뤸𹺰𹸤𱸹𹼤뿸𹰤𸹸뤸鸸𺸤뺸𺼤𰺸𺰤鸻뤸뺺𻸤鹼𻼤麸𻰤𹻸뤸𱺹𼸤뺸𼼤븼𼰤켸뤸𸹸𽸤𽼤𽰤뤸뺸𾸤鸾𾼤𸺰𾰤𹹸뤸참𿸤𰻻𿼤𰸰𿰤𺺰뤸뺸𸸤뺸𸼤鸾𸰤𻺰뤸뺸𹸤뺸𹼤鸾𹰤𻺰뤸뺸𺸤𹹸𺼤츺𺰤븺뤸𹸰𻸤캸𻼤鸾𻰤𹺰뤸𰺹𼸤鸸𼼤뺸𼰤鸼뤸鰸𽸤𰸰꺼𽼤𰺹𽰤麸뤸뺺𾸤𹸰𾼤븺𾰤𹺰뤸𸻸𿸤𸻸𿼤𰺹𿰤뺺뤸캸𸸤𹸰𸼤츸𸰤𹸰뤸뺺𹸤뻱𹼤𸹸𹰤𹻸뤸뺸𺸤𱺹𺼤븼𺰤츸뤸뺸𻸤𰺸𻼤鸰𻰤黾뤸𹺰𼸤뺺𼼤뺸𼰤鸾뤸𻺰𽸤뺺𽼤𰺹𽰤뺺뤸뺸𾸤鸾𾼤𻺰𾰤뺸뤸鸸𿸤𰻻𿼤𰸰𿰤𺺰뤸𸻸𸸤뺸𸼤길𸰤𹸰뤸𰺹𹸤𰺺꼸𹼤뺺𹰤뤸𺸤𹽸𺼤참𺰤𰺹黸뤸길𻸤𰸰𻼤𸺰𻰤𱸹뤸뺸𼸤𰺹𼼤뺺𼰤븸뤸뺸𽸤𱾸길𽼤鸾𽰤븺뤸𸰰𾸤𸻻𾼤길𾰤𸻹뤸븸𿸤𹺰𿼤𱼹𿰤뺸뤸𰺸𸸤𰺹𸼤뺺𸰤𸻸뤸븾𹸤𸹸𹼤𸹸𹰤鸸뤸뺸𺸤𰺽𺼤𰻻𺰤鹸뤸黼𻸤鰸𻼤𸻹𻰤𱾹뤸𱰸𼸤麾𼼤𸼰𼰤꾸뤸뺸𽸤𰻻𽼤𹸰𽰤𰺸뤸뺸𾸤𰺽𾼤뺺𾰤鸸뤸뺸𿸤𰺽𿼤𰻻𿰤黸뤸𸸤鹸𸼤𸰤𸹸뤸𹸤𹼤𹰤𸺰뤸𸹸𺸤뺸𺼤鸸𺰤𱰸뤸뺸𻸤黸𻼤𹺰𻰤𸹸뤸鸸𼸤뺸𼼤𰺸𼰤鸼뤸𸺰𽸤黾𽼤𹺰𽰤𸹸뤸𾸤𰸰뾸𾼤𾰤𸺰뤸𱾹𿸤𿼤𹻸𿰤𱼹뤸麰𸸤𹼰𸼤鸹𸰤𰻺뤸𱰸𹸤빺𹼤鹺𹰤鰹뤸츸𺸤鸻𺼤黼𺰤𺾰뤸𱼸鸸𻸤鸸𻼤𺺰𻰤뺸뤸뺸𼸤黼𼼤𺼰𼰤𱼸鸸뤸뺸𽸤麰𽼤𺺰𽰤鸸뤸뺸𾸤黼𾼤𺾰𾰤𱼸鸸뤸鸸𿸤𱼸鸸𿼤麰𿰤뤸𱰸𸸤鼸𸼤𻼰𸰤뤸𱾸𹸤𰺸뾸𹼤븸𹰤뤸𱼹𺸤𱾹𺼤뺸𺰤鸾뤸𺺰𻸤𱾸𻼤븸𻰤𻼰뤸뺸𼸤𱾸𼼤𼰤뤸뺸𽸤𻸰𽼤鸸𽰤𰺽뤸𰻻𾸤뺺𾼤𾰤鼺뤸𸺰𿸤𸹸𿼤鸸𿰤𰺸뤸鸾𸸤𹺰𸼤뺺𸰤𰺸뤸𹸰𹸤뺺𹼤𰺹𹰤뺺뤸츸𺸤𺼤캸𺰤뺸뤸𰺸𻸤뺺𻼤鸸𻰤뺸뤸黼𼸤𹰰𼼤𰺸𼰤뺺뤸𽸤𽼤𽰤뺸뤸鸾𾸤𹺰𾼤𸹸𾰤뺸뤸𰺸𿸤鸸𿼤鸼𿰤鰸뤸뺺𸸤𸼤鿺𸰤𸺰뤸븺𹸤뺸𹼤鸸𹰤꾽뤸𰻺𺸤𺼤껻𺰤븹뤸꼹𻸤鰸𻼤鹸𻰤𻹸뤸𰺸𼸤뺹𼼤龼𼰤꼼뤸鸿𽸤鿼𽼤𽰤𰺸뤸껿𾸤龰𾼤𹼰𾰤갹뤸갹𿸤븹𿼤𹼰𿰤𰺹뤸𰺹𸸤𰸱𸼤𸺰𸰤𸻻빰뤸길𹸤𰺹𹼤麸𹰤뤸𺸤𺼤뺸𺰤𰻻뤸𰸰𻸤𹺰𻼤𸹸𻰤鸸뤸뺸𼸤鿼𼼤𹰰𼰤𸹸뤸뺸𽸤𰻻𽼤𰺸𽰤鸸뤸龸𾸤𱼸𾼤뺽麹𾰤鸾뤸𸺰𿸤𰺸𿼤갹𿰤븺뤸갰𸸤𸼤𰺸𸰤긹뤸뺸𹸤龸𹼤𹰰𹰤꼹뤸𱾹𺸤꼹𺼤뺸𺰤龰뤸𹰰𻸤𸻸𻼤𻰤𰺹뤸鸿𼸤꺸𼼤齺麹𼰤뺸뤸鸼𽸤𻾰𽼤꼸鸸𽰤𰻺鸹뤸𾸤𰺸𾼤𾰤갹뤸𱰹𿸤꾸𿼤𿰤뺸뤸龰𸸤𹺰𸼤갸𸰤뺸뤸龸𹸤𻺰𹼤뺹𹰤찺븸뤸뺹𺸤鸾𺼤𻰰𺰤꼸鸸뤸뺸𻸤𰺸𻼤𹸰𻰤뺺뤸뺹𼸤鸾𼼤𹺰𼰤鿺뤸찺븸𽸤𹸰𽼤𽰤뤸꾸𾸤꼸鸸𾼤뺸𾰤龰뤸𿸤꺸𿼤길𿰤뺸뤸龸𸸤𸼤𱾸𸰤꼹뤸갹𹸤꾸𹼤𹰤𰺸뤸뺸𺸤鸾𺼤𻺰𺰤鹿뤸𹸰𻸤븺𻼤뺸꾻𻰤鿼뤸꼾𼸤갸𼼤鿺𼰤뤸𽸤뺸꾻𽼤龰𽰤𸰰뤸길𾸤뺸𾼤𰺹𾰤뺺뤸𿸤𿼤𿰤길뤸뺸𸸤鹻𸼤𸰤龹뤸鸸𹸤븸𹼤𹰰𹰤黻뤸鼹𺸤빸𺼤鹸𺰤鰹뤸鼾𻸤𸺰𻼤鸹𻰤𸻸뤸𱾹𼸤𱺹𼼤𱰸𼰤𰺸뤸鸰𽸤𰺸𽼤黾𽰤𸺰뤸𰻺𾸤뺸𾼤뺺𾰤𱺸뤸麾𿸤𿼤𱰸𿰤뤸𱸸𸸤븹𸼤𹼰𸰤𱺹뤸𰻺𹸤𰺸𹼤鸸𹰤뺸뤸𱺸𺸤鸸𺼤麼𺰤뤸鸻𻸤𰺺𻼤𰺸𻰤뺸뤸𰹰𼸤𸹸𼼤𸹸𼰤𸹸뤸鸿븸𽸤뺽𽼤鼸𽰤𺾰뤸鸹𾸤𸻸𾼤𱼹𾰤𱺹뤸𰺸𿸤鸰𿼤𰺸𿰤𱱺뤸黾𸸤𸺰𸼤𱾹𸰤鼺뤸𺼰𹸤뺸븸𹼤뺸𹰤鸼뤸𹾰𺸤𱰹𺼤鸾𺰤𺼰뤸𱰹𻸤𹸰𻼤𰺸𻰤뺸븸뤸𱰺𼸤𰺸𼼤꺰𼰤뺸뤸𰻻𽸤𰸰𽼤𸺰𽰤𱺸뤸뺸𾸤𰺽길𾼤𱱻𾰤麾뤸𿸤찺𿼤븽鸸𿰤鰸뤸鸸𸸤𸼤鸽𸰤龸뤸뺸𹸤븸𹼤𹰤鼸鸹뤸𺸤𺼤𺰤뺸뤸鸾𻸤𸺰𻼤𸹸𻰤뺸뤸鸸𼸤뺸𼼤鼸𼰤𹼰뤸麽뺸𽸤鼹𽼤𱰹𽰤뺸뤸黸𾸤𹼰𾼤𸻸𾰤𰺹뤸𰺸𿸤鸸𿼤𱾸𿰤뺸뤸뺺븸𸸤𱰸𸼤뺸𸰤黸뤸鸻𹸤𹼤𱾸𹰤𱸸뤸𺸤캸𺼤뺸𺰤𰻺뤸𰺸𻸤쾸𻼤𻰤𺾰뤸鸸𼸤𱰹𼼤뺸𼰤黸뤸𹼰𽸤𸻸𽼤𱼹𽰤鸼뤸뺸𾸤𰺺𾼤뺺𾰤𱰸뤸뺸𿸤黸𿼤𿰤鸻뤸鸸𸸤뺸𸼤鼸𸰤鼸鸾뤸𹸤麸𹼤𹰤뤸𺸤𺼤鼾𺰤𸺰뤸𸹸𻸤뺸𻼤鼼𻰤𹾰뤸鸹𼸤뺸𼼤鼸𼰤𹼰뤸𽸤𱾹𽼤뺸𽰤븸뤸𹼰𾸤𸻸𾼤뺸𾰤𰺹뤸鸻𿸤鸻𿼤𱰸𿰤뺸뤸뺺𸸤𱾸𸼤뺸𸰤븸뤸鸻𹸤𹼤𱰸𹰤𱸸뤸𺸤캸𺼤𱾹𺰤鼰뤸𹼰𻸤𱼹𻼤𰻺鸸𻰤𰺸뤸鸸𼸤뺸𼼤𱾸𼰤𱼸뤸븹𽸤𽼤鸻𽰤𰺺뤸𰺸𾸤鸹𾼤𰹰𾰤𸹸뤸𸹸𿸤𸹸𿼤𱼿鰸𿰤뺽뤸麰𸸤𺾰𸼤𱼹𸰤𱾹뤸뺸𹸤븸𹼤𹼰𹰤𰻺뺸뤸𹹸𺸤𱰸𺼤𱺹𺰤鸸뤸𸼰𻸤鹺𻼤뺸𻰤鸼뤸𻾰𼸤뺸𼼤鸾𼰤𻼰뤸븺𽸤𹸰𽼤뺸𽰤뺸뤸𰺺𾸤뺺𾼤뺸𾰤𰻻뤸𰸰𿸤𸺰𿼤𱾸𿰤뺺뤸뺸𸸤𰺽𸼤껰𸰤껻뤸𰺸𹸤𰻻𹼤뺺𹰤뺸뤸븸𺸤𺼤𱰸𺰤鸸뤸뺸𻸤鼸𻼤𻰤𱾹뤸𼸤𼼤𼰤齸뤸鿾𽸤𸺰𽼤긹𽰤뺸뤸龸𾸤𹼰𾼤𹱸𾰤𰺹뤸鹸𿸤𿼤鸰𿰤鿾뤸꺹𸸤𸺰𸼤𰺹𸰤갹뤸𹸤鸻𹼤𹰤븹뤸𸾰𺸤鸿𺼤꺸𺰤𰺸뤸갰𻸤𻼤𻰤鸾뤸𺺰𼸤길𼼤𱿻𼰤𰹰뤸𸹸𽸤𸹸𽼤𸹸𽰤𰺿뤸𰺽𾸤껰𾼤껿𾰤𰺸뤸갹𿸤鸰𿼤鿸𿰤𹼰뤸껻𸸤𰻺𸼤鸸𸰤꾹뤸뺸𹸤𰺺𹼤뺺𹰤갸뤸뺸𺸤鿸𺼤𺰤鸿뤸길𻸤뺸𻼤龸𻰤뤸𼸤𼼤𼰤뤸참𽸤黺𽼤𸺰𽰤꺹뤸뺸𾸤龼𾼤𹼰𾰤𹻸뤸꾹𿸤뺸𿼤븸𿰤𻼰뤸꺸𸸤𹽸𸼤𱸹𸰤𰺽뤸𰺸𹸤걺𹼤𰺹麸𹰤뤸龰𺸤𺼰𺼤꾸𺰤𰺹鹱뤸뺸𻸤龰𻼤𺾰𻰤꾸뤸뺸𼸤龰𼼤𺼰𼰤꾸뤸뺸𽸤𰸰𽼤𸺰𽰤𱾸뤸鸸𾸤𰻻𾼤븸𾰤𺰰뤸𿸤𰺺𿼤꾸𿰤𹸰뤸𸸤𸼤鸸𸰤뺸뤸𹸤鸿𹼤𹰤𰻻뤸𰻻𺸤鸿𺼤뺸𺰤𰺽뤸𻸤鸿𻼤뺸𻰤꼸븸뤸𼸤뺸𼼤龰𼰤𹼰뤸鸿𽸤긹𽼤뺸𽰤𰸰뤸𺺰𾸤뺸𾼤鸸𾰤𰺸뤸𰻻𿸤龰𿼤𹰰𿰤뤸𻺰𸸤뺸𸼤𰻻𸰤龰뤸𹰰𹸤꾹𹼤뺸𹰤龰뤸𹰰𺸤𰺺𺼤𺰤𹺰뤸꾸𻸤꾹𻼤갽𻰤鸿뤸𼸤뺸𼼤𰺺𼰤뺺뤸鸸𽸤븹𽼤𺼰𽰤꼸鸸뤸뺸𾸤𰸰𾼤𸺰𾰤𰺹뤸𰺸𿸤븸𿼤𻺰𿰤𰺹뤸뺸𸸤𰺸𸼤麸𸰤뺸뤸꼸𹸤𹼤𰻻𹰤𰻻뤸갸𺸤鸿𺼤걺𺰤뺸뤸𻸤𰺺𻼤뺺𻰤꼸鸸뤸뺸𼸤龰𼼤𼰤뺸뤸꾹𽸤꾸𽼤뺸𽰤븸뤸𾸤𰺽𾼤꺸𾰤뺸뤸龼𿸤𿼤꾹𿰤뤸𸸤뺸𸼤鸸𸰤𰺸뤸참𹸤꼸𹼤𱰸𹰤𰹰뤸𸹸𺸤𸹸𺼤𸹸𺰤鿻뤸麸𻸤𱾹𻼤𰻺𻰤참뤸鹸𼸤꼸𼼤껻𼰤𱾸뤸𽸤𽼤麸𽰤뺸뤸鸾𾸤𸺰𾼤𰺹𾰤뺸뤸鸾𿸤𺺰𿼤뺸𿰤𰺹뤸뺺𸸤뺸𸼤鸾𸰤𸺰뤸뺸𹸤껸𹼤𰻻𹰤𰺸뤸뺺𺸤𸻸𺼤븾𺰤𸹸뤸𸹸𻸤𻼤꺹𻰤뺸뤸龼𼸤𹰰𼼤𼰤𸻸뤸갽𽸤길𽼤꾸븹𽰤뤸갸𾸤꼹𾼤𻹸𾰤鸿뤸뺸𿸤鿼𿼤𸼰𿰤꺸뤸뺸𸸤鿼𸼤𺰰𸰤뺸뤸뺸𹸤꺰𹼤𹰤𰺸뤸뺺𺸤뺸𺼤뺺𺰤뺸뤸뺺𻸤븺𻼤뺸𻰤龼뤸꾸븹𼸤𼼤갸𼰤뤸𽸤𽼤뺸𽰤𰸰뤸𹺰𾸤𸹸𾼤뺸𾰤鸾뤸𸺰𿸤鼹𿼤𰺸𿰤뺺뤸뺸𸸤鼰𸼤𹰰𸰤鹸뤸麹𹸤뺸𹼤鼼𹰤𹰰뤸쾸𺸤𸻸𺼤鰸𺰤龸뤸뺸𻸤鸾𻼤𹰰𻰤𸻸뤸𰺹𼸤鸼븸𼼤뺸𼰤黼뤸𸾰𽸤𸻸𽼤𱸹𽰤뤸𱺹𾸤麺𾼤𸺰𾰤𸻸뤸뺸𿸤鸾𿼤𺺰𿰤뺸뤸𱸹𸸤븼𸼤𱺹𸰤뺸뤸鸾𹸤𹺰𹼤𸻸𹰤뺸뤸鸾𺸤𺺰𺼤뺸𺰤𱸹뤸𱺹𻸤븼𻼤켸𻰤뺸뤸鸾𼸤𹺰𼼤𸻸𼰤뺸뤸鸾𽸤𸺰𽼤鸹𽰤𱸹뤸븼𾸤𱺹𾼤𾰤𱸹뤸𱺹𿸤𱼹𿼤𿰤쾸뤸麺𸸤𸺰𸼤𸻸𸰤뺸뤸鸾𹸤𸺰𹼤𱸹𹰤𱺹뤸븼𺸤𱼹𺼤𹸰𺰤𱼹뤸븺𻸤𱼹𻼤𱸹𻰤𱺹뤸𼸤𱾹𼼤麺𼰤𺺰뤸뺸𽸤뺸𽼤鸾𽰤𻺰뤸뺸𾸤뺸𾼤𰺹𾰤뺺뤸뺸𿸤참𿼤뺺𿰤뾸뤸𰻺꺸𸸤鸻𸼤麸𸰤𱰸뤸𹸰𹸤찺𹼤꺰𹰤뤸𰺸𺸤뺺𺼤𸻸𺰤鰸뤸麸𻸤뺸𻼤鼼𻰤뤸龸𼸤鼸鸸𼼤뺸𼰤鼰뤸𽸤鸽𽼤𽰤뤸뺸𾸤鸾𾼤𸺰𾰤𱰹뤸뺸𿸤黸𿼤鰸𿰤꺸뤸뺸𸸤𰻻𸼤𰸰𸰤뤸𱰸𹸤𹼤븺𹰤븺뤸𺸤𸹸𺼤𰺺𺰤齰뤸𰻻꾸𻸤麸𻼤𰻻𻰤𸼰뤸𱸹𼸤𰺸𼼤𱹻𼰤뤸𸹸𽸤𽼤𽰤鹸뤸뺸𾸤鸿𾼤𸺰𾰤龹뤸鰹𿸤𺻸𿼤𰺹𿰤鼹뤸캸븸𸸤켸𸼤𸰤츸븹뤸𰺹𹸤츺븸𹼤𹰤鸸뤸鹺뺸𺸤麹𺼤츸𺰤캸뤸𻸤켸𻼤츺𻰤뺸뤸鸽𼸤𰺸𼼤齼𼰤龸뤸𽸤鰸𽼤龹𽰤뺸뤸븸𾸤𹰰𾼤𺻸𾰤鹺뤸𰺹𿸤鼹𿼤캸𿰤켸뤸𸸤츸𸼤𰺹𸰤츺뤸𹸤鸽뺸𹼤鸸𹰤鹺뺸뤸麹𺸤츸𺼤캸𺰤뤸켸𻸤츺𻼤龸𻰤뺸뤸븸𼸤𼼤𺻸𼰤뤸𽸤𽼤𻿸𽰤鹾뤸긹𾸤鸾𾼤뺸𾰤뤸븸𿸤𰺸𿼤𰺽𿰤𱰹뤸𸸤꼹𸼤𰻻𸰤뺺뤸걺𹸤꾹𹼤鸿𹰤뺸뤸𰺸𺸤𰺽𺼤𰻻𺰤뺺뤸꺹𻸤𻼤갽𻰤鸿뤸뺸𼸤𰺸𼼤鸻븸𼰤𰺽뤸𰻻𽸤뺺𽼤鸾𽰤뺸뤸𾸤鸿𾼤𾰤뤸뺸𿸤𰺸𿼤븸𿰤𰺽뤸𰻻𸸤뺺𸼤𸰤뤸𹸤뺸𹼤븼𹰤츸뤸鸸𺸤𰻺꾸𺼤𰺺𺰤뤸𰺸𻸤𰻻𻼤뺺𻰤𹹸뤸뺸𼸤븼𼼤𱸹𼰤뺸뤸鸰𽸤꼸𽼤뺸𽰤𰺸뤸뺺𾸤鸸𾼤뺸𾰤黼뤸𺰰𿸤뺸𿼤뺸𿰤鸼뤸𸰰𸸤뺸𸼤鼺𸰤𸺰뤸𸹸𹸤𰺸𹼤뺺𹰤뺸뤸鸾𺸤𺾰𺼤븺𺰤𹸰뤸뺸𻸤𰺹𻼤뺺𻰤뺸뤸鸸𼸤𰺾𼼤鸸𼰤참뤸𰻻𽸤𰸰𽼤𸺰𽰤鸸뤸𹸰𾸤鸹𾼤𸻻뺸𾰤𰺹뤸鸸𿸤뺸𿼤黼𿰤𻺰뤸븺𸸤뺸𸼤鸾𸰤𻺰뤸븺𹸤鸸𹼤𸻸𹰤𰸰꼸뤸𻺰𺸤븺𺼤鸸𺰤뺸뤸黼𻸤鰸𻼤뺸𻰤뺸뤸𰻻𼸤𰸰𼼤𹺰𼰤𰸰꺸뤸뺸𽸤鸾𽼤𺺰𽰤뺸뺻뤸𰸰꺸𾸤𺺰𾼤뺸뺻𾰤𰸰꺸뤸𻺰𿸤븺𿼤뺸뺻𿰤鸾뤸𺺰𸸤븺𸼤뺸𸰤𰺸뤸뺺𹸤뺻𹼤鸼𹰤𸾰뤸𸹸𺸤븺𺼤뺸뺻𺰤뺺뤸뺸뺻𻸤뺺𻼤鸹𻰤뺸뤸鼸𼸤鰸𼼤𸹸𼰤뺸뺻뤸뺺𽸤麹𽼤뺸𽰤鼼뤸鰸𾸤鸸𾼤𾰤𱸸뤸𿸤麸𿼤뺸𿰤鼸뤸𸸤뺸뺻𸼤𸰤뤸𹸤참𹼤黺𹰤𺺰뤸븺𺸤鸸𺼤𰻻𺰤𰸰뤸𹺰𻸤𸻸𻼤뺸𻰤鸾뤸𺺰𼸤뺸𼼤𸻸𼰤𰺺꼸뤸뺺𽸤븺𽼤𹸰𽰤븺뤸鸾𾸤𻺰𾼤븺𾰤뺸뤸𰺸𿸤鸼𿼤𸾰𿰤뺺뤸뺸𸸤뺺𸼤뺸𸰤뺺뤸鸹𹸤뺸𹼤鼸𹰤鰸뤸븺𺸤뺸𺼤鸸𺰤꼸뤸뺸뺻𻸤𰺸𻼤뺺𻰤뤸𱸸𼸤𼼤鸸𼰤뤸𽸤𽼤𸻸𽰤𰺹뤸뺺𾸤뺺𾼤鼹𾰤뺸뤸鼰𿸤鰸𿼤麹𿰤𰺸뤸鸼𸸤鹺뾸𸼤鸸𸰤켼뤸𱸹𹸤𹼤캼𹰤麸뤸鼾𺸤𺼤츺𺰤뺸뤸鸾𻸤𸺰𻼤鸿𻰤븼뤸𱸸𼸤鸿𼼤뺸𼰤𰻺뤸꾸𽸤鸻𽼤뺸𽰤𰻺뤸鸻𾸤뺸𾼤鸻𾰤𰻺鸸뤸麸𿸤鼸鸸𿼤뺸𿰤鼰뤸𸸤麹𸼤𸰤뤸𹸤𱸹𹼤뺸𹰤麸뤸鰸𺸤𱺹𺼤麸𺰤뤸뺸𻸤龼𻼤𻰤鹸뤸𹼰𼸤𱰹𼼤𸻸𼰤鸹뤸갽𽸤뺸𽼤𽰤븸뤸𹼰𾸤𰺸𾼤𰻺𾰤꼸뤸𱼸𿸤쾸龿𿼤鸾𿰤𰺸뤸꾹𸸤긽𸼤꼸鸸𸰤鿾뤸𸼰𹸤𰺽𹼤鸻𹰤𱰸뤸븹𺸤븸𺼤𺰤鸾뤸麸𻸤꺸𻼤뺸𻰤龼뤸𼸤갸𼼤𰻺꾸𼰤걺꺸뤸껰𽸤𰹰𽼤𸹸𽰤𸹸뤸𸹸𾸤꾿𾼤鸺𾰤𰻻뤸𰹰𿸤𸹸𿼤𸹸𿰤𸹸뤸갿𸸤껿𸼤𰸰𸰤鸾뤸𸺰𹸤𱰸𹼤뺸𹰤鸾뤸𺺰𺸤鸾𺼤𱰸𺰤黾뤸𺼰𻸤鹸𻼤黺𻰤𺼰뤸𱰹𼸤鸰𼼤𰻺𼰤黼뤸𻾰𽸤鸸𽼤뺸𽰤𰻺뤸黸𾸤𻾰𾼤𱰸𾰤뺸뤸鸾𿸤𺺰𿼤𿰤鿾뤸𻰰𸸤𸼤𰹰𸰤𸹸뤸𸹸𹸤𸹸𹼤븸𹰤𹺰뤸𺸤𹸰𺼤𺰤𻼰뤸𻸤𹸰𻼤𰻺꾸𻰤𰻺꾸뤸𰺸𼸤𼼤鸿𼰤뤸𸻸𽸤갸𽼤鸿𽰤麺뤸𱸸𾸤뺸𾼤麸𾰤뤸𱺸𿸤𿼤𿰤𸹸뤸𸸤참𸼤𰻻𸰤𰸰뤸𹺰𹸤𸹸𹼤뺸𹰤鸾뤸𹺰𺸤𸹸𺼤뺸𺰤鸾뤸𸺰𻸤𸹸𻼤뺸𻰤𰺽뤸鸸𼸤黼𼼤鰸𼰤𸹸뤸쾸𽸤𽼤𹼰𽰤𰺸뤸뺸𾸤鸾𾼤𻺰𾰤븺뤸뺸𿸤鸾𿼤𹺰𿰤𰸰꺸뤸𹸰𸸤븺𸼤𻺰𸰤참뤸𹸤𸾰𹼤𰺸𹰤참뤸𸻸𺸤껻𺼤𰺹𺰤𱰸길뤸黰𻸤麻𻼤븸𻰤𸾰뤸𸻺𼸤𰺸𼼤𹸰𼰤뺺뤸鹸𽸤뺸𽼤鸼𽰤𸺰뤸鸹𾸤麸𾼤븺𾰤𰻺뺸뤸𱺸𿸤뺸𿼤𱸹𿰤鸾뤸𸺰𸸤鸸𸼤𸰤𸹸뤸뺸𹸤鸸𹼤𰺽𹰤꼸뤸𰺸𺸤𰻺𺼤麸𺰤鰸뤸𸹸𻸤鼺𻼤𻰤𰻺뺸뤸𸻸𼸤뺺𼼤鸹𼰤뺸뤸뺸𽸤鸰𽼤𽰤뺺뤸鸸𾸤뺸𾼤뺺𾰤黾뤸𹼰𿸤𱸹𿼤𱸹𿰤𸻸뤸麹𸸤𸼤𸻸𸰤龹뤸𱺸𹸤鸹𹼤鼹𹰤𱿺뺸뤸𰺸븸𺸤鹸𺼤𱰸𺰤켹뤸뺹븸𻸤찹𻼤𰺽𻰤꼸뤸𰺸𼸤鸻𼼤𰹰𼰤𸹸뤸𸹸𽸤𸹸𽼤𰺿𽰤𰹰뤸𸹸𾸤𸹸𾼤𸹸𾰤鿻뤸𰻺𿸤꼸𿼤𰺸𿰤鸸뤸鼺𸸤𸼤뺺븹𸰤캺뤸𹸤𹼤𹰤麹뤸뺸𺸤鼼𺼤鸹𺰤鰸뤸𰻺뺸𻸤𱺸𻼤뺸𻰤鸾뤸𸺰𼸤𱸹𼼤𼰤𸹸뤸𰺹𽸤麸𽼤鰸𽰤𰻺뤸麹𾸤鸸𾼤뺸𾰤뤸鼸𿸤𿼤𿰤뤸𸻸𸸤𰺹𸼤뺺𸰤븺뤸鸹𹸤𰺸𹼤𰺸𹰤캼뤸츼𺸤𱸸𺼤𱺸𺰤𱼹뤸𻸤𱾹𻼤麺𻰤𸺰뤸鸸𼸤𹸰𼼤긹𼰤鼺뤸𽸤𰺸𽼤긹𽰤뤸𾸤𾼤뺹𾰤𰸰뤸𹺰𿸤𸻸𿼤𰺹𿰤뺺뤸븺𸸤鸸𸼤뺸𸰤黼뤸갹𹸤鹸𹼤𹰰𹰤뤸뺸𺸤𰻻𺼤𰸰𺰤𺺰뤸뺸𻸤鹸𻼤뺸𻰤𰸰뤸𻺰𼸤뺸𼼤𸻺𼰤鸸뤸𰺹𽸤黼𽼤𹺰𽰤뺸뤸𰸰𾸤𻺰𾼤뺸𾰤뺸뤸𰸰𿸤𺺰𿼤븸𿰤뺸뤸𰸰𸸤𹺰𸼤갹𸰤뺸뤸츸𹸤븼𹼤𹻸𹰤뺸뤸𰺹𺸤뺺𺼤𹸰𺰤븸뤸𸻸𻸤𰺹𻼤𹸰𻰤뺺뤸𼸤𱸹𼼤鹸𼰤鹺쾸뤸뺸𽸤鸾𽼤𺺰𽰤鸽뤸齾𾸤𹺰𾼤鿾𾰤뺸뤸鸾𿸤𹺰𿼤𺱺𿰤𹸰뤸鰹𸸤𸺰𸼤𱸸𸰤븺뤸𹸰𹸤븺𹼤𹰤𱺹뤸鰹𺸤齺𺼤𹺰𺰤븹뤸뺹𻸤鸾𻼤𺺰𻰤븺뤸뺸𼸤𼼤𰺸𼰤𹸰뤸뺺𽸤뺹𽼤鸾𽰤𸺰뤸齾𾸤뺸𾼤𰺸𾰤뺺뤸뺹𿸤鸾𿼤𻺰𿰤鸽뤸齾𸸤𹺰𸼤길𸰤뺸뤸𰺹𹸤𹸰𹼤뺺𹰤뺸뤸길𺸤𰺹𺼤뺺𺰤𹸰뤸븺𻸤鸸𻼤𰻻𻰤𰸰뤸𼸤鿺𼼤𼰤麹뤸뺸𽸤鼼𽼤鰸𽰤𰻻뤸𰸰𾸤𸺰𾼤뾸𾰤뺸뤸껸𿸤𰺸𿼤𰻻𿰤꾸뤸鼸𸸤龸𸼤𱺹𸰤켹뤸𹸤𱸹𹼤麺𹰤𹺰뤸𰺹𺸤켹𺼤鸸𺰤𺺰뤸뺸𻸤뺸𻼤𱸹𻰤𰸰뤸𸺰𼸤𱺹𼼤𼰤𸹸뤸麺𽸤𺺰𽼤뺸𽰤𰺹뤸𰻺𾸤𹸰𾼤鰺츸𾰤뺸뤸𰺸𿸤鸾𿼤𿰤뺺뤸𸸤麸𸼤齺𸰤𻺰뤸鸽𹸤븺𹼤븺𹰤鸽뤸齾𺸤𺼤鹺쾸𺰤뤸𺺰𻸤븺𻼤뺸𻰤鸾뤸𸺰𼸤鿾𼼤뺸𼰤鸾뤸𹺰𽸤鿾𽼤𸻸𽰤뺺뤸뺸𾸤뺺𾼤𹺰𾰤鹸뤸뺸𿸤齼𿼤鰸𿰤𱾹뤸𱱺쾸𸸤뺸𸼤𰻻𸰤𰸰뤸𻺰𹸤鸽𹼤𰻺븹𹰤𰸰븸뤸𻺰𺸤鸽𺼤麹𺰤뾸뤸뺸𻸤鸾𻼤𹺰𻰤麸뤸뺸𼸤鿺𼼤𸺰𼰤뺺뤸𹸰𽸤뺸𽼤뺸𽰤𹸰뤸뺺𾸤鼾𾼤𾰤뾸뤸鸽𿸤뺸𿼤齼𿰤뤸𱱺쾸𸸤𸼤𸰤뤸𹸤𸹸𹼤뺸𹰤鸾뤸𺺰𺸤뺸𺼤𰺸𺰤鸾뤸𹺰𻸤뺺𻼤뺸𻰤길뤸𰺹𼸤뺺𼼤뺸𼰤鸾뤸𸺰𽸤𸻻빰𽼤븺𽰤鸹뤸𾸤𱸹𾼤𹹸𾰤뤸𱸹𿸤鸰𿼤𿰤𸹸뤸𸸤𱸹𸼤鸸𸰤𰻻뤸𰸰𹸤𻺰𹼤븺𹰤𰻻뤸𰸰𺸤𻺰𺼤뺸𺰤뺸뤸뺺𻸤뺸𻼤뺺𻰤뤸𱸹𼸤𰺹𼼤뺺𼰤뤸𽸤뺸𽼤鸾𽰤𻺰뤸뺸𾸤뺸𾼤뺺𾰤븺뤸뺸𿸤鸾𿼤𻺰𿰤뺹뤸뺸𸸤뺺𸼤븺𸰤뺹뤸𰸰𹸤𸺰𹼤𸹸𹰤뺸뤸鸾𺸤𹰰𺼤𰺹𺰤뺺뤸𻸤𸹸𻼤뺸𻰤𰻻뤸𰸰𼸤𹺰𼼤𱰹𼰤뺸뤸黸𽸤鰸𽼤𸻻빰𽰤𱾹뤸𰻺꺸𾸤鸸𾼤麸𾰤𱰸뤸뺸𿸤黸𿼤𿰤𰻺꺸뤸鸸𸸤𰸰꾸𸼤𻺰𸰤뺸뤸뺸𹸤鹻𹼤𰺹𹰤麸뤸뺺𺸤뺸𺼤鸾𺰤𻺰뤸참𻸤뺸𻼤𰻻𻰤𰸰뤸𺺰𼸤참𼼤뺸𼰤𰺹뤸뺺𽸤참𽼤𰻻𽰤𰸰뤸𹺰𾸤뺸𾼤鸾𾰤𻺰뤸鸸𿸤뺸𿼤鸾𿰤𺺰뤸뺸𸸤鸸𸼤뺸𸰤꾸뤸𰺹𹸤뺺𹼤뺸𹰤鸾뤸𺺰𺸤뺸𺼤뺸𺰤𰸰뤸𸺰𻸤黺𻼤뺸𻰤𰺹뤸뺺𼸤𻾰𼼤뺸𼰤뺸뤸길𽸤𰺹𽼤뺺𽰤뺸뤸鸾𾸤𺺰𾼤鸸𾰤𰺸뤸鸰𿸤黾𿼤𸺰𿰤뺺뤸뺸𸸤길𸼤𰺹𸰤뺺뤸鸸𹸤𸻻빰𹼤麸𹰤뤸𸹸𺸤𺼤참𺰤𰻻뤸𰸰𻸤𺺰𻼤뺹𻰤𸻸뤸𰺺길𼸤𹸰𼼤뺺𼰤鸾뤸𸺰𽸤껻𽼤𰸰꺸𽰤𺺰뤸뺸𾸤껻𾼤𰻻𾰤𰺸뤸꾸𿸤鸼𿼤𺺰𿰤뺸뤸뺸𸸤鸾𸼤𺺰𸰤𰺹뤸𰺹𹸤뺺𹼤𹸰𹰤𱸹뤸鸾𺸤𸺰𺼤𱸹𺰤뤸𰺸𻸤𻼤𸹸𻰤뺸뤸鸸𼸤꾸𼼤𰺸𼰤𰺹뤸뺺𽸤𽼤𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𸸸뤸𸸸𿸤𸸸𿼤𸸸𿰤𸸸뤸𸸸𸸤𸸸𸼤齸𸰤齸뤸𸸸𹸤뼱𹼤𼱼𹰤뤸𺸤𺼤𱺽뾽𺰤갹뤸뼿𻸤밹𻼤鰰𻰤鰾뤸뼸뾼𼸤칻𼼤𸸸𼰤𸸸뤸𸸸𽸤𸸸𽼤𸸸𽰤𸸸뤸𸸸𾸤𸸸𾼤𸸸𾰤𼼾뤸𻹻𿸤𻸻𿼤𸸸𿰤𻹻黼뤸𻼻黸 \ No newline at end of file diff --git a/tools/autoconvert b/tools/autoconvert new file mode 100755 index 0000000..1c14768 --- /dev/null +++ b/tools/autoconvert @@ -0,0 +1,82 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IO::File; +use IO::Dir; +use File::Basename; +use File::Spec::Functions qw(rel2abs catdir catfile); + +our $mydir = dirname(rel2abs(__FILE__)); +our $basedir = catdir($mydir, '..', 'firmware'); +our $fwtool = catfile($mydir, 'fwtool'); + +my $root = IO::Dir->new($basedir) or die("Can't access $basedir: $!"); +for (my $vendor = $root->read(); defined($vendor); $vendor = $root->read()) { + if ($vendor !~ /^(.|..)$/) { + my $vendordir = catdir($basedir, $vendor); + my $devices = IO::Dir->new($vendordir); + if (defined($devices)) { + for (my $device = $devices->read(); defined($device); $device = $devices->read()) { + if ($device !~ /^(.|..)$/) { + my $devicedir = catdir($vendordir, $device); + if (-d $devicedir) { + print("Processing $vendor/$device...\n"); + my $readme = catfile($devicedir, 'README.md'); + my $sileadts = catfile($devicedir, 'silead_ts.fw'); + if (-e $readme) { + my $overwrite; + if (-e $sileadts) { + print("silead_ts.fw found, overwrite? (y/N)"); + my $answer = readline(); + $overwrite = ($answer =~ /^[yY]/); + } else { + $overwrite = 1; + } + if ($overwrite) { + my $firmware = catfile($devicedir, 'firmware.fw'); + my $model = '1680'; + my $width = 4095; + my $height = 4095; + my $points = 10; + my %flags = ( xflip => 0, yflip => 0, swap => 0, track => 0 ); + + my $table = IO::File->new($readme, 'r') or warn("Error opening README.md"); + while (my $line = <$table>) { + if ($line =~ /Touch controller\s*\|[ \ta-zA-Z]*([0-9]{4})/) { + $model = $1; + } elsif ($line =~ /Extracted firmware\s*\|[^(]*\(([a-zA-Z0-9_.]+)\)/) { + $firmware = catfile($devicedir, $1); + } elsif ($line =~ /Touch panel resolution\s*\|[^0-9]*([0-9]+)[ \t\/xX,]+([0-9]+)/) { + $width = $1; + $height = $2; + } elsif ($line =~ /Multitouch support\s*\|[^0-9]*([0-9]+)/) { + $points = $1; + } elsif ($line =~ /Finger tracking\s*\|\W*[Nn]/) { + $flags{track} = 1; + } elsif ($line =~ /Mirrored horizontally\s*\|\W*[Yy]/) { + $flags{xflip} = 1; + } elsif ($line =~ /Mirrored vertically\s*\|\W*[Yy]/) { + $flags{yflip} = 1; + } elsif ($line =~ /Axes swapped\s*\|\W*[Yy]/) { + $flags{swap} = 1; + } + } + + if (-e $firmware) { + my $flagstring = join(',', map({ $flags{$_} ? "$_" : "no$_" } keys(%flags))); + print("Running: fwtool -c $firmware -1 -m $model -w $width -h $height -t $points -f $flagstring $sileadts\n"); + system($fwtool, '-c', $firmware, '-1', '-m', $model, '-w', $width, '-h', $height, '-t', $points, '-f', $flagstring, $sileadts); + } else { + print("Firmware $firmware found.\n"); + } + } + } else { + print("No README.md found.\n"); + } + } + } + } + } + } +} diff --git a/tools/fw_extractor b/tools/fw_extractor new file mode 100755 index 0000000..6e83cba --- /dev/null +++ b/tools/fw_extractor @@ -0,0 +1,36 @@ +#! /usr/bin/python +from subprocess import * +import sys +import os + +if len(sys.argv) != 2: + print "Firware extractor.\n" + print "Requires elf file (driver) argument" + sys.exit(1) + +filename = sys.argv[1] + +p = Popen(['/bin/sh', '-c', 'readelf -S '+ filename + ' | grep \ \.rodata\ | sed \'s/\\[ *//g\''], stdout=PIPE) + +args = p.stdout.readlines() + +if len(args) != 1: + print "No simple .rodata section found" + sys.exit(1) + +rodata = args[0] + +args = rodata.split(']') +args = args[1].split() + +offset = int(args[3], 16) + +print ".rodata offset is ", offset, "\n" + +p = Popen(['/bin/sh', '-c', 'readelf -s '+ filename +' | grep -i fw'], stdout=PIPE) + +for line in p.stdout: + args = line.split() + + print "Found", args[7], "offset", offset + int(args[1],16), "count", args[2] + call(['dd','if='+filename,'bs=1','count='+args[2], 'skip='+str(offset + int(args[1],16)),'of='+args[7] + ".fw"]) diff --git a/tools/fwtool b/tools/fwtool new file mode 100755 index 0000000..29c6df3 --- /dev/null +++ b/tools/fwtool @@ -0,0 +1,143 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IO::File; +use Getopt::Long; +use File::Basename; +use lib dirname (__FILE__); +use Firmware::Silead; + +sub usage() { + print STDERR "Usage: fwtool {-i | -c | -s | -x } [ -1 | -2 | -3 ] [-w ] [-h ] [-t ] [-f ] \n"; + print STDERR "-i Prints statistics and information about new-style firmware.fw\n"; + print STDERR "-c Converts any older firmware format into new-style firmware.fw\n"; + print STDERR "-s Sets parameters and flags\n"; + print STDERR "-x Exports a firmware into plain format, to use with other Linux/Android drivers\n"; + print STDERR " The source firmware format can be specified with these parameters:\n"; + print STDERR "-1 Plain firmware, as used with the Android driver (default)\n"; + print STDERR "-2 Windows GSL_TS_CFG.h firmware\n"; + print STDERR "-3 Scrambled Windows SileadTouch.fw firmware\n"; + print STDERR " For the -c and -s modes, the following parameters may be set:\n"; + print STDERR "-m Sets the controller model (4-byte ASCII string, ex.: 1680)\n"; + print STDERR "-w Sets the width parameter\n"; + print STDERR "-h Sets the height parameter\n"; + print STDERR "-t Sets the number of supported touch points parameter\n"; + print STDERR "-f Sets flags, separated by commas (optional, supported flags: xflip, yflip, swap, track)\n"; + print STDERR " xflip enables horizontal flipping\n"; + print STDERR " yflip enables vertical flipping\n"; + print STDERR " swap enables axis swapping\n"; + print STDERR " track enables in-driver finger tracking (use for controllers that don't support it)\n"; + print STDERR " Each flag may be prefixed with 'no' to disable it.\n"; + -1; +} + +my ($mode, $format, $tscfg, $model, $width, $height, $touches, $flags, $plain) = ('info', 'plain'); +GetOptions( + 'info' => sub { $mode = 'info'; }, + 'convert=s' => sub { $mode = 'convert'; $tscfg = $_[1]; }, + 'set' => sub { $mode = 'set'; }, + 'xport=s' => sub { $mode = 'export'; $plain = $_[1]; }, + 'model=s' => \$model, + 'width=i' => \$width, + 'height=i' => \$height, + 'touches=i' => \$touches, + 'flags=s' => \$flags, + '1' => sub { $format = 'plain' }, + '2' => sub { $format = 'tscfg' }, + '3' => sub { $format = 'scrambled' }, +) or exit usage; + +my $fwfile = $ARGV[0] or exit usage; + +sub set_params { + my ($rep) = @_; + if (defined $model) { + $rep->set_model($model); + } + if (defined $width) { + $rep->set_width($width); + } + if (defined $height) { + $rep->set_height($height); + } + if (defined $touches) { + $rep->set_touches($touches); + } + if (defined $flags) { + for my $flag (split /,\s*/, $flags) { + if ($flag =~ /^(no)?xflip$/) { + $rep->set_xmirrored($flag !~ /^no/); + } elsif ($flag =~ /^(no)?yflip$/) { + $rep->set_ymirrored($flag !~ /^no/); + } elsif ($flag =~ /^(no)?swap$/) { + $rep->set_swapped($flag !~ /^no/); + } elsif ($flag =~ /^(no)?track$/) { + $rep->set_tracking($flag !~ /^no/); + } else { + warn "Invalid flag: $flag"; + } + } + } +} + +if ($mode eq 'info') { + print "Loading $fwfile...\n"; + my $rep = Firmware::Silead->load($fwfile) or die "Can't load firmware $fwfile: $@"; + print "Controller model: " . $rep->model . "\n"; + print "Panel width: " . $rep->width . "\n"; + print "Panel height: " . $rep->height . "\n"; + print "Number of touch points: " . $rep->touches . "\n"; + print "X axis flipped: " . ($rep->xmirrored ? "yes" : "no") . "\n"; + print "Y axis flipped: " . ($rep->ymirrored ? "yes" : "no") . "\n"; + print "X and Y axes swapped: " . ($rep->swapped ? "yes" : "no") . "\n"; + print "Software tracking enabled: " . ($rep->tracking ? "yes" : "no") . "\n"; + my @pages = $rep->get_pages; + print "Number of pages: ". scalar(@pages) . "\n"; + print "Page list:"; + for my $page (@pages) { + printf " %02x", $page; + } + print "\n"; +} elsif ($mode eq 'set') { + print "Loading $fwfile...\n"; + my $rep = Firmware::Silead->load($fwfile) or die "Can't load firmware $fwfile: $@"; + print "Setting parameters...\n"; + set_params($rep); + print "Saving $fwfile...\n"; + $rep->save($fwfile); +} elsif ($mode eq 'convert') { + print "Loading $tscfg...\n"; + my $data; + do { + my $in = IO::File->new($tscfg, 'r') or die "Can't open $tscfg: $!"; + $in->binmode; + local $/ = undef; + $data = <$in>; + defined($data) or die "Can't load firmware: $!"; + $in->close(); + }; + + my $rep = Firmware::Silead->new(); + if ($format eq 'plain') { + $rep->import_fw($data) or die "Can't parse firmware: $@"; + } elsif ($format eq 'tscfg') { + $rep->import_tscfg($data) or die "Can't parse firmware: $@"; + } elsif ($format eq 'scrambled') { + $rep->import_scrambled($data) or die "Can't parse firmware: $@"; + } + + print "Setting parameters...\n"; + set_params($rep); + + print "Saving $fwfile...\n"; + $rep->save($fwfile) or die "Can't write firmware: $@"; +} elsif ($mode eq 'export') { + print "Loading $fwfile...\n"; + my $rep = Firmware::Silead->load($fwfile) or die "Can't load firmware $fwfile: $@"; + print "Exporting to $plain...\n"; + my $out = IO::File->new($plain, 'w') or die "Can't open $plain: $!"; + my $data = $rep->export_fw(); + $out->print($data) or die "Can't write firmware: $!"; + $out->close(); +} diff --git a/tools/scanwindrv b/tools/scanwindrv new file mode 100755 index 0000000..e6c7709 --- /dev/null +++ b/tools/scanwindrv @@ -0,0 +1,129 @@ +#!/usr/bin/perl + +use strict; +use warnings; +require 5.018; +use IO::File; + +sub usage() { + print(STDERR "Usage: scanwindrv SileadTouch.sys\n"); + print(STDERR "Scans a Windows driver for sections that look like a firmware image and\n"); + print(STDERR "writes each into sequentially numbered files: firmware_01.fw firmware_02.fw ...\n"); + -1; +} + +my $drvfile = $ARGV[0] or exit usage; + +my $driver = ''; +do { + my $in = IO::File->new($drvfile, 'r') or die "Can't open $drvfile: $!"; + $in->binmode(); + local $/; + $driver = <$in>; + defined $driver or die "Can't read firmware: $!"; + $in->close(); +}; + +my $candidate = 0; + +# find candidates +for (my $offset = 0; $offset + 8 <= length($driver); $offset++) { + + my ($cmd, $page) = unpack('(LL)<', substr($driver, $offset, 8)); + if ($cmd == 0x000000f0 && ($page & 0xffffff00) == 0x00000000) { + printf(STDERR "Found possible candidate at offset 0x%08x\n", $offset); + # possible candidate, start copying pages + + my $firmware = ''; + my $size; + FIRMWARE: for ($size = 0; $offset + $size + 129 * 8 <= length($driver);) { + + #printf(STDERR "offset=0x%08x size=%u[0x%08x]\n", $offset, $size, $size); + my ($cmd, $page) = unpack('(LL)<', substr($driver, $offset + $size, 8)); + #printf(STDERR "Page header at 0x%08x: [0x%02x, 0x%08x]\n", $offset + $size, $cmd, $page); + + # if this doesn't look like a page register - page pair, we're done + if ($cmd != 0x000000f0 || ($page & 0xffffff00) != 0x00000000) { + last FIRMWARE; + } + + for (my $index = 0; $index + 4 <= 128; $index += 4) { + my ($idx, $dat) = unpack('(LL)<', substr($driver, $offset + $size + 8 + $index * 2, 8)); + #printf(STDERR "Data at 0x%08x: [0x%02x, 0x%02x]\n", $offset + $size + 8 + $index * 2, $idx, $dat); + + # if the index is not sequential, this is probably not part of the fw and we're done + if ($idx != $index) { + #printf(STDERR "Expected index 0x%02x, got 0x%02x\n", $index, $idx); + last FIRMWARE; + } + } + + # one page complete, copy + substr($firmware, $size, 33 * 8) = substr($driver, $offset + $size, 33 * 8); + $size += 33 * 8; + } + + # check if we have enough data + if (length($firmware) > 8) { + my $fwname = sprintf("firmware_%02u.fw", $candidate); + printf(STDERR "Writing firmware to %s, size = %u bytes\n", $fwname, length($firmware)); + my $out = IO::File->new($fwname, 'w', 0666) or die "Can't open $fwname: $!"; + $out->binmode(); + print($out $firmware); + $out->close(); + $candidate++; + } else { + printf(STDERR "Not a firmware, ignoring\n"); + } + + # skip ahead + $offset += $size; + } +} + +=cut +export F=SileadTouch.sys +cat $F \ + | hexdump -e '1/1 "0x%8.8_ax "' -e '1/1 "%8._ad "' -e '8/1 "%02X ""\n"""' \ + | grep -i -E "F0 00 00 00 02 00 00 00|7C 00 00 00 .. .. .. .." \ + | grep "F0 00 00 00 02 00 00 00" -B1 \ + ; \ +echo -- \ + ; \ +cat $F \ + | hexdump -e '1/1 "0x%8.8_ax "' -e '1/1 "%8._ad "' -e '8/1 "%02X ""\n"""' \ + | grep -i -E "F0 00 00 00 02 00 00 00|7C 00 00 00 .. .. .. .." \ + | tail -n2 + +cat <)9v(lco;>cB5SO-ouGFQD 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 literal 0 HcmV?d00001 diff --git a/tools/unscramble b/tools/unscramble new file mode 100755 index 0000000..be0be5c --- /dev/null +++ b/tools/unscramble @@ -0,0 +1,52 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IO::File; + +sub usage() { + print STDERR "Usage: unscramble SileadTouch.fw gsl_ts.fw\n"; + print STDERR "Converts a scrambled Silead Windows driver firmware image into legacy binary format.\n"; + -1; +} + +my $scrfile = $ARGV[0] or exit usage; +my $fwfile = $ARGV[1] or exit usage; + +my $scrambled = ''; +do { + my $in = IO::File->new($scrfile, 'r') or die "Can't open $scrfile: $!"; + $in->binmode(); + local $/; + $scrambled = <$in>; + defined $scrambled or die "Can't read firmware: $!"; + $in->close(); +}; + +my $unscrambled = ''; +for my $char (split //, $scrambled) { + $unscrambled .= chr(ord($char) ^ 0x88); +} + +my $out = IO::File->new($fwfile, 'w') or die "Can't open $fwfile: $!"; + +my $cfg = 0; +for my $line (split /\n/, $unscrambled) { + if ($cfg and $line =~ /};/) { + $cfg = 0; + } + if ($line =~ /TS_CFG_DATA/) { + $cfg = 1; + } + if ($cfg) { + $line =~ s/\s//g; + $line = lc($line); + if ($line =~ /{0x([0-9a-f]+),0x([0-9a-f]+)},/) { + my $address = hex($1); + my $data = hex($2); + print $out pack('(LL)<', $address, $data) or die "Can't write to output: $!";; + } + } +} + +$out->close(); diff --git a/tools/untscfg b/tools/untscfg new file mode 100755 index 0000000..c629310 --- /dev/null +++ b/tools/untscfg @@ -0,0 +1,47 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IO::File; + +sub usage() { + print STDERR "Usage: untscfg GSL_TS_CFG.h gsl_ts.fw\n"; + print STDERR "Converts the GSL_TS_CFG.h from a Silead Windows driver package into legacy binary format.\n"; + -1; +} + +my $tscffile = $ARGV[0] or exit usage; +my $fwfile = $ARGV[1] or exit usage; + +my $unscrambled = ''; +do { + my $in = IO::File->new($tscffile, 'r') or die "Can't open $tscffile: $!"; + $in->binmode(); + local $/; + $unscrambled = <$in>; + defined $unscrambled or die "Can't read firmware: $!"; + $in->close(); +}; + +my $out = IO::File->new($fwfile, 'w') or die "Can't open $fwfile: $!"; + +my $cfg = 0; +for my $line (split /\n/, $unscrambled) { + if ($cfg and $line =~ /};/) { + $cfg = 0; + } + if ($line =~ /TS_CFG_DATA/) { + $cfg = 1; + } + if ($cfg) { + $line =~ s/\s//g; + $line = lc($line); + if ($line =~ /{0x([0-9a-f]+),0x([0-9a-f]+)},/) { + my $address = hex($1); + my $data = hex($2); + print $out pack('(LL)<', $address, $data) or die "Can't write to output: $!";; + } + } +} + +$out->close();